Пример #1
0
def test_access_info():
    '''Test the AccessInfo class.
    '''
    location = 12
    access_info = AccessInfo(AccessType.READ, location, Node())
    assert access_info.access_type == AccessType.READ
    assert access_info.location == location
    assert access_info.indices is None
    access_info.change_read_to_write()
    assert access_info.access_type == AccessType.WRITE
    with pytest.raises(InternalError) as err:
        access_info.change_read_to_write()
    assert "Trying to change variable to 'WRITE' which does not have "\
        "'READ' access." in str(err)

    access_info.indices = ["i"]
    assert access_info.indices == ["i"]

    access_info = AccessInfo(AccessType.UNKNOWN, location, Node())
    assert access_info.access_type == AccessType.UNKNOWN
    assert access_info.location == location
    assert access_info.indices is None

    access_info = AccessInfo(AccessType.UNKNOWN, location, Node(), ["i", "j"])
    assert access_info.access_type == AccessType.UNKNOWN
    assert access_info.location == location
    assert access_info.indices == ["i", "j"]
Пример #2
0
def test_variable_access_info():
    '''Test the VariableAccesInfo class, i.e. the class that manages a list
    of VariableInfo instances for one variable
    '''

    vai = VariableAccessInfo("var_name")
    assert vai.var_name == "var_name"
    assert vai.is_written() is False
    assert vai.is_read() is False
    assert vai.all_accesses == []

    vai.add_access(AccessType.READ, Node(), 2)
    assert vai.is_read()
    vai.change_read_to_write()
    assert not vai.is_read()
    assert vai.is_written()

    # Now we have one write access, which we should not be able to
    # change to write again:
    with pytest.raises(InternalError) as err:
        vai.change_read_to_write()
    assert "Trying to change variable 'var_name' to 'WRITE' which "\
        "does not have 'READ' access." in str(err)

    assert vai.all_accesses[0] == vai[0]
    with pytest.raises(IndexError) as err:
        _ = vai[1]

    # Add a READ access - now we should not be able to
    # change read to write anymore:
    vai.add_access(AccessType.READ, Node(), 1)
    with pytest.raises(InternalError) as err:
        vai.change_read_to_write()
    assert "Variable 'var_name' had 2 accesses listed, "\
           "not one in change_read_to_write." in str(err)
Пример #3
0
def test_variable_access_info_read_write():
    # pylint: disable=invalid-name
    '''Test the handling of READWRITE accesses. A READWRITE indicates both
    a read and a write access, but if a variable as a READ and a WRITE
    access, this is not one READWRITE access. A READWRITE access is only
    used in subroutine calls (depending on kernel metadata)
    '''

    vai = VariableAccessInfo("var_name")
    assert vai.has_read_write() is False

    # Add a READ and WRITE access at the same location, and make sure it
    # is not reported as READWRITE access
    vai.add_access(AccessType.READ, Node(), 2)
    vai.add_access(AccessType.WRITE, Node(), 2)
    assert vai.has_read_write() is False

    vai.add_access(AccessType.READWRITE, Node(), 2)
    assert vai.has_read_write()

    # Create a new instance, and add only one READWRITE access:
    vai = VariableAccessInfo("var_name")
    vai.add_access(AccessType.READWRITE, Node(), 2)
    assert vai.has_read_write()
    assert vai.is_read()
    assert vai.is_written()
Пример #4
0
    def __init__(self, invoke, ast):
        Node.__init__(self)
        NemoFparser2ASTProcessor.__init__(self)

        self._invoke = invoke
        self._ast = ast
        self.process_nodes(self, ast.content, ast)
Пример #5
0
    def __init__(self, invoke, ast):
        # pylint: disable=super-init-not-called, non-parent-init-called
        Node.__init__(self)
        NemoFparser2ASTProcessor.__init__(self)

        self._invoke = invoke
        self._ast = ast
        self.process_nodes(self, ast.content, ast)
Пример #6
0
def test_basegen_add_invalid_posn():
    '''Check that attempting to call add on BaseGen with an invalid
    position argument raises an error'''
    from psyclone.psyGen import Node
    from psyclone.f2pygen import BaseGen
    parent = Node()
    bgen = BaseGen(parent, parent)
    obj = Node()
    with pytest.raises(Exception) as err:
        bgen.add(obj, position=['wrong'])
    assert "supported positions are ['append', 'first'" in str(err)
Пример #7
0
def test_basegen_add_auto():
    ''' Check that attempting to call add on BaseGen raises an error if
    position is "auto"'''
    from psyclone.psyGen import Node
    from psyclone.f2pygen import BaseGen
    parent = Node()
    bgen = BaseGen(parent, parent)
    obj = Node()
    with pytest.raises(Exception) as err:
        bgen.add(obj, position=['auto'])
    assert "auto option must be implemented by the sub" in str(err)
Пример #8
0
def test_omploop_no_collapse():
    ''' Check that the OMPLoopTrans.directive() method rejects the
    collapse argument '''
    from psyclone.psyGen import Node
    from psyclone.transformations import OMPLoopTrans
    trans = OMPLoopTrans()
    pnode = Node()
    cnode = Node()
    with pytest.raises(NotImplementedError) as err:
        _ = trans._directive(pnode, cnode, collapse=2)
    assert ("The COLLAPSE clause is not yet supported for '!$omp do' "
            "directives" in str(err))
Пример #9
0
def test_accloop():
    ''' Generic tests for the ACCLoopTrans transformation class '''
    from psyclone.transformations import ACCLoopTrans
    from psyclone.psyGen import Node, ACCLoopDirective
    trans = ACCLoopTrans()
    assert trans.name == "ACCLoopTrans"
    assert str(trans) == "Adds an 'OpenACC loop' directive to a loop"

    pnode = Node()
    cnode = Node()
    tdir = trans._directive(pnode, [cnode])
    assert isinstance(tdir, ACCLoopDirective)
Пример #10
0
    def __init__(self, invoke, ast):
        # pylint: disable=super-init-not-called, non-parent-init-called
        Node.__init__(self)
        NemoFparser2Reader.__init__(self)

        self._invoke = invoke
        self._ast = ast
        # Whether or not we've already checked the associated Fortran for
        # potential name-clashes when inserting profiling code.
        # TODO this can be removed once #435 is done and we're no longer
        # manipulating the fparser2 parse tree.
        self._name_clashes_checked = False

        self.process_nodes(self, ast.content, ast)
Пример #11
0
def test_variables_access_info():
    '''Test the implementation of VariablesAccessInfo, a class that manages
    a list of variables, each with a list of accesses.
    '''
    var_accesses = VariablesAccessInfo()
    node1 = Node()
    var_accesses.add_access("read", AccessType.READ, node1)
    node2 = Node()
    var_accesses.add_access("written", AccessType.WRITE, node2)
    assert str(var_accesses) == "read: READ, written: WRITE"

    var_accesses.next_location()
    node = Node()
    var_accesses.add_access("written", AccessType.WRITE, node)
    var_accesses.next_location()
    var_accesses.add_access("read_written", AccessType.WRITE, node)
    var_accesses.add_access("read_written", AccessType.READ, node)
    assert str(var_accesses) == "read: READ, read_written: READ+WRITE, "\
                                "written: WRITE"
    assert set(var_accesses.all_vars) == set(
        ["read", "written", "read_written"])
    all_accesses = var_accesses["read"].all_accesses
    assert all_accesses[0].node == node1
    written_accesses = var_accesses["written"].all_accesses
    assert written_accesses[0].location == 0
    assert written_accesses[1].location == 1
    # Check that the location pointer is pointing to the next statement:
    assert var_accesses.location == 2

    # Create a new instance
    var_accesses2 = VariablesAccessInfo()
    var_accesses2.add_access("new_var", AccessType.READ, node)
    var_accesses2.add_access("written", AccessType.READ, node)

    # Now merge the new instance with the previous instance:
    var_accesses.merge(var_accesses2)
    assert str(var_accesses) == "new_var: READ, read: READ, " \
                                "read_written: READ+WRITE, written: READ+WRITE"

    with pytest.raises(KeyError):
        _ = var_accesses["does_not_exist"]
    with pytest.raises(KeyError):
        var_accesses.is_read("does_not_exist")
    with pytest.raises(KeyError):
        var_accesses.is_written("does_not_exist")

    assert "READWRITE" not in str(var_accesses)
    var_accesses.add_access("readwrite", AccessType.READWRITE, node)
    assert "READWRITE" in str(var_accesses)
Пример #12
0
    def __init__(self, children=None, parent=None):
        Node.__init__(self, children=children, parent=parent)

        # Store the name of the profile variable that is used for this
        # profile name. This allows to show the variable name in __str__
        # (and also if we would call create_name in gen(), the name would
        # change every time gen() is called).
        self._var_name = NameSpaceFactory().create().create_name("profile")

        # Name of the region. In general at constructor time we might not
        # have a parent subroutine or a child for the kernel, so we leave
        # the name empty for now. The region and module names are set the
        # first time gen() is called (and then remain unchanged).
        self._region_name = None
        self._module_name = None
Пример #13
0
def test_check_intergrid():
    ''' Test that the check_intergrid utility does not raise an error if the
    supplied node has no children. '''
    from psyclone.psyGen import Node
    from psyclone.transformations import check_intergrid
    tnode = Node()
    check_intergrid(tnode)
Пример #14
0
def test_ompdirective_type():
    ''' Check that we can query the type of an OMP Directive '''
    from psyclone.psyGen import Node
    parent = Node()
    dirgen = DirectiveGen(parent, "omp", "begin", "do", "schedule(static)")
    ompdir = dirgen.root
    assert ompdir.type == "do"
Пример #15
0
def test_psyirvisitor_visit_no_method2():
    '''Check that an exception is not raised if the method for the Node class
    does not exist and skip_nodes is set to True.

    '''
    visitor = PSyIRVisitor(skip_nodes=True)
    result = visitor(Node())
    assert result is None
Пример #16
0
def test_ompdirective_wrong_posn():
    ''' Check that we raise an error if we request an OMP Directive with
    an invalid position '''
    from psyclone.psyGen import Node
    parent = Node()
    with pytest.raises(RuntimeError) as err:
        _ = DirectiveGen(parent, "omp", "start", "do", "schedule(static)")
    assert "unrecognised position 'start'" in str(err)
Пример #17
0
def test_ompdirective_wrong():
    ''' Check that we raise an error if we request an OMP Directive of
    unrecognised type '''
    from psyclone.psyGen import Node
    parent = Node()
    with pytest.raises(RuntimeError) as err:
        _ = DirectiveGen(parent, "omp", "begin", "dosomething",
                         "schedule(static)")
    assert "unrecognised directive type" in str(err)
Пример #18
0
def test_directive_wrong_type():
    ''' Check that we raise an error if we request a Directive of
    unrecognised type '''
    from psyclone.psyGen import Node
    parent = Node()
    with pytest.raises(RuntimeError) as err:
        _ = DirectiveGen(parent, "some_dir_type", "begin", "do",
                         "schedule(static)")
    assert "unsupported directive language" in str(err)
Пример #19
0
def test_psyirvisitor_visit_no_method1():
    '''Check that an exception is raised if the method for the Node class
    does not exist.

    '''
    visitor = PSyIRVisitor()
    with pytest.raises(VisitorError) as excinfo:
        visitor(Node())
    assert ("Visitor Error: Unsupported node 'Node' found: method names "
            "attempted were ['node_node']." in str(excinfo.value))
Пример #20
0
def test_variables_access_info_merge():
    # pylint: disable=invalid-name
    '''Tests the merge operation of VariablesAccessInfo.
    '''
    # First create one instance representing for example:
    # a=b; c=d
    var_accesses1 = VariablesAccessInfo()
    node = Node()
    var_accesses1.add_access("b", AccessType.READ, node)
    var_accesses1.add_access("a", AccessType.WRITE, node)
    var_accesses1.next_location()
    var_accesses1.add_access("d", AccessType.READ, node)
    var_accesses1.add_access("c", AccessType.WRITE, node)
    c_accesses = var_accesses1["c"]
    assert len(c_accesses.all_accesses) == 1
    assert c_accesses[0].access_type == AccessType.WRITE

    # First create one instance representing for example:
    # e=f; g=h
    var_accesses2 = VariablesAccessInfo()
    var_accesses2.add_access("f", AccessType.READ, node)
    var_accesses2.add_access("e", AccessType.WRITE, node)
    var_accesses2.next_location()
    var_accesses2.add_access("h", AccessType.READ, node)
    var_accesses2.add_access("g", AccessType.WRITE, node)

    # Now merge the second instance into the first one
    var_accesses1.merge(var_accesses2)

    # The e=f access pattern should have the same location
    # as the c=d (since there is no next_location after
    # adding the b=a access):
    c_accesses = var_accesses1["c"]
    e_accesses = var_accesses1["e"]
    assert c_accesses[0].access_type == AccessType.WRITE
    assert e_accesses[0].access_type == AccessType.WRITE
    assert c_accesses[0].location == e_accesses[0].location

    # Test that the g=h part has a higher location than the
    # c=d data. This makes sure that merge() increases the
    # location number of accesses when merging.
    c_accesses = var_accesses1["c"]
    g_accesses = var_accesses1["g"]
    h_accesses = var_accesses1["h"]
    assert c_accesses[0].location < g_accesses[0].location
    assert g_accesses[0].location == h_accesses[0].location

    # Also make sure that the access location was properly increased
    # Originally we had locations 0,1. Then we merged accesses with
    # location 0,1 in - the one at 0 is merged with the current 1,
    # and the new location 1 increases the current location from
    # 1 to 2:
    # pylint: disable=protected-access
    assert var_accesses1._location == 2
Пример #21
0
    def __init__(self, children=None, parent=None):
        '''Constructor for a ProfileNode that is inserted in a schedule.
        Parameters:
            :param children: A list of children nodes for this node.
            :type children: A list of :py::class::`psyclone.psyGen.Node` \
            or derived classes.
            :param parent: The parent of this node.
            :type parent: A :py::class::`psyclone.psyGen.Node`.
        '''
        Node.__init__(self, children=children, parent=parent)

        # Store the name of the profile variable that is used for this
        # profile name. This allows to show the variable name in __str__
        # (and also if we would call create_name in gen(), the name would
        # change every time gen() is called).
        self._var_name = NameSpaceFactory().create().create_name("profile")

        # Name of the region. In general at constructor time we might not
        # have a parent subroutine or a child for the kernel, so we leave
        # the name empty for now. The region and module names are set the
        # first time gen() is called (and then remain unchanged).
        self._region_name = None
        self._module_name = None
Пример #22
0
def test_psyirvisitor_visit_attribute_error():
    '''Check that an Attribute Error is raised if the method for the Node
    class does exist and the method itself raises an Attribute
    Error. This is checked because AttributeError is used to catch a
    method not existing. Therefore an AttributeError raised by a
    method that does exist could be mistaken as meaning that the
    method does not exist.

    '''
    class MyPSyIRVisitor(PSyIRVisitor):
        '''Subclass PSyIRVisitor to make the node method exist but it itself
        raises an attribute error.'''
        def node_node(self, _):
            ''' Raise an AttributeError for testing purposes '''
            raise AttributeError("Error")

    visitor = MyPSyIRVisitor()
    with pytest.raises(AttributeError) as excinfo:
        _ = visitor(Node())
    assert str(excinfo.value) == "Error"
Пример #23
0
def test_variable_access_info_read_write():
    '''Test the handling of READWRITE accesses. A READWRITE indicates both
    a read and a write access, but if a variable as a READ and a WRITE
    access, this is not one READWRITE access. A READWRITE access is only
    used in subroutine calls (depending on kernel metadata)
    '''

    vai = VariableAccessInfo("var_name")
    assert vai.has_read_write() is False

    # Add a READ and WRITE access at the same location, and make sure it
    # is not reported as READWRITE access
    node = Node()
    vai.add_access(AccessType.READ, 2, node)
    assert vai[0].node == node
    assert vai[0].location == 2
    vai.add_access(AccessType.WRITE, 2, Node())
    assert vai.has_read_write() is False

    vai.add_access(AccessType.READWRITE, 2, Node())
    assert vai.has_read_write()

    # Create a new instance, and add only one READWRITE access:
    vai = VariableAccessInfo("var_name")
    vai.add_access(AccessType.READWRITE, 2, Node())
    assert vai.has_read_write()
    assert vai.is_read()
    assert vai.is_written()

    vai_array = VariableAccessInfo("array")
    vai_array.add_access(AccessType.READ, 2, Node(), [1])
    vai_array.add_access(AccessType.WRITE, 3, Node(), ["i"])
    assert vai_array.is_array()

    # Adding a non-array access marks this as not array:
    # TODO #500: once we have a symboltable, this test
    # needs to be adjusted.
    vai_array.add_access(AccessType.WRITE, 3, Node())
    assert not vai_array.is_array()
Пример #24
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)