Deleted Added
sdiff udiff text old ( 11802:be62996c95d1 ) new ( 11988:665cd5f8b52b )
full compact
1# Copyright (c) 2017 ARM Limited
2# All rights reserved.
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license
9# terms below provided that you ensure that this notice is replicated

--- 26 unchanged lines hidden (view full) ---

36# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40#
41# Authors: Steve Reinhardt
42# Nathan Binkert
43# Andreas Hansson
44# Andreas Sandberg
45
46import sys
47from types import FunctionType, MethodType, ModuleType
48from functools import wraps
49import inspect
50
51import m5
52from m5.util import *
53from m5.util.pybind import *
54
55# Have to import params up top since Param is referenced on initial
56# load (when SimObject class references Param to create a class
57# variable, the 'name' param)...
58from m5.params import *
59# There are a few things we need that aren't in params.__all__ since
60# normal users don't need them
61from m5.params import ParamDesc, VectorParamDesc, \

--- 205 unchanged lines hidden (view full) ---

267 code()
268 code('void ${member_prefix}setName(const std::string &name_)'
269 '${end_of_decl}')
270
271 if not is_header:
272 code('{')
273 code.indent()
274 code('this->name = name_;')
275 code.dedent()
276 code('}')
277
278 if is_header:
279 code('const std::string &${member_prefix}getName()')
280 code('{ return this->name; }')
281
282 code()

--- 108 unchanged lines hidden (view full) ---

391 code('};')
392
393# The metaclass for SimObject. This class controls how new classes
394# that derive from SimObject are instantiated, and provides inherited
395# class behavior (just like a class controls how instances of that
396# class are instantiated, and provides inherited instance behavior).
397class MetaSimObject(type):
398 # Attributes that can be set only at initialization time
399 init_keywords = {
400 'abstract' : bool,
401 'cxx_class' : str,
402 'cxx_type' : str,
403 'cxx_header' : str,
404 'type' : str,
405 'cxx_bases' : list,
406 'cxx_exports' : list,
407 'cxx_param_exports' : list,
408 }
409 # Attributes that can be set any time
410 keywords = { 'check' : FunctionType }
411
412 # __new__ is called before __init__, and is where the statements
413 # in the body of the class definition get loaded into the class's
414 # __dict__. We intercept this to filter out parameter & port assignments
415 # and only allow "private" attributes to be passed to the base
416 # __new__ (starting with underscore).
417 def __new__(mcls, name, bases, dict):
418 assert name not in allClasses, "SimObject %s already present" % name
419
420 # Copy "private" attributes, functions, and classes to the
421 # official dict. Everything else goes in _init_dict to be
422 # filtered in __init__.
423 cls_dict = {}
424 value_dict = {}
425 cxx_exports = []
426 for key,val in dict.items():
427 try:
428 cxx_exports.append(getattr(val, "__pybind"))
429 except AttributeError:
430 pass
431
432 if public_value(key, val):
433 cls_dict[key] = val
434 else:
435 # must be a param/port setting
436 value_dict[key] = val
437 if 'abstract' not in value_dict:
438 value_dict['abstract'] = False
439 if 'cxx_bases' not in value_dict:
440 value_dict['cxx_bases'] = []
441 if 'cxx_exports' not in value_dict:
442 value_dict['cxx_exports'] = cxx_exports
443 else:
444 value_dict['cxx_exports'] += cxx_exports
445 if 'cxx_param_exports' not in value_dict:
446 value_dict['cxx_param_exports'] = []
447 cls_dict['_value_dict'] = value_dict
448 cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict)
449 if 'type' in value_dict:
450 allClasses[name] = cls
451 return cls
452
453 # subclass initialization
454 def __init__(cls, name, bases, dict):

--- 213 unchanged lines hidden (view full) ---

668
669 def __str__(cls):
670 return cls.__name__
671
672 # See ParamValue.cxx_predecls for description.
673 def cxx_predecls(cls, code):
674 code('#include "params/$cls.hh"')
675
676 def pybind_predecls(cls, code):
677 code('#include "${{cls.cxx_header}}"')
678
679 # See ParamValue.swig_predecls for description.
680 def swig_predecls(cls, code):
681 code('%import "python/_m5/param_$cls.i"')
682
683 # Hook for exporting additional C++ methods to Python via SWIG.
684 # Default is none, override using @classmethod in class definition.
685 def export_methods(cls, code):
686 pass

--- 85 unchanged lines hidden (view full) ---

772 code('};')
773
774 for ns in reversed(namespaces):
775 code('} // namespace $ns')
776
777 code()
778 code('%include "params/$cls.hh"')
779
780 def pybind_decl(cls, code):
781 class_path = cls.cxx_class.split('::')
782 namespaces, classname = class_path[:-1], class_path[-1]
783 py_class_name = '_COLONS_'.join(class_path) if namespaces else \
784 classname;
785
786 # The 'local' attribute restricts us to the params declared in
787 # the object itself, not including inherited params (which
788 # will also be inherited from the base class's param struct
789 # here). Sort the params based on their key
790 params = map(lambda (k, v): v, sorted(cls._params.local.items()))
791 ports = cls._ports.local
792
793 code('''#include "pybind11/pybind11.h"
794#include "pybind11/stl.h"
795
796#include "sim/sim_object.hh"
797#include "params/$cls.hh"
798#include "sim/init.hh"
799#include "${{cls.cxx_header}}"
800
801''')
802
803 for param in params:
804 param.pybind_predecls(code)
805
806 code('''namespace py = pybind11;
807
808static void
809module_init(py::module &m_internal)
810{
811 py::module m = m_internal.def_submodule("param_${cls}");
812''')
813 code.indent()
814 if cls._base:
815 code('py::class_<${cls}Params, ${{cls._base.type}}Params>(m, ' \
816 '"${cls}Params")')
817 else:
818 code('py::class_<${cls}Params>(m, "${cls}Params")')
819
820 code.indent()
821 if not hasattr(cls, 'abstract') or not cls.abstract:
822 code('.def(py::init<>())')
823 code('.def("create", &${cls}Params::create)')
824
825 param_exports = cls.cxx_param_exports + [
826 PyBindProperty(k)
827 for k, v in sorted(cls._params.local.items())
828 ] + [
829 PyBindProperty("port_%s_connection_count" % port.name)
830 for port in ports.itervalues()
831 ]
832 for exp in param_exports:
833 exp.export(code, "%sParams" % cls)
834
835 code(';')
836 code()
837 code.dedent()
838
839 bases = [ cls._base.cxx_class ] + cls.cxx_bases if cls._base else \
840 cls.cxx_bases
841 if bases:
842 base_str = ", ".join(bases)
843 code('py::class_<${{cls.cxx_class}}, ${base_str}>(m, ' \
844 '"${py_class_name}")')
845 else:
846 code('py::class_<${{cls.cxx_class}}>(m, "${py_class_name}")')
847 code.indent()
848 for exp in cls.cxx_exports:
849 exp.export(code, cls.cxx_class)
850 code(';')
851 code.dedent()
852 code()
853 code.dedent()
854 code('}')
855 code()
856 code('static EmbeddedPyBind embed_obj("${0}", module_init, "${1}");',
857 cls, cls._base.type if cls._base else "")
858
859
860 # Generate the C++ declaration (.hh file) for this SimObject's
861 # param struct. Called from src/SConscript.
862 def cxx_param_decl(cls, code):
863 # The 'local' attribute restricts us to the params declared in
864 # the object itself, not including inherited params (which
865 # will also be inherited from the base class's param struct
866 # here). Sort the params based on their key
867 params = map(lambda (k, v): v, sorted(cls._params.local.items()))

--- 8 unchanged lines hidden (view full) ---

876 class_path = cls._value_dict['cxx_class'].split('::')
877
878 code('''\
879#ifndef __PARAMS__${cls}__
880#define __PARAMS__${cls}__
881
882''')
883
884
885 # The base SimObject has a couple of params that get
886 # automatically set from Python without being declared through
887 # the normal Param mechanism; we slip them in here (needed
888 # predecls now, actual declarations below)
889 if cls == SimObject:
890 code('''#include <string>''')
891
892 # A forward class declaration is sufficient since we are just
893 # declaring a pointer.
894 for ns in class_path[:-1]:
895 code('namespace $ns {')
896 code('class $0;', class_path[-1])
897 for ns in reversed(class_path[:-1]):
898 code('} // namespace $ns')
899 code()
900
901 for param in params:
902 param.cxx_predecls(code)
903 for port in ports.itervalues():
904 port.cxx_predecls(code)
905 code()
906
907 if cls._base:
908 code('#include "params/${{cls._base.type}}.hh"')

--- 15 unchanged lines hidden (view full) ---

924
925 code.indent()
926 if cls == SimObject:
927 code('''
928 SimObjectParams() {}
929 virtual ~SimObjectParams() {}
930
931 std::string name;
932 ''')
933
934 for param in params:
935 param.cxx_decl(code)
936 for port in ports.itervalues():
937 port.cxx_decl(code)
938
939 code.dedent()
940 code('};')
941

--- 11 unchanged lines hidden (view full) ---

953# SimObject class definition to the MetaSimObject methods (in
954# particular _set_param, which gets called for parameters with default
955# values defined on the SimObject class itself). It will get
956# overridden by the permanent definition (which requires that
957# SimObject be defined) lower in this file.
958def isSimObjectOrVector(value):
959 return False
960
961def cxxMethod(*args, **kwargs):
962 """Decorator to export C++ functions to Python"""
963
964 def decorate(func):
965 name = func.func_name
966 override = kwargs.get("override", False)
967 cxx_name = kwargs.get("cxx_name", name)
968
969 args, varargs, keywords, defaults = inspect.getargspec(func)
970 if varargs or keywords:
971 raise ValueError("Wrapped methods must not contain variable " \
972 "arguments")
973
974 # Create tuples of (argument, default)
975 if defaults:
976 args = args[:-len(defaults)] + zip(args[-len(defaults):], defaults)
977 # Don't include self in the argument list to PyBind
978 args = args[1:]
979
980
981 @wraps(func)
982 def cxx_call(self, *args, **kwargs):
983 ccobj = self.getCCObject()
984 return getattr(ccobj, name)(*args, **kwargs)
985
986 @wraps(func)
987 def py_call(self, *args, **kwargs):
988 return self.func(*args, **kwargs)
989
990 f = py_call if override else cxx_call
991 f.__pybind = PyBindMethod(name, cxx_name=cxx_name, args=args)
992
993 return f
994
995 if len(args) == 0:
996 return decorate
997 elif len(args) == 1 and len(kwargs) == 0:
998 return decorate(*args)
999 else:
1000 raise TypeError("One argument and no kwargs, or only kwargs expected")
1001
1002# This class holds information about each simobject parameter
1003# that should be displayed on the command line for use in the
1004# configuration system.
1005class ParamInfo(object):
1006 def __init__(self, type, desc, type_str, example, default_val, access_str):
1007 self.type = type
1008 self.desc = desc
1009 self.type_str = type_str

--- 44 unchanged lines hidden (view full) ---

1054 void memWriteback();
1055 void regStats();
1056 void resetStats();
1057 void regProbePoints();
1058 void regProbeListeners();
1059 void startup();
1060''')
1061
1062 cxx_exports = [
1063 PyBindMethod("init"),
1064 PyBindMethod("initState"),
1065 PyBindMethod("memInvalidate"),
1066 PyBindMethod("memWriteback"),
1067 PyBindMethod("regStats"),
1068 PyBindMethod("resetStats"),
1069 PyBindMethod("regProbePoints"),
1070 PyBindMethod("regProbeListeners"),
1071 PyBindMethod("startup"),
1072 ]
1073
1074 cxx_param_exports = [
1075 PyBindProperty("name"),
1076 ]
1077
1078 @cxxMethod
1079 def loadState(self, cp):
1080 """Load SimObject state from a checkpoint"""
1081 pass
1082
1083 # Returns a dict of all the option strings that can be
1084 # generated as command line options for this simobject instance
1085 # by tracing all reachable params in the top level instance and
1086 # any children it contains.
1087 def enumerateParams(self, flags_dict = {},
1088 cmd_line_str = "", access_str = ""):
1089 if hasattr(self, "_paramEnumed"):
1090 print "Cycle detected enumerating params"

--- 442 unchanged lines hidden (view full) ---

1533 return d
1534
1535 def getCCParams(self):
1536 if self._ccParams:
1537 return self._ccParams
1538
1539 cc_params_struct = getattr(m5.internal.params, '%sParams' % self.type)
1540 cc_params = cc_params_struct()
1541 cc_params.name = str(self)
1542
1543 param_names = self._params.keys()
1544 param_names.sort()
1545 for param in param_names:
1546 value = self._values.get(param)
1547 if value is None:
1548 fatal("%s.%s without default or user set value",
1549 self.path(), param)
1550
1551 value = value.getValue()
1552 if isinstance(self._params[param], VectorParamDesc):
1553 assert isinstance(value, list)
1554 vec = getattr(cc_params, param)
1555 assert not len(vec)
1556 setattr(cc_params, param, list(value))
1557 else:
1558 setattr(cc_params, param, value)
1559
1560 port_names = self._ports.keys()
1561 port_names.sort()
1562 for port_name in port_names:
1563 port = self._port_refs.get(port_name, None)
1564 if port != None:

--- 104 unchanged lines hidden (view full) ---

1669
1670 allClasses = baseClasses.copy()
1671 instanceDict = baseInstances.copy()
1672 noCxxHeader = False
1673
1674# __all__ defines the list of symbols that get exported when
1675# 'from config import *' is invoked. Try to keep this reasonably
1676# short to avoid polluting other namespaces.
1677__all__ = [
1678 'SimObject',
1679 'cxxMethod',
1680 'PyBindMethod',
1681 'PyBindProperty',
1682]