From 47ef97b9caad0a72751523855d145dcd96fc5738 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Thu, 9 Sep 2010 14:26:29 -0700 Subject: [PATCH] scons: Stop building the big monolithic swigged params module kill params.i and create a separate .i for each object (param, enums, etc.) --- src/SConscript | 130 +++++++++------------- src/python/SConscript | 5 + src/python/m5/SimObject.py | 49 +++++--- src/python/m5/internal/enums/__init__.py | 36 ++++++ src/python/m5/internal/params/__init__.py | 36 ++++++ src/python/m5/internal/swig/__init__.py | 27 +++++ src/python/m5/objects/params.py | 29 +++++ src/python/m5/params.py | 62 ++++++++--- src/python/swig/inet.i | 3 + src/python/swig/range.i | 12 +- src/python/swig/sim_object.i | 3 +- src/python/swig/system.i | 7 +- 12 files changed, 281 insertions(+), 118 deletions(-) create mode 100644 src/python/m5/internal/enums/__init__.py create mode 100644 src/python/m5/internal/params/__init__.py create mode 100644 src/python/m5/internal/swig/__init__.py create mode 100644 src/python/m5/objects/params.py diff --git a/src/SConscript b/src/SConscript index f7794658b..5aa534a80 100644 --- a/src/SConscript +++ b/src/SConscript @@ -399,7 +399,7 @@ for name,obj in sorted(sim_objects.iteritems()): # calculate extra dependencies # module_depends = ["m5", "m5.SimObject", "m5.params"] -depends = [ PySource.modules[dep].tnode for dep in module_depends ] +depends = [ PySource.modules[dep].snode for dep in module_depends ] ######################################################################## # @@ -470,6 +470,7 @@ def createSwigParam(target, source, env): param = all_params[name] code = code_formatter() + code('%module(package="m5.internal.swig") ${name}_$0', param.file_ext) param.swig_decl(code) code.write(target[0].abspath) @@ -493,6 +494,24 @@ def createEnumParam(target, source, env): obj.cxx_decl(code) code.write(target[0].abspath) +def createEnumSwig(target, source, env): + assert len(target) == 1 and len(source) == 1 + + name = str(source[0].get_contents()) + obj = all_enums[name] + + code = code_formatter() + code('''\ +%module(package="m5.internal.enums") $name + +%{ +#include "enums/$name.hh" +%} + +%include "enums/$name.hh" +''') + code.write(target[0].abspath) + # Generate all of the SimObject param struct header files params_hh_files = [] for name,simobj in sorted(sim_objects.iteritems()): @@ -511,6 +530,7 @@ for name,param in all_params.iteritems(): params_i_files.append(i_file) env.Command(i_file, Value(name), createSwigParam) env.Depends(i_file, depends) + SwigSource('m5.internal.swig', i_file) # Generate all enum header files for name,enum in sorted(all_enums.iteritems()): @@ -526,95 +546,49 @@ for name,enum in sorted(all_enums.iteritems()): env.Command(hh_file, Value(name), createEnumParam) env.Depends(hh_file, depends + extra_deps) -# Build the big monolithic swigged params module (wraps all SimObject -# param structs and enum structs) -def buildParams(target, source, env): - names = [ s.get_contents() for s in source ] - objs = [ sim_objects[name] for name in names ] + i_file = File('enums/%s.i' % name) + env.Command(i_file, Value(name), createEnumSwig) + env.Depends(i_file, depends + extra_deps) + SwigSource('m5.internal.enums', i_file) - ordered_objs = [] - obj_seen = set() - def order_obj(obj): - name = str(obj) - if name in obj_seen: - return - - obj_seen.add(name) - if str(obj) != 'SimObject': - order_obj(obj.__bases__[0]) - - ordered_objs.append(obj) - - for obj in objs: - order_obj(obj) +def buildParam(target, source, env): + name = source[0].get_contents() + obj = sim_objects[name] + class_path = obj.cxx_class.split('::') + classname = class_path[-1] + namespaces = class_path[:-1] + params = obj._params.local.values() code = code_formatter() - code('%module params') + code('%module(package="m5.internal.params") $name') + code() code('%{') - for obj in ordered_objs: - code('#include "params/$obj.hh"') + code('#include "params/$obj.hh"') + for param in params: + param.cxx_predecls(code) code('%}') + code() - for obj in ordered_objs: - params = obj._params.local.values() - for param in params: - param.swig_predecls(code) - - enums = set() - for obj in ordered_objs: - params = obj._params.local.values() - for param in params: - ptype = param.ptype - if issubclass(ptype, m5.params.Enum) and ptype not in enums: - enums.add(ptype) - code('%include "enums/$0.hh"', ptype.__name__) - - for obj in ordered_objs: - obj.swig_objdecls(code) - code() - - for obj in ordered_objs: - continue - if obj.swig_objdecls: - obj.swig_objdecls(code) - continue - - class_path = obj.cxx_class.split('::') - classname = class_path[-1] - namespaces = class_path[:-1] - - for ns in namespaces: - code('namespace $ns {') - - if namespaces: - code('// avoid name conflicts') - sep_string = '_COLONS_' - flat_name = sep_string.join(class_path) - code('%rename($flat_name) $classname;') - - code('// stop swig from creating/wrapping default ctor/dtor') - code('%nodefault $classname;') - if obj._base: - code('class $classname : public ${{obj._base.cxx_class}} {};') - else: - code('class $classname {};') + for param in params: + param.swig_predecls(code) - for ns in reversed(namespaces): - code('/* namespace $ns */ }') - code() + code() + if obj._base: + code('%import "params/${{obj._base}}.i"') + code() + obj.swig_objdecls(code) + code() - code('%include "src/sim/sim_object_params.hh"') - for obj in ordered_objs: - code('%include "params/$obj.hh"') + code('%include "params/$obj.hh"') code.write(target[0].abspath) -params_file = File('params/params.i') -names = sorted(sim_objects.keys()) -env.Command(params_file, map(Value, names), buildParams) -env.Depends(params_file, params_hh_files + params_i_files + depends) -SwigSource('m5.objects', params_file) +for name in sim_objects.iterkeys(): + params_file = File('params/%s.i' % name) + env.Command(params_file, Value(name), buildParam) + env.Depends(params_file, depends) + SwigSource('m5.internal.params', params_file) # Generate the main swig init file def makeEmbeddedSwigInit(target, source, env): diff --git a/src/python/SConscript b/src/python/SConscript index e68058f40..d995d0091 100644 --- a/src/python/SConscript +++ b/src/python/SConscript @@ -50,6 +50,7 @@ PySource('m5', 'm5/stats.py') PySource('m5', 'm5/ticks.py') PySource('m5', 'm5/trace.py') PySource('m5.objects', 'm5/objects/__init__.py') +PySource('m5.objects', 'm5/objects/params.py') PySource('m5.util', 'm5/util/__init__.py') PySource('m5.util', 'm5/util/attrdict.py') PySource('m5.util', 'm5/util/code_formatter.py') @@ -65,6 +66,10 @@ 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/range.i') SwigSource('m5.internal', 'swig/stats.i') SwigSource('m5.internal', 'swig/trace.i') PySource('m5.internal', 'm5/internal/__init__.py') +PySource('m5.internal.enums', 'm5/internal/enums/__init__.py') +PySource('m5.internal.params', 'm5/internal/params/__init__.py') +PySource('m5.internal.swig', 'm5/internal/swig/__init__.py') diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index d26a99051..e370bf8b5 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -98,15 +98,10 @@ allClasses = {} instanceDict = {} def default_cxx_predecls(cls, code): - '''A forward class declaration is sufficient since we are - just declaring a pointer.''' + code('#include "params/$cls.hh"') - class_path = cls._value_dict['cxx_class'].split('::') - for ns in class_path[:-1]: - code('namespace $ns {') - code('class $0;', class_path[-1]) - for ns in reversed(class_path[:-1]): - code('/* namespace $ns */ }') +def default_swig_predecls(cls, code): + code('%import "params/$cls.i"') def default_swig_objdecls(cls, code): class_path = cls.cxx_class.split('::') @@ -233,7 +228,8 @@ class MetaSimObject(type): setattr(cls, 'cxx_predecls', m) if 'swig_predecls' not in cls.__dict__: - setattr(cls, 'swig_predecls', getattr(cls, 'cxx_predecls')) + m = MethodType(default_swig_predecls, cls, MetaSimObject) + setattr(cls, 'swig_predecls', m) if 'swig_objdecls' not in cls.__dict__: m = MethodType(default_swig_objdecls, cls, MetaSimObject) @@ -346,6 +342,15 @@ class MetaSimObject(type): "Class %s has no parameter \'%s\'" % (cls.__name__, attr) def __getattr__(cls, attr): + if attr == 'cxx_class_path': + return cls.cxx_class.split('::') + + if attr == 'cxx_class_name': + return cls.cxx_class_path[-1] + + if attr == 'cxx_namespaces': + return cls.cxx_class_path[:-1] + if cls._values.has_key(attr): return cls._values[attr] @@ -359,12 +364,6 @@ class MetaSimObject(type): return cls.__name__ def cxx_decl(cls, code): - code('''\ -#ifndef __PARAMS__${cls}__ -#define __PARAMS__${cls}__ - -''') - # 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 @@ -377,8 +376,23 @@ class MetaSimObject(type): print params raise - # get all predeclarations - cls.cxx_predecls(code) + class_path = cls._value_dict['cxx_class'].split('::') + + code('''\ +#ifndef __PARAMS__${cls}__ +#define __PARAMS__${cls}__ + +''') + + # A forward class declaration is sufficient since we are just + # declaring a pointer. + for ns in class_path[:-1]: + code('namespace $ns {') + code('class $0;', class_path[-1]) + for ns in reversed(class_path[:-1]): + code('/* namespace $ns */ }') + code() + for param in params: param.cxx_predecls(code) code() @@ -394,7 +408,6 @@ class MetaSimObject(type): cls.cxx_struct(code, cls._base, params) - # close #ifndef __PARAMS__* guard code() code('#endif // __PARAMS__${cls}__') return code diff --git a/src/python/m5/internal/enums/__init__.py b/src/python/m5/internal/enums/__init__.py new file mode 100644 index 000000000..95bd61395 --- /dev/null +++ b/src/python/m5/internal/enums/__init__.py @@ -0,0 +1,36 @@ +# Copyright (c) 2010 The Hewlett-Packard Development Company +# 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 + +try: + modules = __loader__.modules +except NameError: + modules = { } + +for module in modules.iterkeys(): + if module.startswith('m5.internal.enums.'): + exec "from %s import *" % module diff --git a/src/python/m5/internal/params/__init__.py b/src/python/m5/internal/params/__init__.py new file mode 100644 index 000000000..d424298ab --- /dev/null +++ b/src/python/m5/internal/params/__init__.py @@ -0,0 +1,36 @@ +# Copyright (c) 2010 The Hewlett-Packard Development Company +# 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 + +try: + modules = __loader__.modules +except NameError: + modules = { } + +for module in modules.iterkeys(): + if module.startswith('m5.internal.params.'): + exec "from %s import *" % module diff --git a/src/python/m5/internal/swig/__init__.py b/src/python/m5/internal/swig/__init__.py new file mode 100644 index 000000000..ac299f99c --- /dev/null +++ b/src/python/m5/internal/swig/__init__.py @@ -0,0 +1,27 @@ +# Copyright (c) 2010 The Hewlett-Packard Development Company +# 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 diff --git a/src/python/m5/objects/params.py b/src/python/m5/objects/params.py new file mode 100644 index 000000000..4bae9fa3b --- /dev/null +++ b/src/python/m5/objects/params.py @@ -0,0 +1,29 @@ +# Copyright (c) 2010 The Hewlett-Packard Development Company +# 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 + +from m5.internal.params import * diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 00bba636b..0143fe2e7 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -241,18 +241,43 @@ class VectorParamDesc(ParamDesc): return VectorParamValue(tmp_list) def swig_predecls(self, code): - code('%include "${{self.ptype_str}}_vptype.i"') + code('%import "${{self.ptype_str}}_vptype.i"') def swig_decl(self, code): - cxx_type = re.sub('std::', '', self.ptype.cxx_type) - code('%include "std_vector.i"') + code('%{') + self.ptype.cxx_predecls(code) + code('%}') + code() self.ptype.swig_predecls(code) + code() + code('%include "std_vector.i"') + code() + + ptype = self.ptype_str + cxx_type = self.ptype.cxx_type + code('''\ -namespace std { -%template(vector_${{self.ptype_str}}) vector< $cxx_type >; +%typemap(in) std::vector< $cxx_type >::value_type { + if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { + if (SWIG_ConvertPtr($$input, (void **)&$$1, + $$descriptor($cxx_type), 0) == -1) { + return NULL; + } + } +} + +%typemap(in) std::vector< $cxx_type >::value_type * { + if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { + if (SWIG_ConvertPtr($$input, (void **)&$$1, + $$descriptor($cxx_type *), 0) == -1) { + return NULL; + } + } } ''') + code('%template(vector_$ptype) std::vector< $cxx_type >;') + def cxx_predecls(self, code): code('#include ') self.ptype.cxx_predecls(code) @@ -537,18 +562,19 @@ class Range(ParamValue): @classmethod def cxx_predecls(cls, code): - code('#include "base/range.hh"') cls.type.cxx_predecls(code) - -class AddrRange(Range): - type = Addr + code('#include "base/range.hh"') @classmethod def swig_predecls(cls, code): - code('%include "python/swig/range.i"') + cls.type.swig_predecls(code) + code('%import "python/swig/range.i"') + +class AddrRange(Range): + type = Addr def getValue(self): - from m5.objects.params import AddrRange + from m5.internal.range import AddrRange value = AddrRange() value.start = long(self.first) @@ -558,12 +584,8 @@ class AddrRange(Range): class TickRange(Range): type = Tick - @classmethod - def swig_predecls(cls, code): - code('%include "python/swig/range.i"') - def getValue(self): - from m5.objects.params import TickRange + from m5.internal.range import TickRange value = TickRange() value.start = long(self.first) @@ -838,6 +860,14 @@ class Enum(ParamValue): % (value, self.vals) self.value = value + @classmethod + def cxx_predecls(cls, code): + code('#include "enums/$0.hh"', cls.__name__) + + @classmethod + def swig_predecls(cls, code): + code('%import "enums/$0.i"', cls.__name__) + def getValue(self): return int(self.map[self.value]) diff --git a/src/python/swig/inet.i b/src/python/swig/inet.i index 96b4b85d0..e92b44597 100644 --- a/src/python/swig/inet.i +++ b/src/python/swig/inet.i @@ -32,6 +32,9 @@ #include "base/inet.hh" %} +%import "stdint.i" +%import "std_string.i" + namespace Net { struct EthAddr { diff --git a/src/python/swig/range.i b/src/python/swig/range.i index 659bde8d7..f0cf43be4 100644 --- a/src/python/swig/range.i +++ b/src/python/swig/range.i @@ -28,10 +28,18 @@ * Authors: Nathan Binkert */ -%rename(assign) *::operator=; +%module(package="m5.internal") range -%include "base/range.hh" +%{ +#include "base/range.hh" +#include "base/types.hh" +%} + +%include "stdint.i" %include "base/types.hh" +%rename(assign) *::operator=; +%include "base/range.hh" + %template(AddrRange) Range; %template(TickRange) Range; diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i index af9afd057..76d312417 100644 --- a/src/python/swig/sim_object.i +++ b/src/python/swig/sim_object.i @@ -28,8 +28,6 @@ * Authors: Nathan Binkert */ -%module sim_object - %{ #include "python/swig/pyobject.hh" %} @@ -39,6 +37,7 @@ %include "std_string.i" %include "base/types.hh" +%include "sim/sim_object_params.hh" class BaseCPU; diff --git a/src/python/swig/system.i b/src/python/swig/system.i index a95101bf7..5e36b4ac5 100644 --- a/src/python/swig/system.i +++ b/src/python/swig/system.i @@ -28,9 +28,12 @@ * Authors: Nathan Binkert */ -%module sim_object +%{ +#include "sim/system.hh" +%} -%include "enums/MemoryMode.hh" +%import "python/swig/sim_object.i" +%import "enums/MemoryMode.hh" class System : public SimObject { -- 2.30.2