Beispiel #1
0
def test_profile_node_create():
    ''' Basic checks for the create() method of ProfileNode. '''
    sched = KernelSchedule.create("test", SymbolTable(), [])
    pnode = ProfileNode.create([], SymbolTable())
    sched.addchild(pnode)
    assert str(pnode) == ("ProfileStart[var=profile_psy_data]\n" "ProfileEnd")
    pnode2 = ProfileNode.create([],
                                symbol_table=sched.symbol_table,
                                options={"region_name": ("my_mod", "first")})
    assert pnode2._module_name == "my_mod"
    assert pnode2._region_name == "first"
    # Check that the symbol table contains the appropriate symbols:
    # A Container for the profile_psy_data_mod module
    table = sched.symbol_table
    csym = table.lookup("profile_psy_data_mod")
    assert isinstance(csym, ContainerSymbol)
    # A type symbol for the derived type used to capture profiling data
    type_sym = table.lookup("profile_PSyDataType")
    assert isinstance(type_sym, TypeSymbol)
    assert isinstance(type_sym.interface, GlobalInterface)
    assert type_sym.interface.container_symbol is csym
    # A symbol of derived type to contain the profiling data. As it must
    # have the (unsupported) 'save' and 'target' attributes, it has to be of
    # UnknownFortranType.
    dsym = table.lookup("profile_psy_data")
    assert isinstance(dsym, DataSymbol)
    assert isinstance(dsym.datatype, UnknownFortranType)
    assert (dsym.datatype.declaration ==
            "type(profile_PSyDataType), save, target :: profile_psy_data")
Beispiel #2
0
def test_lower_to_lang_level_single_node():
    ''' Test the lower_to_language_level() method when a Schedule contains
    a single ProfileNode.

    '''
    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)
    one = Literal("1.0", REAL_TYPE)
    assign1 = Assignment.create(Reference(arg1), zero)
    assign2 = Assignment.create(Reference(arg1), one)

    kschedule = KernelSchedule.create(
        "work1", symbol_table, [assign1, assign2, Return()])
    Profiler.add_profile_nodes(kschedule, Loop)
    assert isinstance(kschedule.children[0], ProfileNode)
    assert isinstance(kschedule.children[-1], Return)
    kschedule.lower_to_language_level()
    # The ProfileNode should have been replaced by two CodeBlocks with its
    # children inserted between them.
    assert isinstance(kschedule[0], CodeBlock)
    # The first CodeBlock should have the "profile-start" annotation.
    assert kschedule[0].annotations == ["profile-start"]
    ptree = kschedule[0].get_ast_nodes
    assert len(ptree) == 1
    assert isinstance(ptree[0], Fortran2003.Call_Stmt)
    assert kschedule[1] is assign1
    assert kschedule[2] is assign2
    assert isinstance(kschedule[-2], CodeBlock)
    assert kschedule[-2].annotations == []
    ptree = kschedule[-2].get_ast_nodes
    assert len(ptree) == 1
    assert isinstance(ptree[0], Fortran2003.Call_Stmt)
    assert isinstance(kschedule[-1], Return)
Beispiel #3
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()
    arg1 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    arg2 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    arg3 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    arg4 = symbol_table.new_symbol(symbol_type=DataSymbol, datatype=REAL_TYPE)
    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
Beispiel #4
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
Beispiel #5
0
def test_scope():
    '''Test that the scope method in a Node instance returns the closest
    ancestor Schedule or Container Node (including itself) or raises
    an exception if one does not exist.

    '''
    kernel_symbol_table = SymbolTable()
    symbol = DataSymbol("tmp", REAL_TYPE)
    kernel_symbol_table.add(symbol)
    ref = Reference(symbol)
    assign = Assignment.create(ref, Literal("0.0", REAL_TYPE))
    kernel_schedule = KernelSchedule.create("my_kernel", kernel_symbol_table,
                                            [assign])
    container = Container.create("my_container", SymbolTable(),
                                 [kernel_schedule])
    assert ref.scope is kernel_schedule
    assert assign.scope is kernel_schedule
    assert kernel_schedule.scope is kernel_schedule
    assert container.scope is container

    anode = Literal("x", INTEGER_TYPE)
    with pytest.raises(SymbolError) as excinfo:
        _ = anode.scope
    assert ("Unable to find the scope of node "
            "'Literal[value:'x', Scalar<INTEGER, UNDEFINED>]' as "
            "none of its ancestors are Container or Schedule nodes."
            in str(excinfo.value))
Beispiel #6
0
def test_transform_multi_apply(tmpdir):
    '''Check that the ArrayRange2Loop transformation can be used to create
    nested loops by calling it multiple times when an array has
    multiple dimensions that use a range.

    '''
    trans = ArrayRange2LoopTrans()

    symbol_table = SymbolTable()
    symbol = DataSymbol("n", INTEGER_TYPE)
    symbol_table.add(symbol)
    lhs = create_array_y_2d_slice(symbol_table)
    rhs = create_array_z(symbol_table)
    assignment = Assignment.create(lhs, rhs)
    routine = KernelSchedule.create("work", symbol_table, [assignment])
    trans.apply(assignment)
    trans.apply(assignment)
    expected = ("  do idx = LBOUND(y2, 2), UBOUND(y2, 2), 1\n"
                "    do idx_1 = LBOUND(y2, 1), UBOUND(y2, 1), 1\n"
                "      y2(idx_1,idx)=z(idx_1,n,idx)\n"
                "    enddo\n"
                "  enddo\n")
    writer = FortranWriter()
    result = writer(routine)
    assert expected in result
    assert Compile(tmpdir).string_compiles(result)
Beispiel #7
0
def test_transform_apply_insert(tmpdir):
    '''Check that the PSyIR is transformed as expected when there are
    multiple statements in the PSyIR. 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)
    # Create the first assignment. In Fortran notation: x(:) = y(n,:)
    lhs = create_array_x(symbol_table)
    rhs = create_array_y(symbol_table)
    assignment1 = Assignment.create(lhs, rhs)
    # Create the second assignment. In Fortran notation: y2(:,:) = z(:,n,:)
    lhs = create_array_y_2d_slice(symbol_table)
    rhs = create_array_z(symbol_table)
    assignment2 = Assignment.create(lhs, rhs)
    routine = KernelSchedule.create("work", symbol_table,
                                    [assignment1, assignment2])
    trans.apply(assignment1)
    trans.apply(assignment2)
    writer = FortranWriter()
    expected = ("  do idx = LBOUND(x, 1), UBOUND(x, 1), 1\n"
                "    x(idx)=y(n,idx)\n"
                "  enddo\n"
                "  do idx_1 = LBOUND(y2, 2), UBOUND(y2, 2), 1\n"
                "    y2(:,idx_1)=z(:,n,idx_1)\n"
                "  enddo\n")
    result = writer(routine)
    assert expected in result
    assert Compile(tmpdir).string_compiles(result)
Beispiel #8
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()
    arg1 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    arg2 = symbol_table.new_symbol("arg",
                                   symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    arg3 = symbol_table.new_symbol(symbol_type=DataSymbol, datatype=REAL_TYPE)
    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
Beispiel #9
0
def test_container_create_invalid():
    '''Test that the create method in a Container class raises the
    expected exception if the provided input is invalid.

    '''
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("x", REAL_SINGLE_TYPE))
    children = [KernelSchedule.create("mod_1", SymbolTable(), [])]

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

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

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

    # contents of children list are not Container or KernelSchedule.
    with pytest.raises(GenerationError) as excinfo:
        _ = Container.create("mod_name", symbol_table, ["invalid"])
    assert ("Item 'str' can't be child 0 of 'Container'. The valid format is:"
            " '[Container | KernelSchedule | InvokeSchedule]*'."
            in str(excinfo.value))
def test_find_or_create_change_symbol_type():
    ''' Check that the _find_or_create_imported_symbol routine correctly
    updates the class of the located symbol if it is not an instance of
    the requested symbol type.
    '''
    # pylint: disable=unidiomatic-typecheck
    # Create some suitable PSyIR from scratch
    symbol_table = SymbolTable()
    tmp_sym = symbol_table.new_symbol("tmp")
    sub_sym = symbol_table.new_symbol("my_sub")
    kernel1 = KernelSchedule.create("mod_1", SymbolTable(), [])
    _ = Container.create("container_name", symbol_table, [kernel1])
    assign = Assignment.create(Reference(tmp_sym), Literal("1.0", REAL_TYPE))
    kernel1.addchild(assign)
    # Search for the 'tmp' symbol
    sym = _find_or_create_imported_symbol(assign, "tmp")
    assert sym is tmp_sym
    assert type(sym) == Symbol
    # Repeat but this time specify that we're expecting a DataSymbol
    sym = _find_or_create_imported_symbol(assign,
                                          "tmp",
                                          symbol_type=DataSymbol,
                                          datatype=REAL_TYPE)
    assert sym is tmp_sym
    assert type(sym) == DataSymbol
    assert sym.datatype == REAL_TYPE
    # Search for 'my_sub' and specify that it should be a RoutineSymbol
    sym2 = _find_or_create_imported_symbol(assign,
                                           "my_sub",
                                           symbol_type=RoutineSymbol)
    assert sym2 is sub_sym
    assert type(sym2) == RoutineSymbol
def test_find_or_create_imported_symbol_2():
    ''' Check that the _find_or_create_imported_symbol() method creates new
    symbols when appropriate. '''
    # Create some suitable PSyIR from scratch
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("tmp", REAL_TYPE))
    kernel1 = KernelSchedule.create("mod_1", SymbolTable(), [])
    container = Container.create("container_name", symbol_table, [kernel1])
    xvar = DataSymbol("x", REAL_TYPE)
    xref = Reference(xvar)
    assign = Assignment.create(xref, Literal("1.0", REAL_TYPE))
    kernel1.addchild(assign)
    # We have no wildcard imports so there can be no symbol named 'undefined'
    with pytest.raises(SymbolError) as err:
        _ = _find_or_create_imported_symbol(assign, "undefined")
    assert "No Symbol found for name 'undefined'" in str(err.value)
    # We should be able to find the 'tmp' symbol in the parent Container
    sym = _find_or_create_imported_symbol(assign, "tmp")
    assert sym.datatype.intrinsic == ScalarType.Intrinsic.REAL
    # Add a wildcard import to the SymbolTable of the KernelSchedule
    new_container = ContainerSymbol("some_mod")
    new_container.wildcard_import = True
    kernel1.symbol_table.add(new_container)
    # Symbol not in any container but we do have wildcard imports so we
    # get a new symbol back
    new_symbol = _find_or_create_imported_symbol(assign, "undefined")
    assert new_symbol.name == "undefined"
    assert isinstance(new_symbol.interface, UnresolvedInterface)
    # pylint: disable=unidiomatic-typecheck
    assert type(new_symbol) == Symbol
    assert "undefined" not in container.symbol_table
    assert kernel1.symbol_table.lookup("undefined") is new_symbol
Beispiel #12
0
def create_matmul():
    '''Utility function that creates a valid matmul node for use with
    subsequent tests.

    '''
    symbol_table = SymbolTable()
    one = Literal("1", INTEGER_TYPE)
    two = Literal("2", INTEGER_TYPE)
    index = DataSymbol("idx", INTEGER_TYPE, constant_value=3)
    symbol_table.add(index)
    array_type = ArrayType(REAL_TYPE, [5, 10, 15])
    mat_symbol = DataSymbol("x", array_type)
    symbol_table.add(mat_symbol)
    lbound1 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(mat_symbol), one.copy())
    ubound1 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(mat_symbol), one.copy())
    my_mat_range1 = Range.create(lbound1, ubound1, one.copy())
    lbound2 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(mat_symbol), two.copy())
    ubound2 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(mat_symbol), two.copy())
    my_mat_range2 = Range.create(lbound2, ubound2, one.copy())
    matrix = ArrayReference.create(
        mat_symbol, [my_mat_range1, my_mat_range2,
                     Reference(index)])
    array_type = ArrayType(REAL_TYPE, [10, 20])
    vec_symbol = DataSymbol("y", array_type)
    symbol_table.add(vec_symbol)
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(vec_symbol), one.copy())
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(vec_symbol), one.copy())
    my_vec_range = Range.create(lbound, ubound, one.copy())
    vector = ArrayReference.create(
        vec_symbol, [my_vec_range, Reference(index)])
    matmul = BinaryOperation.create(BinaryOperation.Operator.MATMUL, matrix,
                                    vector)
    lhs_type = ArrayType(REAL_TYPE, [10])
    lhs_symbol = DataSymbol("result", lhs_type)
    symbol_table.add(lhs_symbol)
    lhs = Reference(lhs_symbol)
    assign = Assignment.create(lhs, matmul)
    KernelSchedule.create("my_kern", symbol_table, [assign])
    return matmul
Beispiel #13
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)
Beispiel #14
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)
Beispiel #15
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")
Beispiel #16
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)
Beispiel #17
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)
Beispiel #18
0
def test_auto_invoke_return_last_stmt(parser):
    ''' 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)
Beispiel #19
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]))
Beispiel #20
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")
Beispiel #21
0
ASSIGN4 = Assignment.create(TMP1, TMP2)
ASSIGN5 = Assignment.create(TMP1, NARYOPERATION)
ASSIGN6 = Assignment.create(TMPARRAY, TWO)

# Call
CALL = Call.create(ROUTINE_SYMBOL, [TMP1, BINARYOPERATION])

# 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, [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)
Beispiel #22
0
    interface=READ_ARG)
for symbol in [NQP_XY, NQP_Z, WEIGHTS_XY, WEIGHTS_Z, BASIS_W3, DIFF_BASIS_W3]:
    SYMBOL_TABLE.add(symbol)

SYMBOL_TABLE.specify_argument_list([
    NDF_W3, UNDF_W3, NCELL_3D, FIELD2, OPERATOR, NQP_XY, NQP_Z, WEIGHTS_XY,
    WEIGHTS_Z, BASIS_W3, DIFF_BASIS_W3
])

# Routine symbol
ROUTINE_SYMBOL = RoutineSymbol("my_sub")

# Call
CALL = Call.create(ROUTINE_SYMBOL,
                   [Reference(FIELD1),
                    Reference(FIELD2),
                    Reference(OPERATOR)])

# KernelSchedule
KERNEL_SCHEDULE = KernelSchedule.create("work", SYMBOL_TABLE, [CALL])

# Container
CONTAINER_SYMBOL_TABLE = SymbolTable()
CONTAINER = Container.create("CONTAINER", CONTAINER_SYMBOL_TABLE,
                             [KERNEL_SCHEDULE])

# Write out the code as Fortran
WRITER = FortranWriter()
RESULT = WRITER(CONTAINER)
print(RESULT)
DATA_REF = StructureReference.create(FIELD_SYMBOL, [("data", [MY_RANGE])])

# Reference to "field%sub_meshes(1)%dx"
DX_REF2 = StructureReference.create(FIELD_SYMBOL, [("sub_meshes", [INT_ONE]),
                                                   "dx"])

# Reference to "chi(1)%sub_meshes(1)%dx"
DX_REF3 = ArrayOfStructuresReference.create(FIELD_BUNDLE_SYMBOL, [INT_ONE],
                                            [("sub_meshes", [INT_ONE]), "dx"])

ASSIGNMENTS = [
    Assignment.create(DX_REF, TWO),
    Assignment.create(FLAG_REF, INT_ONE),
    Assignment.create(DATA_REF, TWO),
    Assignment.create(DX_REF2, TWO),
    Assignment.create(DX_REF3, TWO)]

# KernelSchedule
KERNEL_SCHEDULE = KernelSchedule.create("work", SYMBOL_TABLE, ASSIGNMENTS)

# Container
CONTAINER = Container.create("CONTAINER", CONTAINER_SYMBOL_TABLE,
                             [KERNEL_SCHEDULE])
CONTAINER.view()

# Write out the code as Fortran.
WRITER = FortranWriter()
RESULT = WRITER(CONTAINER)
print("\n")
print(RESULT)
Beispiel #24
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
Beispiel #25
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