コード例 #1
0
ファイル: assignment_test.py プロジェクト: stfc/PSyclone
def test_array_range_with_reduction():
    ''' Test that we correctly identify an array range when it is the result
        of a reduction from an array, e.g x(1, INT(SUM(map(:, :), 1))) = 1.0

    '''
    one = Literal("1.0", REAL_TYPE)
    int_one = Literal("1", INTEGER_TYPE)
    int_two = Literal("2", INTEGER_TYPE)
    int_array_type = ArrayType(INTEGER_SINGLE_TYPE, [10, 10])
    map_sym = DataSymbol("map", int_array_type)
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("x", array_type)
    lbound1 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(map_sym), int_one.copy())
    ubound1 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(map_sym), int_one.copy())
    my_range1 = Range.create(lbound1, ubound1)
    lbound2 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(map_sym), int_two.copy())
    ubound2 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(map_sym), int_two.copy())
    my_range2 = Range.create(lbound2, ubound2)
    bsum_op = BinaryOperation.create(
        BinaryOperation.Operator.SUM,
        ArrayReference.create(map_sym, [my_range1, my_range2]), int_one.copy())
    int_op2 = UnaryOperation.create(UnaryOperation.Operator.INT, bsum_op)
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), int_op2]), one.copy())
    assert assignment.is_array_range is True
コード例 #2
0
ファイル: range_test.py プロジェクト: stfc/PSyclone
def test_range_create():
    ''' Check that the Range.create() method behaves as intended. '''
    start = Literal("1", INTEGER_SINGLE_TYPE)
    stop = Literal("10", INTEGER_SINGLE_TYPE)
    # No step
    erange = Range.create(start, stop)
    assert erange.children[0] is start
    assert erange.children[1] is stop
    assert erange.children[2].value == "1"
    # Step supplied
    erange3 = Range.create(start.copy(), stop.copy(),
                           Literal("5", INTEGER_SINGLE_TYPE),)
    assert erange3.children[2].value == "5"
コード例 #3
0
def test_reference_accesses_bounds(operator_type):
    '''Test that the reference_accesses method behaves as expected when
    the reference is the first argument to either the lbound or ubound
    intrinsic as that is simply looking up the array bounds (therefore
    var_access_info should be empty) and when the reference is the
    second argument of either the lbound or ubound intrinsic (in which
    case the access should be a read).

    '''
    # Note, one would usually expect UBOUND to provide the upper bound
    # of a range but to simplify the test both LBOUND and UBOUND are
    # used for the lower bound. This does not affect the test.
    one = Literal("1", INTEGER_TYPE)
    array_symbol = DataSymbol("test", ArrayType(REAL_TYPE, [10]))
    array_ref1 = Reference(array_symbol)
    array_ref2 = Reference(array_symbol)
    array_access = Array.create(array_symbol, [one])

    # test when first or second argument to LBOUND or UBOUND is an
    # array reference
    operator = BinaryOperation.create(operator_type, array_ref1, array_ref2)
    array_access.children[0] = Range.create(operator, one, one)
    var_access_info = VariablesAccessInfo()
    array_ref1.reference_accesses(var_access_info)
    assert str(var_access_info) == ""
    var_access_info = VariablesAccessInfo()
    array_ref2.reference_accesses(var_access_info)
    assert str(var_access_info) == "test: READ"
コード例 #4
0
ファイル: assignment_test.py プロジェクト: mfkiwl/PSyclone
def test_is_array_range():
    '''test that the is_array_range method behaves as expected, returning
    true if the LHS of the assignment is an array range access and
    false otherwise.

    '''
    one = Literal("1.0", REAL_TYPE)
    int_one = Literal("1", INTEGER_TYPE)
    var = DataSymbol("x", REAL_TYPE)
    reference = Reference(var)

    # lhs is not an array
    assignment = Assignment.create(reference, one)
    assert not assignment.is_array_range

    # lhs is an array reference but has no range
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("x", array_type)
    array_ref = ArrayReference(symbol, [1, 3])
    assignment = Assignment.create(array_ref, one)
    assert not assignment.is_array_range

    # lhs is an array reference with a range
    my_range = Range.create(int_one, int_one, int_one)
    array_ref = ArrayReference.create(symbol, [my_range, int_one])
    assignment = Assignment.create(array_ref, one)
    assert assignment.is_array_range
コード例 #5
0
ファイル: range_test.py プロジェクト: mfkiwl/PSyclone
def test_range_references_props():
    ''' Test that the properties of a Range return what we expect
    when the start, stop and step are references or expressions. '''
    from psyclone.psyir.nodes import BinaryOperation, KernelSchedule
    sched = KernelSchedule("test_sched")
    sym_table = sched.symbol_table
    start_symbol = DataSymbol("istart", INTEGER_SINGLE_TYPE)
    stop_symbol = DataSymbol("istop", INTEGER_SINGLE_TYPE)
    step_symbol = DataSymbol("istep", INTEGER_SINGLE_TYPE)
    sym_table.add(start_symbol)
    sym_table.add(stop_symbol)
    sym_table.add(step_symbol)
    startvar = Reference(start_symbol)
    stopvar = Reference(stop_symbol)
    start = BinaryOperation.create(BinaryOperation.Operator.SUB, startvar,
                                   Literal("1", INTEGER_SINGLE_TYPE))
    stop = BinaryOperation.create(BinaryOperation.Operator.ADD, stopvar,
                                  Literal("1", INTEGER_SINGLE_TYPE))
    step = Reference(step_symbol)
    erange = Range.create(start, stop, step)
    assert erange.start is start
    assert erange.stop is stop
    assert erange.step is step
    assert erange.children[0] is start
    assert erange.children[1] is stop
    assert erange.children[2] is step
コード例 #6
0
ファイル: test_range.py プロジェクト: xyuan/PSyclone
def test_range_view(capsys):
    ''' Check that calling view() on an array with a child Range works
    as expected. '''
    from psyclone.psyir.nodes import Array
    from psyclone.psyir.nodes.node import colored, SCHEDULE_COLOUR_MAP
    # Create the PSyIR for 'my_array(1, 1:10)'
    erange = Range.create(Literal("1", INTEGER_SINGLE_TYPE),
                          Literal("10", INTEGER_SINGLE_TYPE))
    array_type = ArrayType(REAL_SINGLE_TYPE, [10, 10])
    array = Array.create(DataSymbol("my_array", array_type),
                         [Literal("1", INTEGER_SINGLE_TYPE), erange])
    array.view()
    stdout, _ = capsys.readouterr()
    arrayref = colored("ArrayReference",
                       SCHEDULE_COLOUR_MAP[array._colour_key])
    literal = colored("Literal",
                      SCHEDULE_COLOUR_MAP[array.children[0]._colour_key])
    rangestr = colored("Range", SCHEDULE_COLOUR_MAP[erange._colour_key])
    indent = "    "
    assert (arrayref + "[name:'my_array']\n" + indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + indent + rangestr +
            "[]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'10', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, UNDEFINED>]\n" in stdout)
コード例 #7
0
ファイル: assignment_test.py プロジェクト: stfc/PSyclone
def test_is_not_array_range():
    ''' Test that is_array_range correctly rejects things that aren't
    an assignment to an array range.

    '''
    int_one = Literal("1", INTEGER_SINGLE_TYPE)
    one = Literal("1.0", REAL_TYPE)
    var = DataSymbol("x", REAL_TYPE)
    reference = Reference(var)

    # lhs is not an array
    assignment = Assignment.create(reference, one)
    assert assignment.is_array_range is False

    # lhs is an array reference but has no range
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("y", array_type)
    array_ref = Reference(symbol)
    assignment = Assignment.create(array_ref, one.copy())
    assert assignment.is_array_range is False

    # lhs is an array reference but the single index value is obtained
    # using an array range, y(1, SUM(map(:), 1)) = 1.0
    int_array_type = ArrayType(INTEGER_SINGLE_TYPE, [10])
    map_sym = DataSymbol("map", int_array_type)
    start = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                   Reference(map_sym), int_one.copy())
    stop = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                  Reference(map_sym), int_one.copy())
    my_range = Range.create(start, stop)
    sum_op = BinaryOperation.create(BinaryOperation.Operator.SUM,
                                    ArrayReference.create(map_sym, [my_range]),
                                    int_one.copy())
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), sum_op]), one.copy())
    assert assignment.is_array_range is False

    # When the slice has two operator ancestors, one of which is a reduction
    # e.g y(1, SUM(ABS(map(:)), 1)) = 1.0
    abs_op = UnaryOperation.create(
        UnaryOperation.Operator.ABS,
        ArrayReference.create(map_sym, [my_range.copy()]))
    sum_op2 = BinaryOperation.create(BinaryOperation.Operator.SUM, abs_op,
                                     int_one.copy())
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), sum_op2]), one.copy())
    assert assignment.is_array_range is False

    # lhs is a scalar member of a structure
    grid_type = StructureType.create([
        ("dx", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC),
        ("dy", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC)
    ])
    grid_type_symbol = DataTypeSymbol("grid_type", grid_type)
    grid_sym = DataSymbol("grid", grid_type_symbol)
    assignment = Assignment.create(StructureReference.create(grid_sym, ["dx"]),
                                   one.copy())
    assert assignment.is_array_range is False
コード例 #8
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
コード例 #9
0
def test_array_is_lower_bound():
    '''Test that the is_lower_bound method in the Array Node works as
    expected.

    '''
    one = Literal("1", INTEGER_TYPE)
    array = ArrayReference.create(DataSymbol("test",
                                             ArrayType(REAL_TYPE, [10])),
                                  [one])
    with pytest.raises(TypeError) as info:
        array.is_lower_bound("hello")
    assert ("The index argument should be an integer but found 'str'."
            in str(info.value))

    # not a range node at index 0
    assert not array.is_lower_bound(0)

    # range node does not have a binary operator for its start value
    array.children[0] = Range.create(one, one, one)
    assert not array.is_lower_bound(0)

    # range node lbound references a different array
    array2 = ArrayReference.create(DataSymbol("test2",
                                              ArrayType(REAL_TYPE, [10])),
                                   [one])
    operator = BinaryOperation.create(
        BinaryOperation.Operator.LBOUND, array2,
        Literal("1", INTEGER_TYPE))
    array.children[0] = Range.create(operator, one, one)
    assert not array.is_lower_bound(0)

    # range node lbound references a different index
    operator = BinaryOperation.create(
        BinaryOperation.Operator.LBOUND, array,
        Literal("2", INTEGER_TYPE))
    array.children[0] = Range.create(operator, one, one)
    assert not array.is_lower_bound(0)

    # all is well
    operator = BinaryOperation.create(
        BinaryOperation.Operator.LBOUND, array, one)
    array.children[0] = Range.create(operator, one, one)
    assert array.is_lower_bound(0)
コード例 #10
0
ファイル: range_test.py プロジェクト: mfkiwl/PSyclone
def test_range_create():
    ''' Check that the Range.create() method behaves as intended. '''
    parent = Node()
    start = Literal("1", INTEGER_SINGLE_TYPE)
    stop = Literal("10", INTEGER_SINGLE_TYPE)
    # No parent and no step
    erange = Range.create(start, stop)
    assert erange.children[0] is start
    assert erange.children[1] is stop
    assert erange.parent is None
    # Parent but no step
    erange2 = Range.create(start, stop, parent=parent)
    assert erange2.parent is parent
    assert erange2.children[2].value == "1"
    # Parent and step supplied
    erange3 = Range.create(start,
                           stop,
                           step=Literal("5", INTEGER_SINGLE_TYPE),
                           parent=parent)
    assert erange3.parent is parent
    assert erange3.children[2].value == "5"
コード例 #11
0
ファイル: range_test.py プロジェクト: mfkiwl/PSyclone
def test_range_literals_props():
    ''' Test that the properties of a Range return what we expect
    when the start, stop and step are Literals. '''
    start = Literal("10", INTEGER_SINGLE_TYPE)
    stop = Literal("20", INTEGER_SINGLE_TYPE)
    erange = Range.create(start, stop)
    assert erange.children[0] is start
    assert erange.children[1] is stop
    # We didn't supply an increment so check that one was created
    assert isinstance(erange.children[2], Literal)
    assert (
        erange.children[2].datatype.intrinsic == ScalarType.Intrinsic.INTEGER)
    assert (erange.children[2].datatype.precision ==
            ScalarType.Precision.UNDEFINED)
    assert erange.children[2].value == "1"
    # Create another one with a specified step
    erange2 = Range.create(start, stop, Literal("5", INTEGER_SINGLE_TYPE))
    assert erange2.children[0] is start
    assert erange2.children[1] is stop
    assert (
        erange2.children[2].datatype.precision == ScalarType.Precision.SINGLE)
    assert erange2.step.value == "5"
コード例 #12
0
def create_stepped_range(symbol):
    '''Utility routine that creates and returns a Range Node that
    specifies a range from "2" to "symbol" step "2".

    :param symbol: the symbol representing the upper bound.
    :type symbol: :py:class:`psyclone.psyir.symbol.Symbol`

    :returns: a range node specifying a range from 2 to "symbol" with \
        a step of 2 for the supplied array dimension.
    :rtype: :py:class:`psyclone.psyir.nodes.Range`

    '''
    lbound = Literal("2", INTEGER_TYPE)
    ubound = Reference(symbol)
    step = Literal("2", INTEGER_TYPE)
    return Range.create(lbound, ubound, step)
コード例 #13
0
def test_where_array_notation_rank():
    ''' Test that the _array_notation_rank() utility raises the expected
    errors when passed an unsupported Array object.
    '''
    array_type = ArrayType(REAL_TYPE, [10])
    symbol = DataSymbol("my_array", array_type)
    my_array = Array(symbol)
    processor = Fparser2Reader()
    with pytest.raises(NotImplementedError) as err:
        processor._array_notation_rank(my_array)
    assert ("Array reference in the PSyIR must have at least one child but "
            "'my_array'" in str(err.value))
    from psyclone.psyir.nodes import Range
    array_type = ArrayType(REAL_TYPE, [10])
    my_array = Array.create(DataSymbol("my_array", array_type),
                            [Range.create(Literal("1", INTEGER_TYPE),
                                          Literal("10", INTEGER_TYPE))])
    with pytest.raises(NotImplementedError) as err:
        processor._array_notation_rank(my_array)
    assert ("Only array notation of the form my_array(:, :, ...) is "
            "supported." in str(err.value))
コード例 #14
0
def create_range(array_symbol, dim):
    '''Utility routine that creates and returns a Range Node that
    specifies the full range of the supplied dimension (dim) in the
    array (array_symbol). This is done using the LBOUND and UBOUND
    intrinsics.

    :param array_symbol: the array of interest.
    :type array_symbol: :py:class:`psyclone.psyir.symbol.DataSymbol`
    :param int dim: the dimension of interest in the array.

    :returns: a range node specifying the full range of the supplied \
        array dimension.
    :rtype: :py:class:`psyclone.psyir.nodes.Range`

    '''
    int_dim = Literal(str(dim), INTEGER_TYPE)
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array_symbol), int_dim)
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array_symbol), int_dim)
    return Range.create(lbound, ubound)
コード例 #15
0
ファイル: range_test.py プロジェクト: mfkiwl/PSyclone
def test_range_view(capsys):
    ''' Check that calling view() on an array with a child Range works
    as expected. '''
    # Create the PSyIR for 'my_array(1, 1:10)'
    erange = Range.create(Literal("1", INTEGER_SINGLE_TYPE),
                          Literal("10", INTEGER_SINGLE_TYPE))
    array_type = ArrayType(REAL_SINGLE_TYPE, [10, 10])
    array = ArrayReference.create(DataSymbol("my_array", array_type),
                                  [Literal("1", INTEGER_SINGLE_TYPE), erange])
    array.view()
    stdout, _ = capsys.readouterr()
    arrayref = colored("ArrayReference", ArrayReference._colour)
    literal = colored("Literal", Literal._colour)
    rangestr = colored("Range", Range._colour)
    indent = "    "
    assert (arrayref + "[name:'my_array']\n" + indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + indent + rangestr +
            "[]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'10', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, UNDEFINED>]\n" in stdout)
コード例 #16
0
def test_apply4(tmpdir):
    '''Test that the matmul2code apply method produces the expected
    PSyIR. We use the Fortran backend to help provide the test for
    correctness. This example make the lhs be the same array as the
    second operand of the matmul (the vector in this case).

    '''
    trans = Matmul2CodeTrans()
    one = Literal("1", INTEGER_TYPE)
    five = Literal("5", INTEGER_TYPE)
    matmul = create_matmul()
    root = matmul.root
    assignment = matmul.parent
    vector = assignment.scope.symbol_table.lookup("y")
    assignment.children[0] = ArrayReference.create(
        vector, [Range.create(one, five, one.copy()),
                 one.copy()])
    trans.apply(matmul)
    writer = FortranWriter()
    result = writer(root)
    assert ("subroutine my_kern()\n"
            "  integer, parameter :: idx = 3\n"
            "  real, dimension(5,10,15) :: x\n"
            "  real, dimension(10,20) :: y\n"
            "  real, dimension(10) :: result\n"
            "  integer :: i\n"
            "  integer :: j\n"
            "\n"
            "  do i = 1, 5, 1\n"
            "    y(i,1) = 0.0\n"
            "    do j = 1, 10, 1\n"
            "      y(i,1) = y(i,1) + x(i,j,idx) * y(j,idx)\n"
            "    enddo\n"
            "  enddo\n"
            "\n"
            "end subroutine my_kern" in result)
    assert Compile(tmpdir).string_compiles(result)
コード例 #17
0
INT_ONE = Literal("1", INTEGER8_TYPE)

# Reference to the "flag" scalar component of FIELD_SYMBOL, "field%flag"
FLAG_REF = StructureReference.create(FIELD_SYMBOL, ["flag"])

# Reference to "field%grid%dx"
DX_REF = StructureReference.create(FIELD_SYMBOL, ["grid", "dx"])

# Array reference to component of derived type using a range
LBOUND = BinaryOperation.create(
    BinaryOperation.Operator.LBOUND,
    StructureReference.create(FIELD_SYMBOL, ["data"]), INT_ONE)
UBOUND = BinaryOperation.create(
    BinaryOperation.Operator.UBOUND,
    StructureReference.create(FIELD_SYMBOL, ["data"]), INT_ONE)
MY_RANGE = Range.create(LBOUND, UBOUND)

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),
コード例 #18
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
コード例 #19
0
ファイル: create.py プロジェクト: hiker/PSyclone
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
コード例 #20
0
def test_array_is_full_range():
    '''Test that the is_full_range method in the Array Node works as
    expected. '''
    # pylint: disable=too-many-statements
    zero = Literal("0", INTEGER_SINGLE_TYPE)
    one = Literal("1", INTEGER_SINGLE_TYPE)
    array_type = ArrayType(REAL_SINGLE_TYPE, [10])
    symbol = DataSymbol("my_array", array_type)
    reference = Reference(symbol)
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND, reference,
                                    one)
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND, reference,
                                    one)
    symbol_error = DataSymbol("another_array", array_type)
    reference_error = Reference(symbol_error)

    # Index out of bounds
    array_reference = Array.create(symbol, [one])
    with pytest.raises(ValueError) as excinfo:
        array_reference.is_full_range(1)
    assert ("In Array 'my_array' the specified index '1' must be less than "
            "the number of dimensions '1'." in str(excinfo.value))

    # Array dimension is not a Range
    assert not array_reference.is_full_range(0)

    # Check LBOUND
    # Array dimension range lower bound is not a binary operation
    my_range = Range.create(one, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is not an LBOUND binary operation
    my_range = Range.create(ubound, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is an LBOUND binary operation
    # with the first value not being a reference
    lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                          zero, zero)
    my_range = Range.create(lbound_error, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is an LBOUND binary operation
    # with the first value being a reference to a different symbol
    lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                          reference_error, zero)
    my_range = Range.create(lbound_error, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is an LBOUND binary operation
    # with the second value not being a literal.
    lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                          reference, reference)
    my_range = Range.create(lbound_error, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is an LBOUND binary operation
    # with the second value not being an integer literal.
    lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                          reference,
                                          Literal("1.0", REAL_SINGLE_TYPE))
    my_range = Range.create(lbound_error, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range lower bound is an LBOUND binary operation
    # with the second value being an integer literal with the wrong
    # value (should be 0 as this dimension index is 0).
    lbound_error = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                          reference, one)
    my_range = Range.create(lbound_error, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Check UBOUND
    # Array dimension range upper bound is not a binary operation
    my_range = Range.create(lbound, one, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is not a UBOUND binary operation
    my_range = Range.create(lbound, lbound, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is a UBOUND binary operation
    # with the first value not being a reference
    ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                          zero, zero)
    my_range = Range.create(lbound, ubound_error, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is a UBOUND binary operation
    # with the first value being a reference to a different symbol
    ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                          reference_error, zero)
    my_range = Range.create(lbound, ubound_error, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is a UBOUND binary operation
    # with the second value not being a literal.
    ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                          reference, reference)
    my_range = Range.create(lbound, ubound_error, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is a UBOUND binary operation
    # with the second value not being an integer literal.
    ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                          reference,
                                          Literal("1.0", REAL_SINGLE_TYPE))
    my_range = Range.create(lbound, ubound_error, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range upper bound is a UBOUND binary operation
    # with the second value being an integer literal with the wrong
    # value (should be 1 as this dimension is 1).
    ubound_error = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                          reference, zero)
    my_range = Range.create(lbound, ubound_error, one)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Check Step
    # Array dimension range step is not a literal.
    my_range = Range.create(lbound, ubound, lbound)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range step is not an integer literal.
    my_range = Range.create(lbound, ubound, one)
    # We have to change this to a non-integer manually as the create
    # function only accepts integer literals for the step argument.
    my_range.children[2] = Literal("1.0", REAL_SINGLE_TYPE)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # Array dimension range step is is an integer literal with the
    # wrong value (not 1).
    my_range = Range.create(lbound, ubound, zero)
    array_reference = Array.create(symbol, [my_range])
    assert not array_reference.is_full_range(0)

    # All is as it should be.
    # The full range is covered so return true.
    my_range = Range.create(lbound, ubound, one)
    array_reference = Array.create(symbol, [my_range])
    assert array_reference.is_full_range(0)
コード例 #21
0
ファイル: assignment_test.py プロジェクト: stfc/PSyclone
def test_is_array_range():
    '''test that the is_array_range method behaves as expected, returning
    true if the LHS of the assignment is an array range access.

    '''
    one = Literal("1.0", REAL_TYPE)
    int_one = Literal("1", INTEGER_TYPE)
    int_ten = Literal("10", INTEGER_TYPE)

    # lhs is an array reference with a range
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("x", array_type)
    x_range = Range.create(int_one, int_ten.copy(), int_one.copy())
    array_ref = ArrayReference.create(symbol, [x_range, int_one.copy()])
    assignment = Assignment.create(array_ref, one.copy())
    assert assignment.is_array_range is True

    # Check when lhs consists of various forms of structure access
    grid_type = StructureType.create([
        ("dx", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC),
        ("dy", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC)
    ])
    grid_type_symbol = DataTypeSymbol("grid_type", grid_type)
    # Create the definition of the 'field_type', contains array of grid_types
    field_type_def = StructureType.create([
        ("data", ArrayType(REAL_SINGLE_TYPE, [10]), Symbol.Visibility.PUBLIC),
        ("sub_meshes", ArrayType(grid_type_symbol,
                                 [3]), Symbol.Visibility.PUBLIC)
    ])
    field_type_symbol = DataTypeSymbol("field_type", field_type_def)
    field_symbol = DataSymbol("wind", field_type_symbol)

    # Array reference to component of derived type using a range
    lbound = BinaryOperation.create(
        BinaryOperation.Operator.LBOUND,
        StructureReference.create(field_symbol, ["data"]), int_one.copy())
    ubound = BinaryOperation.create(
        BinaryOperation.Operator.UBOUND,
        StructureReference.create(field_symbol, ["data"]), int_one.copy())
    my_range = Range.create(lbound, ubound)

    data_ref = StructureReference.create(field_symbol, [("data", [my_range])])
    assign = Assignment.create(data_ref, one.copy())
    assert assign.is_array_range is True

    # Access to slice of 'sub_meshes': wind%sub_meshes(1:3)%dx = 1.0
    sub_range = Range.create(int_one.copy(), Literal("3", INTEGER_TYPE))
    dx_ref = StructureReference.create(field_symbol,
                                       [("sub_meshes", [sub_range]), "dx"])
    sub_assign = Assignment.create(dx_ref, one.copy())
    assert sub_assign.is_array_range is True

    # Create an array of these derived types and assign to a slice:
    # chi(1:10)%data(1) = 1.0
    field_bundle_symbol = DataSymbol("chi", ArrayType(field_type_symbol, [3]))
    fld_range = Range.create(int_one.copy(), Literal("10", INTEGER_TYPE))
    fld_ref = ArrayOfStructuresReference.create(field_bundle_symbol,
                                                [fld_range],
                                                [("data", [int_one.copy()])])
    fld_assign = Assignment.create(fld_ref, one.copy())
    assert fld_assign.is_array_range is True

    # When the slice has two operator ancestors, none of which are a reduction
    # e.g y(1, INT(ABS(map(:, 1)))) = 1.0
    int_array_type = ArrayType(INTEGER_SINGLE_TYPE, [10, 10])
    map_sym = DataSymbol("map", int_array_type)
    lbound1 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(map_sym), int_one.copy())
    ubound1 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(map_sym), int_one.copy())
    my_range1 = Range.create(lbound1, ubound1)
    abs_op = UnaryOperation.create(
        UnaryOperation.Operator.ABS,
        ArrayReference.create(map_sym, [my_range1, int_one.copy()]))
    int_op = UnaryOperation.create(UnaryOperation.Operator.INT, abs_op)
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), int_op]), one.copy())
    assert assignment.is_array_range is True