sim: make Python Root object a singleton
authorSteve Reinhardt <steve.reinhardt@amd.com>
Tue, 17 Aug 2010 12:06:22 +0000 (05:06 -0700)
committerSteve Reinhardt <steve.reinhardt@amd.com>
Tue, 17 Aug 2010 12:06:22 +0000 (05:06 -0700)
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.

configs/common/Simulation.py
configs/example/memtest-ruby.py
configs/example/memtest.py
configs/example/rubytest.py
configs/splash2/cluster.py
configs/splash2/run.py
src/python/m5/SimObject.py
src/python/m5/simulate.py
src/sim/Root.py
tests/run.py

index 905e435d38acdc0479e3847cba91a91109835c99..0393b0dfa34d4ffd6bec8bdb31cb245602f86872 100644 (file)
@@ -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"))
 
index 709d31844859690d122714f9c9bb591d0f1e7316..16d86f0bc0d332fb3bb892d89e9ee4617e30fc57 100644 (file)
@@ -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)
index d4497092bf27dd87b1bec01e99affbccf4b4f6af..0713dd241de6be948f172e5d5b8ba44fc624684a 100644 (file)
@@ -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)
index 13b862756616b626ee3ee5ef582d0f889a64260d..c9cf0aba4650c5df664ee5f1052668795c4f32da 100644 (file)
@@ -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)
index 45c9ede82bd5d04818ef8b9c61b5eedf49ffaff7..77591dc6222e7614a359da264a45fed9e1ffdb82 100644 (file)
@@ -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:
index 95ec790ba9586da653941a604faff0fdb4903ce5..24faade17a180f7517d3acaaa99f4729e7e643e2 100644 (file)
@@ -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:
index 3b84d60007fab867a6404ab9a2fd337c55731c53..8e14b63d29bb1ac3a0f5149c5ca6c3de16f338ad 100644 (file)
@@ -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
index e43f90173e46291748f541be585e8a868ef2f7e6..2db5c6952865a8abf1b1a87f5e41544f261b8065 100644 (file)
@@ -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)
index fff998e0dea8b2fbf8c8ea85111b539e24836d0f..c7404a11f6d20007ac42f47fbd2888968bf51afd 100644 (file)
 
 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")
index 1e58f02832b28d044935685ea66d2d963bc5ba72..f4105fb411bc58e623f9d15b092cde91ff95f151 100644 (file)
@@ -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)