SimObject.py (13764:1647bbdc9444) | SimObject.py (13778:318f777400e9) |
---|---|
1# Copyright (c) 2017-2018 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 --- 401 unchanged lines hidden (view full) --- 410 'cxx_class' : str, 411 'cxx_type' : str, 412 'cxx_header' : str, 413 'type' : str, 414 'cxx_base' : (str, type(None)), 415 'cxx_extra_bases' : list, 416 'cxx_exports' : list, 417 'cxx_param_exports' : list, | 1# Copyright (c) 2017-2018 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 --- 401 unchanged lines hidden (view full) --- 410 'cxx_class' : str, 411 'cxx_type' : str, 412 'cxx_header' : str, 413 'type' : str, 414 'cxx_base' : (str, type(None)), 415 'cxx_extra_bases' : list, 416 'cxx_exports' : list, 417 'cxx_param_exports' : list, |
418 'cxx_template_params' : list, |
|
418 } 419 # Attributes that can be set any time 420 keywords = { 'check' : FunctionType } 421 422 # __new__ is called before __init__, and is where the statements 423 # in the body of the class definition get loaded into the class's 424 # __dict__. We intercept this to filter out parameter & port assignments 425 # and only allow "private" attributes to be passed to the base --- 23 unchanged lines hidden (view full) --- 449 if 'cxx_extra_bases' not in value_dict: 450 value_dict['cxx_extra_bases'] = [] 451 if 'cxx_exports' not in value_dict: 452 value_dict['cxx_exports'] = cxx_exports 453 else: 454 value_dict['cxx_exports'] += cxx_exports 455 if 'cxx_param_exports' not in value_dict: 456 value_dict['cxx_param_exports'] = [] | 419 } 420 # Attributes that can be set any time 421 keywords = { 'check' : FunctionType } 422 423 # __new__ is called before __init__, and is where the statements 424 # in the body of the class definition get loaded into the class's 425 # __dict__. We intercept this to filter out parameter & port assignments 426 # and only allow "private" attributes to be passed to the base --- 23 unchanged lines hidden (view full) --- 450 if 'cxx_extra_bases' not in value_dict: 451 value_dict['cxx_extra_bases'] = [] 452 if 'cxx_exports' not in value_dict: 453 value_dict['cxx_exports'] = cxx_exports 454 else: 455 value_dict['cxx_exports'] += cxx_exports 456 if 'cxx_param_exports' not in value_dict: 457 value_dict['cxx_param_exports'] = [] |
458 if 'cxx_template_params' not in value_dict: 459 value_dict['cxx_template_params'] = [] |
|
457 cls_dict['_value_dict'] = value_dict 458 cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 459 if 'type' in value_dict: 460 allClasses[name] = cls 461 return cls 462 463 # subclass initialization 464 def __init__(cls, name, bases, dict): --- 303 unchanged lines hidden (view full) --- 768 code.dedent() 769 code() 770 code.dedent() 771 code('}') 772 code() 773 code('static EmbeddedPyBind embed_obj("${0}", module_init, "${1}");', 774 cls, cls._base.type if cls._base else "") 775 | 460 cls_dict['_value_dict'] = value_dict 461 cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 462 if 'type' in value_dict: 463 allClasses[name] = cls 464 return cls 465 466 # subclass initialization 467 def __init__(cls, name, bases, dict): --- 303 unchanged lines hidden (view full) --- 771 code.dedent() 772 code() 773 code.dedent() 774 code('}') 775 code() 776 code('static EmbeddedPyBind embed_obj("${0}", module_init, "${1}");', 777 cls, cls._base.type if cls._base else "") 778 |
779 _warned_about_nested_templates = False |
|
776 777 # Generate the C++ declaration (.hh file) for this SimObject's 778 # param struct. Called from src/SConscript. 779 def cxx_param_decl(cls, code): 780 # The 'local' attribute restricts us to the params declared in 781 # the object itself, not including inherited params (which 782 # will also be inherited from the base class's param struct 783 # here). Sort the params based on their key 784 params = map(lambda k_v: k_v[1], sorted(cls._params.local.items())) 785 ports = cls._ports.local 786 try: 787 ptypes = [p.ptype for p in params] 788 except: 789 print(cls, p, p.ptype_str) 790 print(params) 791 raise 792 | 780 781 # Generate the C++ declaration (.hh file) for this SimObject's 782 # param struct. Called from src/SConscript. 783 def cxx_param_decl(cls, code): 784 # The 'local' attribute restricts us to the params declared in 785 # the object itself, not including inherited params (which 786 # will also be inherited from the base class's param struct 787 # here). Sort the params based on their key 788 params = map(lambda k_v: k_v[1], sorted(cls._params.local.items())) 789 ports = cls._ports.local 790 try: 791 ptypes = [p.ptype for p in params] 792 except: 793 print(cls, p, p.ptype_str) 794 print(params) 795 raise 796 |
793 class_path = cls._value_dict['cxx_class'].split('::') | 797 class CxxClass(object): 798 def __init__(self, sig, template_params=[]): 799 # Split the signature into its constituent parts. This could 800 # potentially be done with regular expressions, but 801 # it's simple enough to pick appart a class signature 802 # manually. 803 parts = sig.split('<', 1) 804 base = parts[0] 805 t_args = [] 806 if len(parts) > 1: 807 # The signature had template arguments. 808 text = parts[1].rstrip(' \t\n>') 809 arg = '' 810 # Keep track of nesting to avoid splitting on ","s embedded 811 # in the arguments themselves. 812 depth = 0 813 for c in text: 814 if c == '<': 815 depth = depth + 1 816 if depth > 0 and not \ 817 self._warned_about_nested_templates: 818 self._warned_about_nested_templates = True 819 print('Nested template argument in cxx_class.' 820 ' This feature is largely untested and ' 821 ' may not work.') 822 elif c == '>': 823 depth = depth - 1 824 elif c == ',' and depth == 0: 825 t_args.append(arg.strip()) 826 arg = '' 827 else: 828 arg = arg + c 829 if arg: 830 t_args.append(arg.strip()) 831 # Split the non-template part on :: boundaries. 832 class_path = base.split('::') |
794 | 833 |
834 # The namespaces are everything except the last part of the 835 # class path. 836 self.namespaces = class_path[:-1] 837 # And the class name is the last part. 838 self.name = class_path[-1] 839 840 self.template_params = template_params 841 self.template_arguments = [] 842 # Iterate through the template arguments and their values. This 843 # will likely break if parameter packs are used. 844 for arg, param in zip(t_args, template_params): 845 type_keys = ('class', 'typename') 846 # If a parameter is a type, parse it recursively. Otherwise 847 # assume it's a constant, and store it verbatim. 848 if any(param.strip().startswith(kw) for kw in type_keys): 849 self.template_arguments.append(CxxClass(arg)) 850 else: 851 self.template_arguments.append(arg) 852 853 def declare(self, code): 854 # First declare any template argument types. 855 for arg in self.template_arguments: 856 if isinstance(arg, CxxClass): 857 arg.declare(code) 858 # Re-open the target namespace. 859 for ns in self.namespaces: 860 code('namespace $ns {') 861 # If this is a class template... 862 if self.template_params: 863 code('template <${{", ".join(self.template_params)}}>') 864 # The actual class declaration. 865 code('class ${{self.name}};') 866 # Close the target namespaces. 867 for ns in reversed(self.namespaces): 868 code('} // namespace $ns') 869 |
|
795 code('''\ 796#ifndef __PARAMS__${cls}__ 797#define __PARAMS__${cls}__ 798 799''') 800 801 802 # The base SimObject has a couple of params that get 803 # automatically set from Python without being declared through 804 # the normal Param mechanism; we slip them in here (needed 805 # predecls now, actual declarations below) 806 if cls == SimObject: 807 code('''#include <string>''') 808 | 870 code('''\ 871#ifndef __PARAMS__${cls}__ 872#define __PARAMS__${cls}__ 873 874''') 875 876 877 # The base SimObject has a couple of params that get 878 # automatically set from Python without being declared through 879 # the normal Param mechanism; we slip them in here (needed 880 # predecls now, actual declarations below) 881 if cls == SimObject: 882 code('''#include <string>''') 883 |
884 cxx_class = CxxClass(cls._value_dict['cxx_class'], 885 cls._value_dict['cxx_template_params']) 886 |
|
809 # A forward class declaration is sufficient since we are just 810 # declaring a pointer. | 887 # A forward class declaration is sufficient since we are just 888 # declaring a pointer. |
811 for ns in class_path[:-1]: 812 code('namespace $ns {') 813 code('class $0;', class_path[-1]) 814 for ns in reversed(class_path[:-1]): 815 code('} // namespace $ns') 816 code() | 889 cxx_class.declare(code) |
817 818 for param in params: 819 param.cxx_predecls(code) 820 for port in ports.values(): 821 port.cxx_predecls(code) 822 code() 823 824 if cls._base: --- 857 unchanged lines hidden --- | 890 891 for param in params: 892 param.cxx_predecls(code) 893 for port in ports.values(): 894 port.cxx_predecls(code) 895 code() 896 897 if cls._base: --- 857 unchanged lines hidden --- |