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")
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
def test_oclw_kernelschedule(): '''Check the OpenCLWriter class kernelschedule_node visitor produces the expected C code. ''' # The kernelschedule OpenCL Backend relies on abstrct methods that # need to be implemented by the APIs. A generic kernelschedule will # produce a NotImplementedError. oclwriter = OpenCLWriter() kschedule = KernelSchedule("kname") with pytest.raises(NotImplementedError) as error: _ = oclwriter(kschedule) assert "Abstract property. Which symbols are data arguments is " \ "API-specific." in str(error) # Mock abstract properties. (pytest monkeypatch does not work # with properties, used sub-class instead) class MockSymbolTable(SymbolTable): ''' Mock needed abstract methods of the Symbol Table ''' @property def iteration_indices(self): return self.argument_list[:2] @property def data_arguments(self): return self.argument_list[2:] kschedule.symbol_table.__class__ = MockSymbolTable # Create a sample symbol table and kernel schedule interface = Symbol.Argument(access=Symbol.Access.UNKNOWN) i = Symbol('i', 'integer', interface=interface) j = Symbol('j', 'integer', interface=interface) data1 = Symbol('data1', 'real', [10, 10], interface=interface) data2 = Symbol('data2', 'real', [10, 10], interface=interface) kschedule.symbol_table.add(i) kschedule.symbol_table.add(j) kschedule.symbol_table.add(data1) kschedule.symbol_table.add(data2) kschedule.symbol_table.specify_argument_list([i, j, data1, data2]) kschedule.addchild(Return(parent=kschedule)) result = oclwriter(kschedule) print(result) assert result == "" \ "__kernel void kname(\n" \ " __global double * restrict data1,\n" \ " __global double * restrict data2\n" \ " ){\n" \ " int data1LEN1 = get_global_size(0);\n" \ " int data1LEN2 = get_global_size(1);\n" \ " int data2LEN1 = get_global_size(0);\n" \ " int data2LEN2 = get_global_size(1);\n" \ " int i = get_global_id(0);\n" \ " int j = get_global_id(1);\n" \ " return;\n" \ "}\n"
def test_fusetrans_error_incomplete(): ''' Check that we reject attempts to fuse loops which are incomplete. ''' from psyclone.psyGen import Loop, Schedule, Literal, Return from psyclone.transformations import LoopFuseTrans, TransformationError sch = Schedule() loop1 = Loop(variable_name="i", parent=sch) loop2 = Loop(variable_name="j", parent=sch) sch.addchild(loop1) sch.addchild(loop2) fuse = LoopFuseTrans() # Check first loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The first loop does not have " \ "4 children." in str(err.value) loop1.addchild(Literal("start", parent=loop1)) loop1.addchild(Literal("stop", parent=loop1)) loop1.addchild(Literal("step", parent=loop1)) loop1.addchild(Schedule(parent=loop1)) loop1.loop_body.addchild(Return(parent=loop1.loop_body)) # Check second loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The second loop does not have " \ "4 children." in str(err.value) loop2.addchild(Literal("start", parent=loop2)) loop2.addchild(Literal("stop", parent=loop2)) loop2.addchild(Literal("step", parent=loop2)) loop2.addchild(Schedule(parent=loop2)) loop2.loop_body.addchild(Return(parent=loop2.loop_body)) # Validation should now pass fuse.validate(loop1, loop2)
def test_psyirvisitor_visit_return_node(): '''Check that when a return PSyIR node is found the actual method called is 'return_node'. This is done to avoid clashing with the Python keyword. ''' from psyclone.psyGen import Return return_node = Return() test_visitor = PSyIRVisitor() with pytest.raises(VisitorError) as excinfo: _ = test_visitor(return_node) assert ("Visitor Error: Unsupported node 'Return' found: method names " "attempted were ['return_node', 'node_node']." "" in str(excinfo))