Пример #1
0
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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
    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)
Пример #5
0
'''
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)