Esempio n. 1
0
def test_transform_apply(lhs_create, rhs_create, expected, tmpdir):
    '''Check that the PSyIR is transformed as expected for various types
    of ranges in an array. The resultant Fortran code is used to
    confirm the transformation has worked correctly.

    '''
    trans = ArrayRange2LoopTrans()
    symbol_table = SymbolTable()
    symbol = DataSymbol("n", INTEGER_TYPE)
    symbol_table.add(symbol)
    lhs = lhs_create(symbol_table)
    rhs = rhs_create(symbol_table)
    assignment = Assignment.create(lhs, rhs)
    routine = KernelSchedule.create("work", symbol_table, [assignment])
    trans.apply(assignment)
    writer = FortranWriter()
    result = writer(routine)
    assert expected in result
    assert Compile(tmpdir).string_compiles(result)
Esempio n. 2
0
def test_psy_data_node_basics():
    '''Tests some elementary functions.'''
    psy_node = PSyDataNode.create([], SymbolTable())
    assert "PSyDataStart[var=psy_data]\n"\
        "PSyDataEnd[var=psy_data]" in str(psy_node)

    psy_node.children = []
    with pytest.raises(InternalError) as error:
        _ = psy_node.psy_data_body
    assert "PSyData node malformed or incomplete" in str(error.value)
Esempio n. 3
0
def test_get_external_symbol(monkeypatch):
    ''' Test the get_external_symbol() method. '''
    asym = Symbol("a")
    with pytest.raises(NotImplementedError) as err:
        asym.get_external_symbol()
    assert ("trying to resolve symbol 'a' properties, the lazy evaluation "
            "of 'Local' interfaces is not supported" in str(err.value))
    other_container = ContainerSymbol("some_mod")
    ctable = SymbolTable()
    ctable.add(other_container)
    # Create a Symbol that is imported from the "some_mod" Container
    bsym = Symbol("b", interface=GlobalInterface(other_container))
    ctable.add(bsym)
    _ = Container.create("test", ctable, [KernelSchedule("dummy")])
    # Monkeypatch the container's FortranModuleInterface so that it always
    # appears to be unable to find the "some_mod" module

    def fake_import(name):
        raise SymbolError("Oh dear")
    monkeypatch.setattr(other_container._interface, "import_container",
                        fake_import)
    with pytest.raises(SymbolError) as err:
        bsym.get_external_symbol()
    assert ("trying to resolve the properties of symbol 'b' in module "
            "'some_mod': PSyclone SymbolTable error: Oh dear" in
            str(err.value))
    # Now create a Container for the 'some_mod' module and attach this to
    # the ContainerSymbol
    ctable2 = SymbolTable()
    some_mod = Container.create("some_mod", ctable2,
                                [KernelSchedule("dummy2")])
    other_container._reference = some_mod
    # Currently the Container does not contain an entry for 'b'
    with pytest.raises(SymbolError) as err:
        bsym.get_external_symbol()
    assert ("trying to resolve the properties of symbol 'b'. The interface "
            "points to module 'some_mod' but could not find the definition" in
            str(err.value))
    # Add an entry for 'b' to the Container's symbol table
    ctable2.add(DataSymbol("b", INTEGER_SINGLE_TYPE))
    new_sym = bsym.resolve_deferred()
    assert isinstance(new_sym, DataSymbol)
    assert new_sym.datatype == INTEGER_SINGLE_TYPE
Esempio n. 4
0
def test_auto_invoke_no_return(capsys):
    ''' Check that using the auto-invoke profiling option does not add any
    profiling if the invoke contains a Return anywhere other than as the
    last statement. '''
    Profiler.set_options([Profiler.INVOKES])
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(
        symbol_type=DataSymbol, datatype=REAL_TYPE)
    zero = Literal("0.0", REAL_TYPE)
    assign1 = Assignment.create(Reference(arg1), zero)
    assign2 = Assignment.create(Reference(arg1), zero.copy())

    # Create Schedule with Return at the start.
    kschedule = KernelSchedule.create(
        "work1", symbol_table, [Return(), assign1, assign2])
    Profiler.add_profile_nodes(kschedule, Loop)
    # No profiling should have been added
    assert not kschedule.walk(ProfileNode)
    _, err = capsys.readouterr()
    assert ("Not adding profiling to routine 'work1' because it contains one "
            "or more Return statements" in err)

    # Create Schedule with Return in the middle.
    kschedule = KernelSchedule.create(
        "work2", symbol_table, [assign1.copy(), Return(), assign2.copy()])
    Profiler.add_profile_nodes(kschedule, Loop)
    # No profiling should have been added
    assert not kschedule.walk(ProfileNode)
    _, err = capsys.readouterr()
    assert ("Not adding profiling to routine 'work2' because it contains one "
            "or more Return statements" in err)

    # Create Schedule with a Return at the end as well as in the middle.
    kschedule = KernelSchedule.create(
        "work3", symbol_table, [assign1.copy(), Return(), assign2.copy(),
                                Return()])
    Profiler.add_profile_nodes(kschedule, Loop)
    # No profiling should have been added
    assert not kschedule.walk(ProfileNode)
    _, err = capsys.readouterr()
    assert ("Not adding profiling to routine 'work3' because it contains one "
            "or more Return statements" in err)
Esempio n. 5
0
def test_lower_named_profile_node():
    ''' Test that the lower_to_language_level method behaves as expected when
    a ProfileNode has pre-set names for the module and region.

    '''
    Profiler.set_options([Profiler.INVOKES])
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol, datatype=REAL_TYPE)
    assign1 = Assignment.create(Reference(arg1), Literal("0.0", REAL_TYPE))
    kschedule = KernelSchedule.create("work1", symbol_table,
                                      [assign1, Return()])
    Profiler.add_profile_nodes(kschedule, Loop)
    pnode = kschedule.walk(ProfileNode)[0]
    # Manually set the module and region names (to save using a transformation)
    pnode._module_name = "my_mod"
    pnode._region_name = "first"
    kschedule.lower_to_language_level()
    cblocks = kschedule.walk(CodeBlock)
    assert ("PreStart('my_mod', 'first', 0, 0)"
            in str(cblocks[0].get_ast_nodes[0]))
Esempio n. 6
0
def test_auto_invoke_return_last_stmt():
    ''' Check that using the auto-invoke profiling option avoids including
    a return statement within the profiling region if it is the last statement
    in the routine. '''
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(
        symbol_type=DataSymbol, datatype=REAL_TYPE)
    zero = Literal("0.0", REAL_TYPE)
    assign1 = Assignment.create(Reference(arg1), zero)
    kschedule = KernelSchedule.create(
        "work", symbol_table, [assign1, Return()])
    # Double-check that the tree is as we expect
    assert isinstance(kschedule[-1], Return)

    Profiler.set_options([Profiler.INVOKES])
    Profiler.add_profile_nodes(kschedule, Loop)
    # The Return should be a sibling of the ProfileNode rather than a child
    assert isinstance(kschedule[0], ProfileNode)
    assert isinstance(kschedule[0].children[0].children[0], Assignment)
    assert isinstance(kschedule[1], Return)
Esempio n. 7
0
def test_profile_node_invalid_name(value):
    '''Test that the expected exception is raised when an invalid profile
    name is provided to a ProfileNode.

    '''
    with pytest.raises(InternalError) as excinfo:
        _ = ProfileNode.create([],
                               SymbolTable(),
                               options={"region_name": value})
    assert ("Error in PSyDataNode. The name must be a tuple containing "
            "two non-empty strings." in str(excinfo.value))
Esempio n. 8
0
def test_routine_create_invalid():
    '''Test that the create method in the Routine class raises the
    expected exceptions if the provided input is invalid.

    '''
    symbol_table = SymbolTable()
    symbol = DataSymbol("x", REAL_TYPE)
    symbol_table.add(symbol)
    children = [Assignment.create(Reference(symbol),
                                  Literal("1", REAL_TYPE))]

    # name is not a string.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create(1, symbol_table, children)
    assert ("name argument in create method of Routine class "
            "should be a string but found 'int'.") in str(excinfo.value)

    # symbol_table not a SymbolTable.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", "invalid", children)
    assert ("symbol_table argument in create method of Routine class "
            "should be a SymbolTable but found 'str'.") in str(excinfo.value)

    # children not a list.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", symbol_table, "invalid")
    assert ("children argument in create method of Routine class "
            "should be a list but found 'str'." in str(excinfo.value))

    # contents of children list are not Node.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", symbol_table, ["invalid"])
    assert (
        "child of children argument in create method of Routine class "
        "should be a PSyIR Node but found 'str'." in str(excinfo.value))

    # return_symbol is not a Symbol
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", symbol_table, [], return_symbol="wrong")
    assert ("Routine return-symbol should be a DataSymbol but found 'str'" in
            str(excinfo.value))
Esempio n. 9
0
 def __init__(self, kern):
     # We don't yet support inter-grid kernels (Issue #162)
     if kern.is_intergrid:
         raise NotImplementedError(
             "Kernel {0} is an inter-grid kernel and stub generation "
             "is not yet supported for inter-grid kernels".format(
                 kern.name))
     ArgOrdering.__init__(self, kern)
     # TODO 719 The stub_symtab is not connected to other parts of the
     # Stub generation. Also the symboltable already has an
     # argument_list that may be able to replace the argument list below.
     self._stub_symtab = SymbolTable()
Esempio n. 10
0
def test_scoping_node_symbol_table():
    '''Test that ScopingNodes have a symbol_table property that returns its
    associated symbol table.'''
    # Since ScopingNode is abstract we will try this with a Container
    container = Container("test")
    assert container.symbol_table is container._symbol_table
    assert isinstance(container.symbol_table, SymbolTable)

    # An existing symbol table can be given to the constructor
    symtab = SymbolTable()
    container = Container("test", symbol_table=symtab)
    assert container.symbol_table is symtab
Esempio n. 11
0
def test_arraytype_shape_dim_from_parent_scope():
    ''' Check that the shape checking in the ArrayType class permits the
    use of a reference to a symbol in a parent scope. '''
    cont = Container("test_mod")
    dim_sym = cont.symbol_table.new_symbol("dim1", symbol_type=DataSymbol,
                                           datatype=INTEGER_TYPE)
    kernel1 = KernelSchedule.create("mod_1", SymbolTable(), [])
    cont.addchild(kernel1)
    asym = kernel1.symbol_table.new_symbol(
        "array1", symbol_type=DataSymbol,
        datatype=ArrayType(INTEGER_TYPE, [Reference(dim_sym)]))
    assert isinstance(asym, DataSymbol)
Esempio n. 12
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()
    arg1 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    local = symbol_table.new_symbol(symbol_type=DataSymbol, datatype=REAL_TYPE)
    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
Esempio n. 13
0
def test_kernelschedule_create():
    '''Test that the create method in the KernelSchedule class correctly
    creates a KernelSchedule instance.

    '''
    symbol_table = SymbolTable()
    symbol = DataSymbol("tmp", REAL_TYPE)
    symbol_table.add(symbol)
    assignment = Assignment.create(Reference(symbol),
                                   Literal("0.0", REAL_TYPE))
    kschedule = KernelSchedule.create("mod_name", symbol_table, [assignment])
    assert isinstance(kschedule, KernelSchedule)
    # A KernelSchedule is not a main program and has no return type.
    assert not kschedule.is_program
    assert kschedule.return_type is None
    check_links(kschedule, [assignment])
    assert kschedule.symbol_table is symbol_table
    result = FortranWriter().routine_node(kschedule)
    assert result == ("subroutine mod_name()\n"
                      "  real :: tmp\n\n"
                      "  tmp = 0.0\n\n"
                      "end subroutine mod_name\n")
Esempio n. 14
0
def test_auto_invoke_empty_schedule(capsys):
    ''' Check the auto-invoke profiling option rejects an empty Schedule, i.e
    the routine has no statements. '''
    Profiler.set_options([Profiler.INVOKES])
    symbol_table = SymbolTable()
    # Create Schedule with Return at the start.
    kschedule = KernelSchedule.create(
        "work1", symbol_table, [])
    Profiler.add_profile_nodes(kschedule, Loop)
    assert not kschedule.walk(ProfileNode)
    _, err = capsys.readouterr()
    assert ("Not adding profiling to routine 'work1' because it does not "
            "contain any statements." in err)
Esempio n. 15
0
def trans(psy):
    '''Transformation routine for use with PSyclone. Applies the PSyIR2SIR
    transform to the supplied invokes after replacing any ABS, SIGN or
    MIN intrinsics with equivalent code. This is done because the SIR
    does not support intrinsics.

    :param psy: the PSy object which this script will transform.
    :type psy: :py:class:`psyclone.psyGen.PSy`
    :returns: the transformed PSy object.
    :rtype: :py:class:`psyclone.psyGen.PSy`

    '''

    abs_trans = Abs2CodeTrans()
    sign_trans = Sign2CodeTrans()
    min_trans = Min2CodeTrans()

    sir_writer = SIRWriter()
    # For each Invoke write out the SIR representation of the
    # schedule. Note, there is no algorithm layer in the NEMO API so
    # the invokes represent all of the original code.
    for invoke in psy.invokes.invoke_list:
        sched = invoke.schedule
        for kernel in sched.walk(NemoKern):

            # The NEMO api currently has no symbol table so create one
            # to allow the generation of new variables. Note, this
            # does not guarantee unique names as we don't know any of
            # the existing names (so generated names could clash).
            symbol_table = SymbolTable()

            kernel_schedule = kernel.get_kernel_schedule()
            for oper in kernel_schedule.walk(Operation):
                if oper.operator == UnaryOperation.Operator.ABS:
                    # Apply ABS transformation
                    abs_trans.apply(oper, symbol_table)
                elif oper.operator == BinaryOperation.Operator.SIGN:
                    # Apply SIGN transformation
                    sign_trans.apply(oper, symbol_table)
                elif oper.operator in [
                        BinaryOperation.Operator.MIN,
                        NaryOperation.Operator.MIN
                ]:
                    # Apply (2-n arg) MIN transformation
                    min_trans.apply(oper, symbol_table)
        kern = sir_writer(sched)
        print(kern)

    return psy
Esempio n. 16
0
def test_find_symbol_table():
    ''' Test the find_symbol_table() method. '''
    sym = Symbol("a_var")
    with pytest.raises(TypeError) as err:
        sym.find_symbol_table("3")
    assert ("expected to be passed an instance of psyir.nodes.Node but got "
            "'str'" in str(err.value))
    # Search for a SymbolTable with only one level of hierarchy
    sched = KernelSchedule("dummy")
    table = sched.symbol_table
    table.add(sym)
    assert sym.find_symbol_table(sched) is table
    # Create a Container so that we have two levels of hierarchy
    ctable = SymbolTable()
    sym2 = Symbol("b_var")
    ctable.add(sym2)
    _ = Container.create("test", ctable, [sched])
    assert sym2.find_symbol_table(sched) is ctable
    # A Symbol that isn't in any table
    sym3 = Symbol("missing")
    assert sym3.find_symbol_table(sched) is None
    # When there is no SymbolTable associated with the PSyIR node
    orphan = Literal("1", INTEGER_SINGLE_TYPE)
    assert sym3.find_symbol_table(orphan) is None
Esempio n. 17
0
def test_psy_data_node_create_errors():
    ''' Test the various checks on the arguments to the create() method. '''
    sym_tab = SymbolTable()
    with pytest.raises(TypeError) as err:
        PSyDataNode.create("hello", sym_tab)
    assert ("create(). The 'children' argument must be a list (of PSyIR "
            "nodes) but got 'str'" in str(err.value))
    with pytest.raises(TypeError) as err:
        PSyDataNode.create(["hello"], sym_tab)
    assert ("create(). The 'children' argument must be a list of PSyIR "
            "nodes but it contains: ['str']" in str(err.value))
    with pytest.raises(TypeError) as err:
        PSyDataNode.create([], "hello")
    assert ("create(). The 'symbol_table' argument must be an instance of "
            "psyir.symbols.SymbolTable but got 'str'" in str(err.value))
Esempio n. 18
0
def test_sched_init():
    ''' Check the Schedule class is initialised as expected.'''

    # By default Schedule sets parent to None, children to an empty list and
    # initialises its own symbol table.
    sched = Schedule()
    assert isinstance(sched, Schedule)
    assert not sched.parent
    assert not sched.children
    assert isinstance(sched.symbol_table, SymbolTable)

    # A custom symbol table and parent and children nodes can be given as
    # arguments of Schedule.
    symtab = SymbolTable()
    sched2 = Schedule(parent=sched, children=[Statement(), Statement()],
                      symbol_table=symtab)
    assert isinstance(sched2, Schedule)
    assert sched2.parent is sched
    assert len(sched2.children) == 2
    assert sched2.symbol_table is symtab
Esempio n. 19
0
def test_validate_intrinsic():
    '''Check that the validate method returns an exception if the rhs of
    the assignment contains an operator that only returns an array
    i.e. can't be performed elementwise. At the moment MATMUL is the
    only operator of this type.

    '''
    symbol_table = SymbolTable()
    array_x = create_array_x(symbol_table)
    array_y_2 = create_array_y_2d_slice(symbol_table)
    matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, array_y_2,
                                    array_x)
    assignment = Assignment.create(array_x, matmul)

    trans = ArrayRange2LoopTrans()
    with pytest.raises(TransformationError) as info:
        trans.validate(assignment)
    assert ("Error in ArrayRange2LoopTrans transformation. The rhs of the "
            "supplied Assignment node 'BinaryOperation[operator:'MATMUL']\\n"
            "ArrayArrayReference[name:'y2']\\nRange[]\\nRange[]\\n\\n"
            "ArrayArrayReference[name:'x']\\nRange[]\\n' contains the MATMUL "
            "operator which can't be performed elementwise."
            in str(info.value))
Esempio n. 20
0
def test_psy_data_node_children_validation():
    '''Test that children added to PSyDataNode are validated. PSyDataNode
    accepts just one Schedule as its child.

    '''
    psy_node = PSyDataNode.create([], SymbolTable())
    del psy_node.children[0]

    # Invalid children (e.g. Return Statement)
    ret = Return()
    with pytest.raises(GenerationError) as excinfo:
        psy_node.addchild(ret)
    assert ("Item 'Return' can't be child 0 of 'PSyData'. The valid format"
            " is: 'Schedule'." in str(excinfo.value))

    # Valid children
    psy_node.addchild(Schedule())

    # Additional children
    with pytest.raises(GenerationError) as excinfo:
        psy_node.addchild(Schedule())
    assert ("Item 'Schedule' can't be child 1 of 'PSyData'. The valid format"
            " is: 'Schedule'." in str(excinfo.value))
Esempio n. 21
0
def test_file_container_create():
    '''Test that the create method in the Container class correctly
    creates a FileContainer instance.

    '''
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("tmp", REAL_SINGLE_TYPE))
    module = Container.create("mod_1", symbol_table, [])
    program = Routine.create("prog_1", SymbolTable(), [], is_program=True)
    file_container = FileContainer.create("container_name", SymbolTable(),
                                          [module, program])
    assert isinstance(file_container, FileContainer)
    result = FortranWriter().filecontainer_node(file_container)
    assert result == ("module mod_1\n"
                      "  implicit none\n"
                      "  real :: tmp\n\n"
                      "  contains\n\n"
                      "end module mod_1\n"
                      "program prog_1\n\n\n"
                      "end program prog_1\n")
Esempio n. 22
0
def test_oclw_gen_array_length_variables():
    '''Check the OpenCLWriter class gen_array_length_variables method produces
    the expected declarations.

    '''
    oclwriter = OpenCLWriter()

    # A scalar should not return any LEN variables
    symbol1 = DataSymbol("dummy2LEN1", INTEGER_TYPE)
    result = oclwriter.gen_array_length_variables(symbol1)
    assert result == ""

    # Array with 1 dimension generates 1 length variable
    array_type = ArrayType(INTEGER_TYPE, [2])
    symbol2 = DataSymbol("dummy1", array_type)
    result = oclwriter.gen_array_length_variables(symbol2)
    assert result == "int dummy1LEN1 = get_global_size(0);\n"

    # Array with multiple dimension generates one variable per dimension
    array_type = ArrayType(INTEGER_TYPE, [2, ArrayType.Extent.ATTRIBUTE, 2])
    symbol3 = DataSymbol("dummy2", array_type)
    result = oclwriter.gen_array_length_variables(symbol3)
    assert result == "int dummy2LEN1 = get_global_size(0);\n" \
        "int dummy2LEN2 = get_global_size(1);\n" \
        "int dummy2LEN3 = get_global_size(2);\n"

    # Create a symbol table
    symtab = SymbolTable()
    symtab.add(symbol1)
    symtab.add(symbol2)
    symtab.add(symbol3)

    # If there are no name clashes, generate array length variables.
    result = oclwriter.gen_array_length_variables(symbol2, symtab)
    assert result == "int dummy1LEN1 = get_global_size(0);\n"

    with pytest.raises(VisitorError) as excinfo:
        _ = oclwriter.gen_array_length_variables(symbol3, symtab)
    assert "Unable to declare the variable 'dummy2LEN1' to store the length " \
        "of 'dummy2' because the Symbol Table already contains a symbol with" \
        " the same name." in str(excinfo.value)
Esempio n. 23
0
def test_container_create():
    '''Test that the create method in the Container class correctly
    creates a Container instance.

    '''
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("tmp", REAL_SINGLE_TYPE))
    kernel1 = KernelSchedule.create("mod_1", SymbolTable(), [])
    kernel2 = KernelSchedule.create("mod_2", SymbolTable(), [])
    container = Container.create("container_name", symbol_table,
                                 [kernel1, kernel2])
    check_links(container, [kernel1, kernel2])
    assert container.symbol_table is symbol_table
    result = FortranWriter().container_node(container)
    assert result == ("module container_name\n"
                      "  real :: tmp\n\n"
                      "  contains\n"
                      "  subroutine mod_1()\n\n\n"
                      "  end subroutine mod_1\n"
                      "  subroutine mod_2()\n\n\n"
                      "  end subroutine mod_2\n\n"
                      "end module container_name\n")
Esempio n. 24
0
 def __init__(self, name, parent=None):
     super(Container, self).__init__(parent=parent)
     self._name = name
     self._symbol_table = SymbolTable(self)
Esempio n. 25
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
Esempio n. 26
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
Esempio n. 27
0
This should output a Fortran representation of the LFRic-PSyIR.

'''
# pylint: disable=no-member
from __future__ import print_function
from psyclone.psyir.nodes import Call, Reference, Container, KernelSchedule
from psyclone.psyir.symbols import RoutineSymbol, SymbolTable, \
    ArgumentInterface
from psyclone.domain.lfric import psyir as lfric_psyir
from psyclone.psyir.backend.fortran import FortranWriter

READ_ARG = ArgumentInterface(ArgumentInterface.Access.READ)

# Add LFRic precision symbols and the module in which they are
# contained to the symbol table
SYMBOL_TABLE = SymbolTable()
for symbol in [
        lfric_psyir.I_DEF, lfric_psyir.R_DEF, lfric_psyir.CONSTANTS_MOD
]:
    SYMBOL_TABLE.add(symbol)

# Create LFRic ndf and undf symbols and add them to the symbol table
NDF_W3 = lfric_psyir.NumberOfDofsDataSymbol("ndf_w3", "w3", interface=READ_ARG)
UNDF_W3 = lfric_psyir.NumberOfUniqueDofsDataSymbol("undf_w3",
                                                   "w3",
                                                   interface=READ_ARG)
for symbol in [NDF_W3, UNDF_W3]:
    SYMBOL_TABLE.add(symbol)

# Create LFRic field data symbols and add them to the symbol table
FIELD1 = lfric_psyir.RealFieldDataDataSymbol("field1", [Reference(UNDF_W3)],
Esempio n. 28
0
>>> python create_structure_types.py

'''
from __future__ import print_function
from psyclone.psyir.nodes import Literal, KernelSchedule, Container, \
    StructureReference, ArrayOfStructuresReference, Assignment, \
    BinaryOperation, Range
from psyclone.psyir.symbols import DataSymbol, SymbolTable, StructureType, \
    ContainerSymbol, ArgumentInterface, ScalarType, ArrayType, TypeSymbol, \
    GlobalInterface, INTEGER_TYPE, INTEGER4_TYPE, INTEGER8_TYPE, \
    DeferredType, Symbol
from psyclone.psyir.backend.fortran import FortranWriter


# Symbol table for container (container itself created after kernel)
CONTAINER_SYMBOL_TABLE = SymbolTable()
REAL_KIND = CONTAINER_SYMBOL_TABLE.new_symbol(
        root_name="RKIND", symbol_type=DataSymbol, datatype=INTEGER_TYPE,
        constant_value=8)

# Shorthand for a scalar type with REAL_KIND precision
SCALAR_TYPE = ScalarType(ScalarType.Intrinsic.REAL, REAL_KIND)

# Derived-type definition in container
GRID_TYPE = StructureType.create([
    ("dx", SCALAR_TYPE, Symbol.Visibility.PUBLIC),
    ("dy", SCALAR_TYPE, Symbol.Visibility.PUBLIC)])
GRID_TYPE_SYMBOL = TypeSymbol("grid_type", GRID_TYPE)
CONTAINER_SYMBOL_TABLE.add(GRID_TYPE_SYMBOL)

# Kernel symbol table, symbols and scalar datatypes
Esempio n. 29
0
def create_psyir_tree():
    ''' Create an example PSyIR Tree.

    :returns: an example PSyIR tree.
    :rtype: :py:class:`psyclone.psyir.nodes.Container`

    '''
    # Symbol table, symbols and scalar datatypes
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    symbol_table.specify_argument_list([arg1])
    tmp_symbol = symbol_table.new_symbol(symbol_type=DataSymbol,
                                         datatype=REAL_DOUBLE_TYPE)
    index_symbol = symbol_table.new_symbol(root_name="i",
                                           symbol_type=DataSymbol,
                                           datatype=INTEGER4_TYPE)
    real_kind = symbol_table.new_symbol(root_name="RKIND",
                                        symbol_type=DataSymbol,
                                        datatype=INTEGER_TYPE,
                                        constant_value=8)
    routine_symbol = RoutineSymbol("my_sub")

    # Array using precision defined by another symbol
    scalar_type = ScalarType(ScalarType.Intrinsic.REAL, real_kind)
    array = symbol_table.new_symbol(root_name="a",
                                    symbol_type=DataSymbol,
                                    datatype=ArrayType(scalar_type, [10]))

    # Make generators for nodes which do not have other Nodes as children,
    # with some predefined scalar datatypes
    def zero():
        return Literal("0.0", REAL_TYPE)

    def one():
        return Literal("1.0", REAL4_TYPE)

    def two():
        return Literal("2.0", scalar_type)

    def int_zero():
        return Literal("0", INTEGER_SINGLE_TYPE)

    def int_one():
        return Literal("1", INTEGER8_TYPE)

    def tmp1():
        return Reference(arg1)

    def tmp2():
        return Reference(tmp_symbol)

    # Unary Operation
    oper = UnaryOperation.Operator.SIN
    unaryoperation = UnaryOperation.create(oper, tmp2())

    # Binary Operation
    oper = BinaryOperation.Operator.ADD
    binaryoperation = BinaryOperation.create(oper, one(), unaryoperation)

    # Nary Operation
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, [tmp1(), tmp2(), one()])

    # Array reference using a range
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array), int_one())
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array), int_one())
    my_range = Range.create(lbound, ubound)
    tmparray = ArrayReference.create(array, [my_range])

    # Assignments
    assign1 = Assignment.create(tmp1(), zero())
    assign2 = Assignment.create(tmp2(), zero())
    assign3 = Assignment.create(tmp2(), binaryoperation)
    assign4 = Assignment.create(tmp1(), tmp2())
    assign5 = Assignment.create(tmp1(), naryoperation)
    assign6 = Assignment.create(tmparray, two())

    # Call
    call = Call.create(routine_symbol, [tmp1(), binaryoperation.copy()])

    # If statement
    if_condition = BinaryOperation.create(BinaryOperation.Operator.GT, tmp1(),
                                          zero())
    ifblock = IfBlock.create(if_condition, [assign3, assign4])

    # Loop
    loop = Loop.create(index_symbol, int_zero(), int_one(), int_one(),
                       [ifblock])

    # KernelSchedule
    kernel_schedule = KernelSchedule.create(
        "work", symbol_table, [assign1, call, assign2, loop, assign5, assign6])

    # Container
    container_symbol_table = SymbolTable()
    container = Container.create("CONTAINER", container_symbol_table,
                                 [kernel_schedule])

    # Import data from another container
    external_container = ContainerSymbol("some_mod")
    container_symbol_table.add(external_container)
    external_var = DataSymbol("some_var",
                              INTEGER_TYPE,
                              interface=GlobalInterface(external_container))
    container_symbol_table.add(external_var)
    routine_symbol.interface = GlobalInterface(external_container)
    container_symbol_table.add(routine_symbol)
    return container
Esempio n. 30
0
def create_psyir_tree():
    ''' Create an example PSyIR Tree.

    :returns: an example PSyIR tree.
    :rtype: :py:class:`psyclone.psyir.nodes.Container`

    '''
    # Symbol table, symbols and scalar datatypes
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    symbol_table.specify_argument_list([arg1])
    tmp_symbol = symbol_table.new_symbol(symbol_type=DataSymbol,
                                         datatype=REAL_DOUBLE_TYPE)
    index_symbol = symbol_table.new_symbol(root_name="i",
                                           symbol_type=DataSymbol,
                                           datatype=INTEGER4_TYPE)
    real_kind = symbol_table.new_symbol(root_name="RKIND",
                                        symbol_type=DataSymbol,
                                        datatype=INTEGER_TYPE,
                                        constant_value=8)
    routine_symbol = RoutineSymbol("my_sub")

    # Array using precision defined by another symbol
    scalar_type = ScalarType(ScalarType.Intrinsic.REAL, real_kind)
    array = symbol_table.new_symbol(root_name="a",
                                    symbol_type=DataSymbol,
                                    datatype=ArrayType(scalar_type, [10]))

    # Nodes which do not have Nodes as children and (some) predefined
    # scalar datatypes
    # TODO: Issue #1136 looks at how to avoid all of the _x versions
    zero_1 = Literal("0.0", REAL_TYPE)
    zero_2 = Literal("0.0", REAL_TYPE)
    zero_3 = Literal("0.0", REAL_TYPE)
    one_1 = Literal("1.0", REAL4_TYPE)
    one_2 = Literal("1.0", REAL4_TYPE)
    one_3 = Literal("1.0", REAL4_TYPE)
    two = Literal("2.0", scalar_type)
    int_zero = Literal("0", INTEGER_SINGLE_TYPE)
    int_one_1 = Literal("1", INTEGER8_TYPE)
    int_one_2 = Literal("1", INTEGER8_TYPE)
    int_one_3 = Literal("1", INTEGER8_TYPE)
    int_one_4 = Literal("1", INTEGER8_TYPE)
    tmp1_1 = Reference(arg1)
    tmp1_2 = Reference(arg1)
    tmp1_3 = Reference(arg1)
    tmp1_4 = Reference(arg1)
    tmp1_5 = Reference(arg1)
    tmp1_6 = Reference(arg1)
    tmp2_1 = Reference(tmp_symbol)
    tmp2_2 = Reference(tmp_symbol)
    tmp2_3 = Reference(tmp_symbol)
    tmp2_4 = Reference(tmp_symbol)
    tmp2_5 = Reference(tmp_symbol)
    tmp2_6 = Reference(tmp_symbol)

    # Unary Operation
    oper = UnaryOperation.Operator.SIN
    unaryoperation_1 = UnaryOperation.create(oper, tmp2_1)
    unaryoperation_2 = UnaryOperation.create(oper, tmp2_2)

    # Binary Operation
    oper = BinaryOperation.Operator.ADD
    binaryoperation_1 = BinaryOperation.create(oper, one_1, unaryoperation_1)
    binaryoperation_2 = BinaryOperation.create(oper, one_2, unaryoperation_2)

    # Nary Operation
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, [tmp1_1, tmp2_3, one_3])

    # Array reference using a range
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array), int_one_1)
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array), int_one_2)
    my_range = Range.create(lbound, ubound)
    tmparray = ArrayReference.create(array, [my_range])

    # Assignments
    assign1 = Assignment.create(tmp1_2, zero_1)
    assign2 = Assignment.create(tmp2_4, zero_2)
    assign3 = Assignment.create(tmp2_5, binaryoperation_1)
    assign4 = Assignment.create(tmp1_3, tmp2_6)
    assign5 = Assignment.create(tmp1_4, naryoperation)
    assign6 = Assignment.create(tmparray, two)

    # Call
    call = Call.create(routine_symbol, [tmp1_5, binaryoperation_2])

    # If statement
    if_condition = BinaryOperation.create(BinaryOperation.Operator.GT, tmp1_6,
                                          zero_3)
    ifblock = IfBlock.create(if_condition, [assign3, assign4])

    # Loop
    loop = Loop.create(index_symbol, int_zero, int_one_3, int_one_4, [ifblock])

    # KernelSchedule
    kernel_schedule = KernelSchedule.create(
        "work", symbol_table, [assign1, call, assign2, loop, assign5, assign6])

    # Container
    container_symbol_table = SymbolTable()
    container = Container.create("CONTAINER", container_symbol_table,
                                 [kernel_schedule])

    # Import data from another container
    external_container = ContainerSymbol("some_mod")
    container_symbol_table.add(external_container)
    external_var = DataSymbol("some_var",
                              INTEGER_TYPE,
                              interface=GlobalInterface(external_container))
    container_symbol_table.add(external_var)
    routine_symbol.interface = GlobalInterface(external_container)
    container_symbol_table.add(routine_symbol)
    return container