Esempio n. 1
0
def test_cw_gen_local_variable(monkeypatch):
    '''Check the CWriter class gen_local_variable method produces
    the expected declarations.

    '''
    cwriter = CWriter()

    monkeypatch.setattr(cwriter, "gen_declaration", lambda x: "<declaration>")

    # Local variables are declared as single statements
    symbol = DataSymbol("dummy1", INTEGER_TYPE)
    result = cwriter.gen_local_variable(symbol)
    # Result should include the mocked gen_declaration and ';\n'
    assert result == "<declaration>;\n"
Esempio n. 2
0
def test_gocean_acc_parallel():
    '''Test that an ACC PARALLEL directive in a 'classical' API (gocean here)
    is created correctly.

    '''
    _, invoke = get_invoke("single_invoke.f90", "gocean1.0",
                           idx=0, dist_mem=False)

    ptrans = ACCParallelTrans()
    ptrans.apply(invoke.schedule[0])

    # Now remove the GOKern (since it's not yet supported in the
    # visitor pattern) and replace it with a simple assignment
    # TODO: #440 tracks this
    replace_child_with_assignment(invoke.schedule[0].dir_body)

    # omp_sched is a GOInvokeSchedule, which is not yet supported.
    # So only convert starting from the OMPParallelDirective. Also, disable
    # node validation so as to avoid the need for a data region.
    fvisitor = FortranWriter(check_global_constraints=False)
    result = fvisitor(invoke.schedule[0])
    correct = '''!$acc begin parallel default(present)
a = b
!$acc end parallel'''
    assert correct in result

    cvisitor = CWriter(check_global_constraints=False)
    with pytest.raises(VisitorError) as err:
        _ = cvisitor(invoke.schedule[0])
    assert "Unsupported node 'ACCParallelDirective' found" in str(err.value)
Esempio n. 3
0
def test_gocean_omp_parallel():
    '''Test that an OMP PARALLEL directive in a 'classical' API (gocean here)
    is created correctly.
    '''

    from psyclone.transformations import OMPParallelTrans

    _, invoke = get_invoke("single_invoke.f90", "gocean1.0", idx=0)

    omp = OMPParallelTrans()
    omp_sched, _ = omp.apply(invoke.schedule[0])

    # Now remove the GOKern (since it's not yet supported in the
    # visitor pattern) and replace it with a simple assignment
    # TODO: #440 tracks this
    replace_child_with_assignment(omp_sched[0])

    # omp_sched is a GOInvokeSchedule, which is not yet supported.
    # So only convert starting from the OMPParallelDirective
    fvisitor = FortranWriter()
    result = fvisitor(omp_sched[0])
    correct = '''!$omp parallel
  a=b
!$omp end parallel'''
    assert correct in result

    cvisitor = CWriter()
    # Remove newlines for easier RE matching
    result = cvisitor(omp_sched[0])
    correct = '''#pragma omp parallel
{
  a = b;
}'''
    result = cvisitor(omp_sched[0])
    assert correct in result
Esempio n. 4
0
def test_nemo_acc_kernels(default_present, expected, parser):
    '''
    Tests that an OpenACC kernels directive is handled correctly in the
    NEMO API.
    '''
    # Generate fparser2 parse tree from Fortran code.
    reader = FortranStringReader(NEMO_TEST_CODE)
    code = parser(reader)
    psy = PSyFactory("nemo", distributed_memory=False).create(code)
    nemo_sched = psy.invokes.invoke_list[0].schedule

    # Now apply a kernels transform
    ktrans = ACCKernelsTrans()
    options = {"default_present": default_present}
    ktrans.apply(nemo_sched[0], options)

    fvisitor = FortranWriter()
    result = fvisitor(nemo_sched)
    correct = '''!$acc kernels{0}
do i = 1, 20, 2
  a = 2 * i + d(i)
  c(i) = a
  b(i) = b(i) + a + c(i)
enddo
!$acc end kernels'''.format(expected)
    assert correct in result

    cvisitor = CWriter()
    with pytest.raises(VisitorError) as err:
        _ = cvisitor(nemo_sched[0])
    assert "Unsupported node 'ACCKernelsDirective' found" in str(err.value)
Esempio n. 5
0
def test_nemo_acc_parallel(parser):
    '''Tests that an OpenACC parallel directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    reader = FortranStringReader(NEMO_TEST_CODE)
    code = parser(reader)
    psy = PSyFactory("nemo", distributed_memory=False).create(code)
    nemo_sched = psy.invokes.invoke_list[0].schedule

    # Now apply an ACC parallel transform
    dtrans = ACCDataTrans()
    ktrans = ACCParallelTrans()

    ktrans.apply(nemo_sched[0])
    dtrans.apply(nemo_sched[0])

    # Disable node validation to avoid having to add a data region
    fort_writer = FortranWriter(check_global_constraints=False)
    result = fort_writer(nemo_sched)

    correct = '''!$acc begin parallel default(present)
do i = 1, 20, 2
  a = 2 * i + d(i)
  c(i) = a
  b(i) = b(i) + a + c(i)
enddo
!$acc end parallel'''
    assert correct in result

    cvisitor = CWriter(check_global_constraints=False)
    with pytest.raises(VisitorError) as err:
        _ = cvisitor(nemo_sched[0])
    assert "Unsupported node 'ACCDataDirective' found" in str(err.value)
Esempio n. 6
0
def test_cw_array():
    '''Check the CWriter class array method correctly prints
    out the C representation of an array.

    '''
    cwriter = CWriter()

    symbol = DataSymbol('a', REAL_TYPE)
    arr = ArrayReference(symbol)
    lit = Literal('0.0', REAL_TYPE)
    assignment = Assignment.create(arr, lit)

    # An array without any children (dimensions) should produce an error.
    with pytest.raises(VisitorError) as excinfo:
        result = cwriter(assignment)
    assert "Arrays must have at least 1 dimension but found node: '" \
        in str(excinfo.value)

    # Dimensions can be references, literals or operations
    arr.addchild(Reference(DataSymbol('b', INTEGER_TYPE), parent=arr))
    arr.addchild(Literal('1', INTEGER_TYPE, parent=arr))
    uop = UnaryOperation.create(UnaryOperation.Operator.MINUS,
                                Literal('2', INTEGER_TYPE))
    uop.parent = arr
    arr.addchild(uop)

    result = cwriter(assignment)
    # Results is reversed and flatten (row-major 1D)
    # dimensions are called <name>LEN<dimension> by convention
    assert result == "a[(-2) * aLEN2 * aLEN1 + 1 * aLEN1 + b] = 0.0;\n"
Esempio n. 7
0
def test_cw_loop():
    '''Tests writing out a Loop node in C. It parses Fortran code
    and outputs it as C. Note that this is atm a literal translation,
    the loops are not functionally identical to Fortran, see TODO #523.

    '''
    from psyclone.tests.utilities import create_schedule

    # Generate PSyIR from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''for(i=1; i<=20; i+=2)
{
  a = (2 * i);
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Esempio n. 8
0
def test_cw_loop(fortran_reader):
    '''Tests writing out a Loop node in C. It parses Fortran code
    and outputs it as C. Note that this is atm a literal translation,
    the loops are not functionally identical to Fortran, see TODO #523.

    '''
    # Generate PSyIR from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
          enddo
        end subroutine tmp
        end module test'''
    container = fortran_reader.psyir_from_source(code).children[0]
    module = container.children[0]

    cvisitor = CWriter()
    result = cvisitor(module[0])
    correct = '''for(i=1; i<=20; i+=2)
{
  a = (2 * i);
}'''
    result = cvisitor(module[0])
    assert correct in result
Esempio n. 9
0
def test_cw_return():
    '''Check the CWriter class return method correctly prints out the
    C representation.

    '''
    cwriter = CWriter()
    result = cwriter(Return())
    assert "return;\n" in result
Esempio n. 10
0
def test_cw_assignment():
    '''Check the CWriter class assignment method generate the appropriate
    output.

    '''
    assignment = Assignment.create(Reference(DataSymbol('a', REAL_TYPE)),
                                   Reference(DataSymbol('b', REAL_TYPE)))
    # Generate C from the PSyIR schedule
    cwriter = CWriter()
    result = cwriter(assignment)
    assert result == "a = b;\n"
Esempio n. 11
0
def test_cw_codeblock():
    '''Check the CWriter class codeblock method raises the expected
    error.
    '''

    cblock = CodeBlock([], "dummy")
    cwriter = CWriter()

    with pytest.raises(VisitorError) as error:
        _ = cwriter(cblock)
    assert "CodeBlocks can not be translated to C." in str(error.value)
Esempio n. 12
0
def test_cw_binaryoperator():
    '''Check the CWriter class binary_operation method correctly
    prints out the C representation of any given BinaryOperation.

    '''
    cwriter = CWriter()

    # Test UnaryOperation without children.
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert ("BinaryOperation malformed or incomplete. It should have "
            "exactly 2 children, but found 0." in str(err.value))

    # Test with children
    ref1 = Reference(DataSymbol("a", REAL_TYPE))
    ref2 = Reference(DataSymbol("b", REAL_TYPE))
    binary_operation = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                              ref1, ref2)
    assert cwriter(binary_operation) == '(a + b)'

    # Test all supported Operators
    test_list = ((BinaryOperation.Operator.ADD,
                  '(a + b)'), (BinaryOperation.Operator.SUB, '(a - b)'),
                 (BinaryOperation.Operator.MUL,
                  '(a * b)'), (BinaryOperation.Operator.DIV, '(a / b)'),
                 (BinaryOperation.Operator.REM,
                  '(a % b)'), (BinaryOperation.Operator.POW, 'pow(a, b)'),
                 (BinaryOperation.Operator.EQ,
                  '(a == b)'), (BinaryOperation.Operator.NE, '(a != b)'),
                 (BinaryOperation.Operator.GT,
                  '(a > b)'), (BinaryOperation.Operator.GE, '(a >= b)'),
                 (BinaryOperation.Operator.LT,
                  '(a < b)'), (BinaryOperation.Operator.LE, '(a <= b)'),
                 (BinaryOperation.Operator.AND,
                  '(a && b)'), (BinaryOperation.Operator.OR,
                                '(a || b)'), (BinaryOperation.Operator.SIGN,
                                              'copysign(a, b)'))

    for operator, expected in test_list:
        binary_operation._operator = operator
        assert cwriter(binary_operation) == expected

    # Test that an unsupported operator raises a error
    class Unsupported(object):
        '''Dummy class'''
        def __init__(self):
            pass

    binary_operation._operator = Unsupported
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert "The C backend does not support the '" in str(err.value)
    assert "' operator." in str(err.value)
Esempio n. 13
0
def test_cw_binaryoperator():
    '''Check the CWriter class binary_operation method correctly
    prints out the C representation of any given BinaryOperation.

    '''
    cwriter = CWriter()

    # Test UnaryOperation without children.
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert("BinaryOperation malformed or incomplete. It should have "
           "exactly 2 children, but found 0." in str(err.value))

    # Add children
    ref1 = Reference("a", binary_operation)
    ref2 = Reference("b", binary_operation)
    binary_operation.addchild(ref1)
    binary_operation.addchild(ref2)
    assert cwriter(binary_operation) == '(a + b)'

    # Test all supported Operators
    test_list = ((BinaryOperation.Operator.ADD, '(a + b)'),
                 (BinaryOperation.Operator.SUB, '(a - b)'),
                 (BinaryOperation.Operator.MUL, '(a * b)'),
                 (BinaryOperation.Operator.DIV, '(a / b)'),
                 (BinaryOperation.Operator.REM, '(a % b)'),
                 (BinaryOperation.Operator.POW, 'pow(a, b)'),
                 (BinaryOperation.Operator.EQ, '(a == b)'),
                 (BinaryOperation.Operator.NE, '(a != b)'),
                 (BinaryOperation.Operator.GT, '(a > b)'),
                 (BinaryOperation.Operator.GE, '(a >= b)'),
                 (BinaryOperation.Operator.LT, '(a < b)'),
                 (BinaryOperation.Operator.LE, '(a <= b)'),
                 (BinaryOperation.Operator.AND, '(a && b)'),
                 (BinaryOperation.Operator.OR, '(a || b)'),
                 (BinaryOperation.Operator.SIGN, 'copysign(a, b)'))

    for operator, expected in test_list:
        binary_operation._operator = operator
        assert cwriter(binary_operation) == expected

    # Test that an unsupported operator raises a error
    # pylint: disable=abstract-method, too-few-public-methods
    class Unsupported():
        '''Dummy class'''
    # pylint: enable=abstract-method, too-few-public-methods
    binary_operation._operator = Unsupported
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert "The C backend does not support the '" in str(err)
    assert "' operator." in str(err)
Esempio n. 14
0
def test_nemo_omp_do(fortran_reader):
    '''Tests if an OpenMP do directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
            b(i) = b(i) + a
          enddo
        end subroutine tmp
        end module test'''
    psyir = fortran_reader.psyir_from_source(code)
    schedule = psyir.children[0].children[0]

    # Now apply a parallel transform
    omp_loop = OMPLoopTrans()
    omp_loop.apply(schedule[0])
    # By default the visitor should raise an exception because the loop
    # directive is not inside a parallel region
    fvisitor_with_checks = FortranWriter()
    with pytest.raises(GenerationError) as err:
        fvisitor_with_checks(schedule)
    assert ("OMPDoDirective must be inside an OMP parallel region but could "
            "not find an ancestor OMPParallelDirective" in str(err.value))
    # Disable checks on global constraints to remove need for parallel region
    fvisitor = FortranWriter(check_global_constraints=False)
    result = fvisitor(schedule)
    correct = '''  !$omp do schedule(static)
  do i = 1, 20, 2
    a = 2 * i
    b(i) = b(i) + a
  enddo
  !$omp end do'''
    assert correct in result

    cvisitor = CWriter(check_global_constraints=False)
    result = cvisitor(schedule[0])
    correct = '''#pragma omp do schedule(static)
{
  for(i=1; i<=20; i+=2)
  {
    a = (2 * i);
    b[i] = (b[i] + a);
  }
}'''
    assert correct in result
Esempio n. 15
0
def test_cw_size():
    ''' Check the CWriter class SIZE method raises the expected error since
    there is no C equivalent. '''
    cwriter = CWriter()
    arr = ArrayReference(DataSymbol('a', INTEGER_TYPE))
    lit = Literal('1', INTEGER_TYPE)
    size = BinaryOperation.create(BinaryOperation.Operator.SIZE, arr, lit)
    lhs = Reference(DataSymbol('length', INTEGER_TYPE))
    assignment = Assignment.create(lhs, size)

    with pytest.raises(VisitorError) as excinfo:
        cwriter(assignment)
    assert ("C backend does not support the 'Operator.SIZE' operator"
            in str(excinfo.value))
Esempio n. 16
0
def test_cw_literal():
    '''Check the CWriter class literal method correctly prints
    out the C representation of a Literal.

    '''

    cwriter = CWriter()

    lit = Literal('1', INTEGER_TYPE)
    assert cwriter(lit) == '1'

    # Test that scientific notation is output correctly
    lit = Literal("3e5", REAL_TYPE, None)
    assert cwriter(lit) == '3e5'
Esempio n. 17
0
def test_nemo_omp_parallel():
    '''Tests if an OpenMP parallel directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
            b(i) = b(i) + a
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")
    from psyclone.transformations import OMPParallelTrans

    # Now apply a parallel transform
    omp_par = OMPParallelTrans()
    # Note that the loop is not handled as nemo kernel, so the
    # omp node-type-check will find the assignment statement and
    # prevent application of omp parallel to the loop. So
    # disable the node type check so that omp parallel is applied.
    omp_par.apply(schedule[0], {"node-type-check": False})

    fvisitor = FortranWriter()
    result = fvisitor(schedule)
    correct = '''!$omp parallel private(a,i)
    do i = 1, 20, 2
      a=2 * i
      b(i)=b(i) + a
    enddo
!$omp end parallel'''
    assert correct in result

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''#pragma omp parallel private(a,i)
{
  for(i=1; i<=20; i+=2)
  {
    a = (2 * i);
    b[i] = (b[i] + a);
  }
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Esempio n. 18
0
def test_cw_unaryoperator():
    '''Check the CWriter class unary_operation method correctly prints out
    the C representation of any given UnaryOperation.

    '''
    cwriter = CWriter()

    # Test UnaryOperation without children.
    unary_operation = UnaryOperation(UnaryOperation.Operator.MINUS)
    with pytest.raises(VisitorError) as err:
        _ = cwriter(unary_operation)
    assert ("UnaryOperation malformed or incomplete. It should have "
            "exactly 1 child, but found 0." in str(err.value))

    # Add child
    ref1 = Literal("a", CHARACTER_TYPE, unary_operation)
    unary_operation.addchild(ref1)
    assert cwriter(unary_operation) == '(-a)'

    # Test all supported Operators
    test_list = ((UnaryOperation.Operator.PLUS,
                  '(+a)'), (UnaryOperation.Operator.MINUS,
                            '(-a)'), (UnaryOperation.Operator.SQRT, 'sqrt(a)'),
                 (UnaryOperation.Operator.NOT,
                  '(!a)'), (UnaryOperation.Operator.COS,
                            'cos(a)'), (UnaryOperation.Operator.SIN, 'sin(a)'),
                 (UnaryOperation.Operator.TAN,
                  'tan(a)'), (UnaryOperation.Operator.ACOS, 'acos(a)'),
                 (UnaryOperation.Operator.ASIN,
                  'asin(a)'), (UnaryOperation.Operator.ATAN, 'atan(a)'),
                 (UnaryOperation.Operator.ABS,
                  'abs(a)'), (UnaryOperation.Operator.REAL, '(float)a'))

    for operator, expected in test_list:
        unary_operation._operator = operator
        assert cwriter(unary_operation) in expected

    # Test that an unsupported operator raises an error
    class Unsupported(object):
        # pylint: disable=missing-docstring
        pass

    unary_operation._operator = Unsupported
    with pytest.raises(NotImplementedError) as err:
        _ = cwriter(unary_operation)
    assert "The C backend does not support the '" in str(err.value)
    assert "' operator." in str(err.value)
Esempio n. 19
0
def test_cw_ifblock():
    '''Check the CWriter class ifblock method correctly prints out the
    C representation.

    '''
    from psyclone.psyGen import IfBlock

    # Try with just a IfBlock node
    ifblock = IfBlock()
    cwriter = CWriter()
    with pytest.raises(VisitorError) as err:
        _ = cwriter(ifblock)
    assert("IfBlock malformed or incomplete. It should have "
           "at least 2 children, but found 0." in str(err.value))

    # Add the if condition
    ifblock.addchild(Reference('a', parent=ifblock))
    with pytest.raises(VisitorError) as err:
        _ = cwriter(ifblock)
    assert("IfBlock malformed or incomplete. It should have "
           "at least 2 children, but found 1." in str(err.value))

    # Fill the if_body and else_body
    ifblock.addchild(Schedule(parent=ifblock))
    ifblock.addchild(Schedule(parent=ifblock))
    ifblock.if_body.addchild(Return(parent=ifblock.if_body))

    ifblock2 = IfBlock(parent=ifblock.else_body)
    ifblock2.addchild(Reference('b', parent=ifblock2))
    ifblock2.addchild(Schedule(parent=ifblock2))
    ifblock2.if_body.addchild(Return(parent=ifblock2.if_body))
    ifblock2.addchild(Schedule(parent=ifblock2))
    ifblock2.else_body.addchild(Return(parent=ifblock2.else_body))

    ifblock.else_body.addchild(ifblock2)

    result = cwriter(ifblock)
    assert result == (
        "if (a) {\n"
        "  return;\n"
        "} else {\n"
        "  if (b) {\n"
        "    return;\n"
        "  } else {\n"
        "    return;\n"
        "  }\n"
        "}\n")
Esempio n. 20
0
def test_cw_gen_declaration():
    '''Check the CWriter class gen_declaration method produces
    the expected declarations.

    '''
    cwriter = CWriter()

    # Basic entries
    symbol = DataSymbol("dummy1", INTEGER_TYPE)
    result = cwriter.gen_declaration(symbol)
    assert result == "int dummy1"

    symbol = DataSymbol("dummy1", CHARACTER_TYPE)
    result = cwriter.gen_declaration(symbol)
    assert result == "char dummy1"

    symbol = DataSymbol("dummy1", BOOLEAN_TYPE)
    result = cwriter.gen_declaration(symbol)
    assert result == "bool dummy1"

    # Array argument
    array_type = ArrayType(REAL_TYPE, [2, ArrayType.Extent.ATTRIBUTE, 2])
    symbol = DataSymbol("dummy2",
                        array_type,
                        interface=ArgumentInterface(
                            ArgumentInterface.Access.READ))
    result = cwriter.gen_declaration(symbol)
    assert result == "double * restrict dummy2"

    # Array with unknown access
    array_type = ArrayType(INTEGER_TYPE, [2, ArrayType.Extent.ATTRIBUTE, 2])
    symbol = DataSymbol("dummy2",
                        array_type,
                        interface=ArgumentInterface(
                            ArgumentInterface.Access.UNKNOWN))
    result = cwriter.gen_declaration(symbol)
    assert result == "int * restrict dummy2"

    # Check invalid datatype produces and error
    symbol._datatype = "invalid"
    with pytest.raises(NotImplementedError) as error:
        _ = cwriter.gen_declaration(symbol)
    assert "Could not generate the C definition for the variable 'dummy2', " \
        "type 'invalid' is currently not supported." in str(error.value)
Esempio n. 21
0
def test_cw_exception():
    '''Check the CWriter class instance raises an exception if an
    unsupported PSyIR node is found.

    '''
    # pylint: disable=abstract-method
    # Define a Node which will be unsupported by the visitor
    class Unsupported(Node):
        '''A PSyIR node that will not be supported by the C visitor.'''
    # pylint: enable=abstract-method

    unsupported = Unsupported()

    cwriter = CWriter()
    with pytest.raises(VisitorError) as excinfo:
        _ = cwriter(unsupported)
    assert "Unsupported node 'Unsupported' found" in str(excinfo.value)
Esempio n. 22
0
def test_nemo_omp_parallel():
    '''Tests if an OpenMP parallel directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
            b(i) = b(i) + a
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")
    from psyclone.transformations import OMPParallelTrans

    # Now apply a parallel transform
    omp_par = OMPParallelTrans()
    omp_par.apply(schedule[0])

    fvisitor = FortranWriter()
    result = fvisitor(schedule)
    correct = '''!$omp parallel private(a,i)
    do i = 1, 20, 2
      a=2 * i
      b(i)=b(i) + a
    enddo
!$omp end parallel'''
    assert correct in result

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''#pragma omp parallel private(a,i)
{
  for(i=1; i<=20; i+=2)
  {
    a = (2 * i);
    b[i] = (b[i] + a);
  }
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Esempio n. 23
0
def test_cw_size():
    ''' Check the CWriter class SIZE method raises the expected error since
    there is no C equivalent. '''
    cwriter = CWriter()

    assignment = Assignment()
    lhs = Reference('length', parent=assignment)
    size = BinaryOperation(BinaryOperation.Operator.SIZE, parent=assignment)
    assignment.addchild(lhs)
    assignment.addchild(size)
    arr = Array('a', parent=size)
    lit = Literal('1', parent=size)
    size.addchild(arr)
    size.addchild(lit)

    with pytest.raises(VisitorError) as excinfo:
        cwriter(assignment)
    assert ("C backend does not support the 'Operator.SIZE' operator"
            in str(excinfo.value))
Esempio n. 24
0
def test_cw_literal():
    '''Check the CWriter class literal method correctly prints
    out the C representation of a Literal.

    '''

    cwriter = CWriter()

    lit = Literal('1')
    assert cwriter(lit) == '1'

    # Test that D scientific notation is replaced by 'e'
    lit = Literal("3e5", None)
    assert cwriter(lit) == '3e5'
    lit = Literal("3d5", None)
    assert cwriter(lit) == '3e5'
    lit = Literal("3D5", None)
    assert cwriter(lit) == '3e5'
    lit = Literal("3D+5", None)
    assert cwriter(lit) == '3e+5'
Esempio n. 25
0
def test_cw_gen_declaration():
    '''Check the CWriter class gen_declaration method produces
    the expected declarations.

    '''
    cwriter = CWriter()

    # Basic entries
    symbol = Symbol("dummy1", "integer")
    result = cwriter.gen_declaration(symbol)
    assert result == "int dummy1"

    symbol = Symbol("dummy1", "character")
    result = cwriter.gen_declaration(symbol)
    assert result == "char dummy1"

    symbol = Symbol("dummy1", "boolean")
    result = cwriter.gen_declaration(symbol)
    assert result == "bool dummy1"

    # Array argument
    symbol = Symbol("dummy2", "real", shape=[2, None, 2],
                    interface=Symbol.Argument(access=Symbol.Access.READ))
    result = cwriter.gen_declaration(symbol)
    assert result == "double * restrict dummy2"

    # Array with unknown intent
    symbol = Symbol("dummy2", "integer", shape=[2, None, 2],
                    interface=Symbol.Argument(access=Symbol.Access.UNKNOWN))
    result = cwriter.gen_declaration(symbol)
    assert result == "int * restrict dummy2"

    # Check invalid datatype produces and error
    symbol._datatype = "invalid"
    with pytest.raises(NotImplementedError) as error:
        _ = cwriter.gen_declaration(symbol)
    assert "Could not generate the C definition for the variable 'dummy2', " \
        "type 'invalid' is currently not supported." in str(error)
Esempio n. 26
0
def test_gocean_omp_do():
    '''Test that an OMP DO directive in a 'classical' API (gocean here)
    is created correctly.
    '''

    from psyclone.transformations import OMPLoopTrans

    _, invoke = get_invoke("single_invoke.f90",
                           "gocean1.0",
                           idx=0,
                           dist_mem=False)
    omp = OMPLoopTrans()
    omp_sched, _ = omp.apply(invoke.schedule[0])

    # Now remove the GOKern (since it's not yet supported in the
    # visitor pattern) and replace it with a simple assignment.
    # While this is invalid usage of OMP (omp must have a loop,
    # not an assignment inside), it is necessary because GOLoops
    # are not supported yet, and it is sufficient to test that the
    # visitor pattern creates correct OMP DO directives.
    # TODO #440 fixes this.
    replace_child_with_assignment(omp_sched[0].dir_body)
    fvisitor = FortranWriter()
    # GOInvokeSchedule is not yet supported, so start with
    # the OMP node:
    result = fvisitor(omp_sched[0])
    correct = '''!$omp do schedule(static)
  a = b
!$omp end do'''
    assert correct in result

    cvisitor = CWriter()
    # Remove newlines for easier RE matching
    result = cvisitor(omp_sched[0])
    correct = '''#pragma omp do schedule(static)
{
  a = b;
}'''
    assert correct in result
Esempio n. 27
0
def test_gocean_omp_do():
    '''Test that an OMP DO directive in a 'classical' API (gocean here)
    is created correctly.

    '''
    _, invoke = get_invoke("single_invoke.f90",
                           "gocean1.0",
                           idx=0,
                           dist_mem=False)
    omp = OMPLoopTrans()
    _, _ = omp.apply(invoke.schedule[0])

    # Now remove the GOKern (since it's not yet supported in the
    # visitor pattern) and replace it with a simple assignment.
    # While this is invalid usage of OMP (omp must have a loop,
    # not an assignment inside), it is necessary because GOLoops
    # are not supported yet, and it is sufficient to test that the
    # visitor pattern creates correct OMP DO directives.
    # TODO #440 fixes this.
    replace_child_with_assignment(invoke.schedule[0].dir_body)
    # Disable validation checks to avoid having to add a parallel region
    fvisitor = FortranWriter(check_global_constraints=False)
    # GOInvokeSchedule is not yet supported, so start with
    # the OMP node:
    result = fvisitor(invoke.schedule[0])
    correct = '''!$omp do schedule(static)
a = b
!$omp end do'''
    assert correct in result

    cvisitor = CWriter(check_global_constraints=False)
    result = cvisitor(invoke.schedule[0])
    correct = '''#pragma omp do schedule(static)
{
  a = b;
}'''
    assert correct in result
Esempio n. 28
0
def test_cw_assignment_and_reference():
    '''Check the CWriter class assignment and reference methods generate
    the appropriate output. Also check that a reference visit raises an
    exception if it has children as this is not expected.

    '''

    assignment = Assignment()
    assignment.addchild(Reference('a', parent=assignment))
    assignment.addchild(Reference('b', parent=assignment))

    # Generate C from the PSyIR schedule
    cwriter = CWriter()
    result = cwriter(assignment)
    assert result == "a = b;\n"

    # Now add a child to the reference node
    assignment.lhs.addchild(Node(parent=assignment))

    # Generate C from the PSyIR schedule
    with pytest.raises(VisitorError) as excinfo:
        result = cwriter(assignment)
    assert "Expecting a Reference with no children but found: " \
        in str(excinfo)
Esempio n. 29
0
    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


if __name__ == "__main__":
    psyir_tree = create_psyir_tree()

    # Write out the code as Fortran
    writer = FortranWriter()
    result = writer(psyir_tree)
    print(result)

    # Write out the code as C. At the moment NaryOperator, KernelSchedule
    # and Container are not supported in the C backend so the full example
    # can't be output.
    writer = CWriter()
    result = writer(psyir_tree.children[0].children[3])
    print(result)
Esempio n. 30
0
# 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)

# Write out the code as Fortran
WRITER = FortranWriter()
RESULT = WRITER(CONTAINER)
print(RESULT)

# Write out the code as C. At the moment NaryOperator, KernelSchedule
# and Container are not supported in the C backend so the full example
# can't be output.
WRITER = CWriter()
RESULT = WRITER(LOOP)
print(RESULT)