From 0536d0cde931e89d33b10228950d455dd54d8a5f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 2 Aug 2007 22:50:02 -0700 Subject: [PATCH] python: Improve support for python calling back to C++ member functions. 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 | 1 - src/python/generate.py | 24 ++++++++++++----- src/python/m5/SimObject.py | 42 +++++++++++++---------------- src/python/m5/internal/__init__.py | 1 - src/python/m5/params.py | 6 ++--- src/python/m5/simulate.py | 16 +++++------ src/python/swig/core.i | 6 +++++ src/python/swig/pyobject.hh | 20 -------------- src/python/swig/sim_object.i | 22 --------------- src/python/swig/system.i | 43 ++++++++++++++++++++++++++++++ src/sim/System.py | 2 ++ 11 files changed, 98 insertions(+), 85 deletions(-) create mode 100644 src/python/swig/system.i diff --git a/src/python/SConscript b/src/python/SConscript index f1b6a393f..b39c9ea9c 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -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') diff --git a/src/python/generate.py b/src/python/generate.py index 6a09b8106..99d0fb68c 100644 --- a/src/python/generate.py +++ b/src/python/generate.py @@ -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: diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 1e7d289e2..22c488f5d 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -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. diff --git a/src/python/m5/internal/__init__.py b/src/python/m5/internal/__init__.py index 6b7859cd7..4aa76cca7 100644 --- a/src/python/m5/internal/__init__.py +++ b/src/python/m5/internal/__init__.py @@ -30,6 +30,5 @@ import core import debug import event import random -import sim_object import stats import trace diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 3fca4e97a..df70bf469 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -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 diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index ba9fb7899..c703664d4 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -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" diff --git a/src/python/swig/core.i b/src/python/swig/core.i index 3edfa4c7e..8960fb228 100644 --- a/src/python/swig/core.i +++ b/src/python/swig/core.i @@ -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 diff --git a/src/python/swig/pyobject.hh b/src/python/swig/pyobject.hh index da609e07e..8e3a96994 100644 --- a/src/python/swig/pyobject.hh +++ b/src/python/swig/pyobject.hh @@ -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(obj); - - if (ptr == NULL) - warn("Casting to BaseCPU pointer failed"); - return ptr; -} - -inline System * -convertToSystemPtr(SimObject *obj) -{ - System *ptr = dynamic_cast(obj); - - if (ptr == NULL) - warn("Casting to System pointer failed"); - return ptr; -} - inline void initAll() { diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i index ebd019ca3..7f71550c6 100644 --- a/src/python/swig/sim_object.i +++ b/src/python/swig/sim_object.i @@ -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 index 000000000..a95101bf7 --- /dev/null +++ b/src/python/swig/system.i @@ -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); +}; + diff --git a/src/sim/System.py b/src/sim/System.py index 3f4c57f0c..5712a5c03 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -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']: