def example_psyir(create_expression): '''Utility function that creates a PSyIR tree containing an ABS intrinsic operator and returns the operator. :param function create_expresssion: function used to create the \ content of the ABS operator. :returns: PSyIR ABS operator instance. :rtype: :py:class:`psyclone.psyGen.UnaryOperation` ''' symbol_table = SymbolTable() name1 = symbol_table.new_symbol_name("arg") arg1 = DataSymbol(name1, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg1) name2 = symbol_table.new_symbol_name() local = DataSymbol(name2, REAL_TYPE) symbol_table.add(local) symbol_table.specify_argument_list([arg1]) var1 = Reference(arg1) var2 = Reference(local) oper = UnaryOperation.Operator.ABS operation = UnaryOperation.create(oper, create_expression(var1)) assign = Assignment.create(var2, operation) _ = KernelSchedule.create("abs_example", symbol_table, [assign]) return operation
def example_psyir_nary(): '''Utility function that creates a PSyIR tree containing a nary MIN intrinsic operator and returns the operator. :returns: PSyIR MIN operator instance. :rtype: :py:class:`psyclone.psyGen.NaryOperation` ''' symbol_table = SymbolTable() name1 = symbol_table.new_symbol_name("arg") arg1 = DataSymbol(name1, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg1) name2 = symbol_table.new_symbol_name("arg") arg2 = DataSymbol(name2, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg2) name3 = symbol_table.new_symbol_name("arg") arg3 = DataSymbol(name3, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg3) name4 = symbol_table.new_symbol_name() arg4 = DataSymbol(name4, REAL_TYPE) symbol_table.add(arg4) symbol_table.specify_argument_list([arg1, arg2, arg3]) var1 = Reference(arg1) var2 = Reference(arg2) var3 = Reference(arg3) var4 = Reference(arg4) oper = NaryOperation.Operator.MIN operation = NaryOperation.create(oper, [var1, var2, var3]) assign = Assignment.create(var4, operation) _ = KernelSchedule.create("min_example", symbol_table, [assign]) return operation
def example_psyir_binary(create_expression): '''Utility function that creates a PSyIR tree containing a binary MIN intrinsic operator and returns the operator. :param function create_expresssion: function used to create the \ content of the first argument of the MIN operator. :returns: PSyIR MIN operator instance. :rtype: :py:class:`psyclone.psyGen.BinaryOperation` ''' symbol_table = SymbolTable() name1 = symbol_table.new_symbol_name("arg") arg1 = DataSymbol(name1, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg1) name2 = symbol_table.new_symbol_name("arg") arg2 = DataSymbol(name2, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) symbol_table.add(arg2) name3 = symbol_table.new_symbol_name() arg3 = DataSymbol(name3, REAL_TYPE) symbol_table.add(arg3) symbol_table.specify_argument_list([arg1, arg2]) var1 = Reference(arg1) var2 = Reference(arg2) var3 = Reference(arg3) oper = BinaryOperation.Operator.MIN operation = BinaryOperation.create(oper, create_expression(var1), var2) assign = Assignment.create(var3, operation) _ = KernelSchedule.create("min_example", symbol_table, [assign]) return operation
def __init__(self, ast=None, children=None, parent=None, options=None): if not options: options = {} # This string stores a prefix to be used with all external PSyData # symbols (i.e. data types and module name), used in the # method 'add_psydata_class_prefix'. self._class_string = options.get("prefix", "") if self._class_string: self._class_string = self._class_string + "_" # Root of the name to use for variables associated with # PSyData regions self._psy_data_symbol_with_prefix = \ self.add_psydata_class_prefix("psy_data") # The use statement that will be inserted. Any use of a module # of the same name that doesn't match this will result in a # NotImplementedError at code-generation time. self.use_stmt = "use {0}, only: "\ .format(self.add_psydata_class_prefix("psy_data_mod")) + \ ", ".join(self.add_psydata_class_prefix(symbol) for symbol in PSyDataNode.symbols) if children: # We need to store the position of the original children, # i.e. before they are added to a schedule node_position = children[0].position # A PSyData node always contains a Schedule sched = self._insert_schedule(children) super(PSyDataNode, self).__init__(ast=ast, children=[sched], parent=parent) # Get or create a symbol table so we can avoid name clashes # when creating variables if parent and hasattr(self.root, 'symbol_table'): symtab = self.root.symbol_table else: # FIXME: This may not be a good solution symtab = SymbolTable() # Store the name of the PSyData variable that is used for this # PSyDataNode. This allows the variable name to be shown in str # (and also, calling create_name in gen() would result in the name # being changed every time gen() is called). self._var_name = symtab.new_symbol_name( self._psy_data_symbol_with_prefix) symtab.add(Symbol(self._var_name)) if children and parent: # Correct the parent's list of children. Use a slice of the list # of nodes so that we're looping over a local copy of the list. # Otherwise things get confused when we remove children from # the list. for child in children[:]: # Remove child from the parent's list of children parent.children.remove(child) # Add this node as a child of the parent # of the nodes being enclosed and at the original location # of the first of these nodes parent.addchild(self, index=node_position) elif parent: parent.addchild(self) # Name of the region. In general at constructor time we might # not have a parent subroutine or any child nodes, so # the name is left empty, unless explicitly provided by the # user. If names are not provided here then the region and # module names are set the first time gen() is called (and # then remain unchanged). self._module_name = None self._region_name = None # The region identifier caches the computed module- and region-name # as a tuple of strings. This is required so that a derived class can # query the actual name of region (e.g. during generation of a driver # for an extract node). If the user does not define a name, i.e. # module_name and region_name are empty, a unique name will be # computed in gen_code(). If this name would then be stored in # module_name and region_name, and gen() is called again, the # names would not be computed again, since the code detects already # defined module and region names. This can then result in duplicated # region names: The test 'test_region' in profile_test triggers this. # gen()) is called first after one profile region is applied, then # another profile region is added, and gen() is called again. The # second profile region would compute a new name, which then happens # to be the same as the name computed for the first region in the # first gen_code call (which indeed implies that the name of the # first profile region is different the second time it is computed). # So in order to guarantee that the computed module and region names # are unique when gen_code is called more than once, we # cannot store a computed name in module_name and region_name. self._region_identifier = ("", "") name = options.get("region_name", None) if name: # pylint: disable=too-many-boolean-expressions if not isinstance(name, tuple) or not len(name) == 2 or \ not name[0] or not isinstance(name[0], str) or \ not name[1] or not isinstance(name[1], str): raise InternalError("Error in PSyDataNode. The name must be a " "tuple containing two non-empty strings.") # pylint: enable=too-many-boolean-expressions # Valid PSyData names have been provided by the user. self._module_name = name[0] self._region_name = name[1] self.set_region_identifier(self._module_name, self._region_name)
''' from __future__ import print_function from psyclone.psyir.nodes import Reference, Literal, UnaryOperation, \ BinaryOperation, NaryOperation, Assignment, IfBlock, Loop, \ Container, Range, Array, Call, KernelSchedule from psyclone.psyir.symbols import DataSymbol, RoutineSymbol, SymbolTable, \ ContainerSymbol, ArgumentInterface, ScalarType, ArrayType, \ GlobalInterface, REAL_TYPE, REAL4_TYPE, REAL_DOUBLE_TYPE, INTEGER_TYPE, \ INTEGER_SINGLE_TYPE, INTEGER4_TYPE, INTEGER8_TYPE from psyclone.psyir.backend.fortran import FortranWriter from psyclone.psyir.backend.c import CWriter # Symbol table, symbols and scalar datatypes SYMBOL_TABLE = SymbolTable() TMP_NAME1 = SYMBOL_TABLE.new_symbol_name() ARG1 = DataSymbol(TMP_NAME1, REAL_TYPE, interface=ArgumentInterface( ArgumentInterface.Access.READWRITE)) SYMBOL_TABLE.add(ARG1) TMP_NAME2 = SYMBOL_TABLE.new_symbol_name() TMP_SYMBOL = DataSymbol(TMP_NAME2, REAL_DOUBLE_TYPE) SYMBOL_TABLE.add(TMP_SYMBOL) INDEX_NAME = SYMBOL_TABLE.new_symbol_name(root_name="i") INDEX_SYMBOL = DataSymbol(INDEX_NAME, INTEGER4_TYPE) SYMBOL_TABLE.add(INDEX_SYMBOL) SYMBOL_TABLE.specify_argument_list([ARG1]) REAL_KIND_NAME = SYMBOL_TABLE.new_symbol_name(root_name="RKIND") REAL_KIND = DataSymbol(REAL_KIND_NAME, INTEGER_TYPE, constant_value=8) SYMBOL_TABLE.add(REAL_KIND)