python: Improve support for python calling back to C++ member functions.
authorNathan Binkert <nate@binkert.org>
Fri, 3 Aug 2007 05:50:02 +0000 (22:50 -0700)
committerNathan Binkert <nate@binkert.org>
Fri, 3 Aug 2007 05:50:02 +0000 (22:50 -0700)
Add support for declaring SimObjects to swig so their members can be wrapped.
Make sim_object.i only contain declarations for SimObject.
Create system.i to contain declarations for System.
Update python code to properly call the C++ given the new changes.

--HG--
extra : convert_revision : 82076ee69e8122d56e91b92d6767e356baae420a

src/python/SConscript
src/python/generate.py
src/python/m5/SimObject.py
src/python/m5/internal/__init__.py
src/python/m5/params.py
src/python/m5/simulate.py
src/python/swig/core.i
src/python/swig/pyobject.hh
src/python/swig/sim_object.i
src/python/swig/system.i [new file with mode: 0644]
src/sim/System.py

index f1b6a393fb9c361f3b4a1b3f9a04488cfab66473..b39c9ea9caa5f88177d460853c17156196af3615 100644 (file)
@@ -53,7 +53,6 @@ SwigSource('m5.internal', 'swig/core.i')
 SwigSource('m5.internal', 'swig/debug.i')
 SwigSource('m5.internal', 'swig/event.i')
 SwigSource('m5.internal', 'swig/random.i')
-SwigSource('m5.internal', 'swig/sim_object.i')
 SwigSource('m5.internal', 'swig/stats.i')
 SwigSource('m5.internal', 'swig/trace.i')
 PySource('m5.internal', 'm5/internal/__init__.py')
index 6a09b81067291c597514db7d0f54a406e489ef23..99d0fb68c4b9c09929ae4dc68da24aa0ec116511 100644 (file)
@@ -274,17 +274,29 @@ class Generate(object):
         print >>out
 
         for obj in ordered_objs:
-            code = 'class %s ' % obj.cxx_class
-            if str(obj) != 'SimObject':
-                code += ': public %s ' % obj.__bases__[0]
-            code += '{};'
+            if obj.swig_objdecls:
+                for decl in obj.swig_objdecls:
+                    print >>out, decl
+                continue
+
+            code = ''
+            base = obj.get_base()
+
+            code += '// stop swig from creating/wrapping default ctor/dtor\n'
+            code += '%%nodefault %s;\n' % obj.cxx_class
+            code += 'class %s ' % obj.cxx_class
+            if base:
+                code += ': public %s' % base
+            code += ' {};\n'
 
             klass = obj.cxx_class;
             if hasattr(obj, 'cxx_namespace'):
-                code = 'namespace %s { %s }' % (obj.cxx_namespace, code)
+                new_code = 'namespace %s {\n' % obj.cxx_namespace
+                new_code += code
+                new_code += '}\n'
+                code = new_code
                 klass = '%s::%s' % (obj.cxx_namespace, klass)
 
-            print >>out, '%%ignore %s;' % klass
             print >>out, code
 
         for obj in ordered_objs:
index 1e7d289e2d5e02f179b25a2aa01c6d5dbc0aa76f..22c488f5d834ed448b8d03ed9af935931fdf637f 100644 (file)
@@ -128,6 +128,7 @@ class MetaSimObject(type):
                       'cxx_class' : types.StringType,
                       'cxx_type' : types.StringType,
                       'cxx_predecls' : types.ListType,
+                      'swig_objdecls' : types.ListType,
                       'swig_predecls' : types.ListType,
                       'type' : types.StringType }
     # Attributes that can be set any time
@@ -225,6 +226,9 @@ class MetaSimObject(type):
                 cls._value_dict['swig_predecls'] = \
                     cls._value_dict['cxx_predecls']
 
+        if 'swig_objdecls' not in cls._value_dict:
+            cls._value_dict['swig_objdecls'] = []
+
         # Now process the _value_dict items.  They could be defining
         # new (or overriding existing) parameters or ports, setting
         # class keywords (e.g., 'abstract'), or setting parameter
@@ -345,12 +349,13 @@ class MetaSimObject(type):
     def __str__(cls):
         return cls.__name__
 
-    def cxx_decl(cls):
-        if str(cls) != 'SimObject':
-            base = cls.__bases__[0].type
-        else:
-            base = None
+    def get_base(cls):
+        if str(cls) == 'SimObject':
+            return None
+
+        return  cls.__bases__[0].type
 
+    def cxx_decl(cls):
         code = "#ifndef __PARAMS__%s\n" % cls
         code += "#define __PARAMS__%s\n\n" % cls
 
@@ -380,6 +385,7 @@ class MetaSimObject(type):
         code += "\n".join(predecls2)
         code += "\n\n";
 
+        base = cls.get_base()
         if base:
             code += '#include "params/%s.hh"\n\n' % base
 
@@ -408,11 +414,7 @@ class MetaSimObject(type):
         return code
 
     def cxx_type_decl(cls):
-        if str(cls) != 'SimObject':
-            base = cls.__bases__[0]
-        else:
-            base = None
-
+        base = cls.get_base()
         code = ''
 
         if base:
@@ -427,17 +429,14 @@ class MetaSimObject(type):
         return code
 
     def swig_decl(cls):
+        base = cls.get_base()
+
         code = '%%module %s\n' % cls
 
         code += '%{\n'
         code += '#include "params/%s.hh"\n' % cls
         code += '%}\n\n'
 
-        if str(cls) != 'SimObject':
-            base = cls.__bases__[0]
-        else:
-            base = None
-
         # The 'dict' attribute restricts us to the params declared in
         # the object itself, not including inherited params (which
         # will also be inherited from the base class's param struct
@@ -483,6 +482,7 @@ class SimObject(object):
     abstract = True
 
     name = Param.String("Object name")
+    swig_objdecls = [ '%include "python/swig/sim_object.i"' ]
 
     # Initialize new instance.  For objects with SimObject-valued
     # children, we need to recursively clone the classes represented
@@ -792,7 +792,6 @@ class SimObject(object):
     # necessary to construct it.  Does *not* recursively create
     # children.
     def getCCObject(self):
-        import internal
         params = self.getCCParams()
         if not self._ccObject:
             self._ccObject = -1 # flag to catch cycles in recursion
@@ -840,24 +839,19 @@ class SimObject(object):
         if not isinstance(self, m5.objects.System):
             return None
 
-        system_ptr = internal.sim_object.convertToSystemPtr(self._ccObject)
-        return system_ptr.getMemoryMode()
+        return self._ccObject.getMemoryMode()
 
     def changeTiming(self, mode):
-        import internal
         if isinstance(self, m5.objects.System):
             # i don't know if there's a better way to do this - calling
             # setMemoryMode directly from self._ccObject results in calling
             # SimObject::setMemoryMode, not the System::setMemoryMode
-            system_ptr = internal.sim_object.convertToSystemPtr(self._ccObject)
-            system_ptr.setMemoryMode(mode)
+            self._ccObject.setMemoryMode(mode)
         for child in self._children.itervalues():
             child.changeTiming(mode)
 
     def takeOverFrom(self, old_cpu):
-        import internal
-        cpu_ptr = internal.sim_object.convertToBaseCPUPtr(old_cpu._ccObject)
-        self._ccObject.takeOverFrom(cpu_ptr)
+        self._ccObject.takeOverFrom(old_cpu._ccObject)
 
     # generate output file for 'dot' to display as a pretty graph.
     # this code is currently broken.
index 6b7859cd71ac47c77507cfc33c368b1c50889227..4aa76cca7c9538a0df7b57a8d8098413131a4a30 100644 (file)
@@ -30,6 +30,5 @@ import core
 import debug
 import event
 import random
-import sim_object
 import stats
 import trace
index 3fca4e97adbde1421c01daac152946f2b45166e3..df70bf4693bfe60e32528fe4d181d3e58920ac3f 100644 (file)
@@ -1025,13 +1025,13 @@ class PortRef(object):
 
     # Call C++ to create corresponding port connection between C++ objects
     def ccConnect(self):
-        import internal
+        from m5.objects.params import connectPorts
 
         if self.ccConnected: # already done this
             return
         peer = self.peer
-        internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name,
-            self.index, peer.simobj.getCCObject(), peer.name, peer.index)
+        connectPorts(self.simobj.getCCObject(), self.name, self.index,
+                     peer.simobj.getCCObject(), peer.name, peer.index)
         self.ccConnected = True
         peer.ccConnected = True
 
index ba9fb789903c1ff0f159c720f95a53e4e22b23d8..c703664d491a99c7ff279c86b79b4fc42ed19f52 100644 (file)
@@ -59,10 +59,10 @@ def instantiate(root):
     root.connectPorts()
 
     # Do a second pass to finish initializing the sim objects
-    internal.sim_object.initAll()
+    internal.core.initAll()
 
     # Do a third pass to initialize statistics
-    internal.sim_object.regAllStats()
+    internal.core.regAllStats()
 
     # Check to make sure that the stats package is properly initialized
     internal.stats.check()
@@ -136,32 +136,32 @@ def checkpoint(root, dir):
         raise TypeError, "Checkpoint must be called on a root object."
     doDrain(root)
     print "Writing checkpoint"
-    internal.sim_object.serializeAll(dir)
+    internal.core.serializeAll(dir)
     resume(root)
 
 def restoreCheckpoint(root, dir):
     print "Restoring from checkpoint"
-    internal.sim_object.unserializeAll(dir)
+    internal.core.unserializeAll(dir)
     need_resume.append(root)
 
 def changeToAtomic(system):
     if not isinstance(system, (objects.Root, objects.System)):
         raise TypeError, "Parameter of type '%s'.  Must be type %s or %s." % \
               (type(system), objects.Root, objects.System)
-    if system.getMemoryMode() != internal.sim_object.SimObject.Atomic:
+    if system.getMemoryMode() != objects.params.SimObject.Atomic:
         doDrain(system)
         print "Changing memory mode to atomic"
-        system.changeTiming(internal.sim_object.SimObject.Atomic)
+        system.changeTiming(objects.params.SimObject.Atomic)
 
 def changeToTiming(system):
     if not isinstance(system, (objects.Root, objects.System)):
         raise TypeError, "Parameter of type '%s'.  Must be type %s or %s." % \
               (type(system), objects.Root, objects.System)
 
-    if system.getMemoryMode() != internal.sim_object.SimObject.Timing:
+    if system.getMemoryMode() != objects.params.SimObject.Timing:
         doDrain(system)
         print "Changing memory mode to timing"
-        system.changeTiming(internal.sim_object.SimObject.Timing)
+        system.changeTiming(objects.params.SimObject.Timing)
 
 def switchCpus(cpuList):
     print "switching cpus"
index 3edfa4c7edae4a80f8dc62ac514b23382a47de97..8960fb228418747713e07e89b474b9e195d31bd1 100644 (file)
@@ -58,6 +58,12 @@ void setClockFrequency(Tick ticksPerSecond);
 %immutable curTick;
 Tick curTick;
 
+void serializeAll(const std::string &cpt_dir);
+void unserializeAll(const std::string &cpt_dir);
+
+void initAll();
+void regAllStats();
+
 %wrapper %{
 // fix up module name to reflect the fact that it's inside the m5 package
 #undef SWIG_name
index da609e07e9bd1358400b2a23baea80adb8ce2ce9..8e3a969947c2fc020c5f46c727cb8e4ec5760055 100644 (file)
@@ -47,26 +47,6 @@ void loadIniFile(PyObject *_resolveFunc);
 int connectPorts(SimObject *o1, const std::string &name1, int i1,
     SimObject *o2, const std::string &name2, int i2);
 
-inline BaseCPU *
-convertToBaseCPUPtr(SimObject *obj)
-{
-    BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj);
-
-    if (ptr == NULL)
-        warn("Casting to BaseCPU pointer failed");
-    return ptr;
-}
-
-inline System *
-convertToSystemPtr(SimObject *obj)
-{
-    System *ptr = dynamic_cast<System *>(obj);
-
-    if (ptr == NULL)
-        warn("Casting to System pointer failed");
-    return ptr;
-}
-
 inline void
 initAll()
 {
index ebd019ca3ce9424dba5d7759f7806b370c0339da..7f71550c6c4df0375f6a695009a17110689a50ac 100644 (file)
@@ -31,7 +31,6 @@
 %module sim_object
 
 %{
-#include "enums/MemoryMode.hh"
 #include "python/swig/pyobject.hh"
 %}
 
@@ -57,31 +56,10 @@ class SimObject {
     SimObject(const std::string &_name);
 };
 
-class System {
-    private:
-      System();
-    public:
-      Enums::MemoryMode getMemoryMode();
-      void setMemoryMode(Enums::MemoryMode mode);
-};
-
 int connectPorts(SimObject *o1, const std::string &name1, int i1,
                  SimObject *o2, const std::string &name2, int i2);
 
-BaseCPU *convertToBaseCPUPtr(SimObject *obj);
-System *convertToSystemPtr(SimObject *obj);
-
-void serializeAll(const std::string &cpt_dir);
-void unserializeAll(const std::string &cpt_dir);
-
-void initAll();
-void regAllStats();
-
 %wrapper %{
-// fix up module name to reflect the fact that it's inside the m5 package
-#undef SWIG_name
-#define SWIG_name "m5.internal._sim_object"
-
 // Convert a pointer to the Python object that SWIG wraps around a
 // C++ SimObject pointer back to the actual C++ pointer.
 SimObject *
diff --git a/src/python/swig/system.i b/src/python/swig/system.i
new file mode 100644 (file)
index 0000000..a95101b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+%module sim_object
+
+%include "enums/MemoryMode.hh"
+
+class System : public SimObject
+{
+    private:
+      System();
+    public:
+      Enums::MemoryMode getMemoryMode();
+      void setMemoryMode(Enums::MemoryMode mode);
+};
+
index 3f4c57f0c96f9717e9dccea4440d9dcad967091d..5712a5c03d24a4d7caa4aac2d004e41821a1e63f 100644 (file)
@@ -36,6 +36,8 @@ class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
 
 class System(SimObject):
     type = 'System'
+    swig_objdecls = [ '%include "python/swig/system.i"' ]
+
     physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
     mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
     if build_env['FULL_SYSTEM']: