help="make xml output pretty")
(options, args) = parser.parse_args()

setupDeferredLogging('preprocessor.log', logging.DEBUG if options.debug else logging.INFO)

if (not options.sourceDir):
    logging.error("sourceDirectory option is mandatory. Use '--help' for informations on how to use this module")
    sys.exit(1)

#prepare xml output
doc = Document()
callGraphRoot = doc.createElement("callGraph")
doc.appendChild(callGraphRoot)

filesInDir = dirEntries(str(options.sourceDir), True, 'h90')

#first pass: loop through all h90 files (hybrid fortran 90) in the current directory
#   and build the basic callgraph based on subprocedures and calls. Also parse @-directives for annotations.
progressIndicatorReset(sys.stderr)
for fileNum, fileInDir in enumerate(filesInDir):
    parser = H90XMLCallGraphGenerator(doc)
    parser.processFile(fileInDir)
    logging.debug("Callgraph generated for " + fileInDir + "")
    printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir), "Callgraph parsing")

#second pass: moved to generateP90Codebase.py since we need symbol analysis already

if (options.pretty):
	sys.stdout.write(doc.toprettyxml())
else:
	sys.stdout.write(doc.toxml())
Exemple #2
0
if (not options.sourceDir):
    logging.error(
        "sourceDirectory option is mandatory. Use '--help' for informations on how to use this module"
    )
    sys.exit(1)

#prepare xml output
doc = Document()
callGraphRoot = doc.createElement("callGraph")
doc.appendChild(callGraphRoot)

filesInDir = dirEntries(str(options.sourceDir), True, 'h90')

#first pass: loop through all h90 files (hybrid fortran 90) in the current directory
#   and build the basic callgraph based on subprocedures and calls. Also parse @-directives for annotations.
progressIndicatorReset(sys.stderr)
for fileNum, fileInDir in enumerate(filesInDir):
    parser = H90XMLCallGraphGenerator(doc)
    parser.processFile(fileInDir)
    logging.debug("Callgraph generated for " + fileInDir + "")
    printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir),
                           "Callgraph parsing")

#second pass: moved to generateP90Codebase.py since we need symbol analysis already

if (options.pretty):
    sys.stdout.write(doc.toprettyxml())
else:
    sys.stdout.write(doc.toxml())
sys.stdout.flush()
def analyseParallelRegions(doc, appliesTo):
	callNodes = doc.getElementsByTagName("call")
	routineNodes = doc.getElementsByTagName("routine")
	templates = doc.getElementsByTagName("parallelRegionTemplate")
	for routineNum, routineNode in enumerate(routineNodes):
		filterParallelRegionNodes(doc, routineNode, appliesTo, templates)
		printProgressIndicator(
			sys.stderr,
			"",
			routineNum + 1,
			len(routineNodes),
			"Filtering parallel regions for %s" %(appliesTo) if appliesTo != "" else "Filtering parallel regions"
		)
	progressIndicatorReset(sys.stderr)
	callNodesByCallerName = getCalleesByCallerName(callNodes)
	callNodesByCalleeName = getCallersByCalleeName(callNodes)

	parallelRegionNodes = doc.getElementsByTagName("parallelRegions")
	parallelRegionNodesByRoutineName = {}
	sys.stderr.write("Populating parallel region cache\n")
	for regionNum, parallelRegionNode in enumerate(parallelRegionNodes):
		routine = parallelRegionNode.parentNode
		routineName = routine.getAttribute("name")
		if appliesTo == "GPU" and parallelRegionNodesByRoutineName.get(routineName) != None:
			raise Exception("Multiple GPU parallel regions in subroutine %s" %(routineName))
		parallelRegionNodesByRoutineName[routineName] = parallelRegionNode

	kernelCallerProblemFound = False
	messagesPresentedFor = []
	sys.stderr.write("Parallel region analysis\n")
	for regionNum, parallelRegionNode in enumerate(parallelRegionNodes):
		if not parallelRegionNode.parentNode.tagName == "routine":
			raise Exception("Parallel region not within routine.")
		parallelRegionNode.parentNode.setAttribute("parallelRegionPosition", "within")
		routine = parallelRegionNode.parentNode
		routineName = routine.getAttribute("name")
		if routineName == None:
			raise Exception("Kernel routine without name")
		addAttributeToAllCallGraphAncestors(routineNodes, callNodesByCalleeName, routine, "parallelRegionPosition", "inside")
		addAttributeToAllCallGraphHeirs(routineNodes, callNodesByCallerName, routine, "parallelRegionPosition", "outside")

		#rename this parallelRegion node to 'activeParallelRegion'
		children = parallelRegionNode.childNodes
		existingActiveParallelRegions = routine.getElementsByTagName("activeParallelRegions")
		newRegionNode = None
		newRegionNodeNeedsAppending = False
		if len(existingActiveParallelRegions) > 0:
			newRegionNode = existingActiveParallelRegions[0]
		else:
			newRegionNode = doc.createElement("activeParallelRegions")
			newRegionNodeNeedsAppending = True
		for child in children:
			newRegionNode.appendChild(child.cloneNode(deep=True))
		routine.removeChild(parallelRegionNode)
		if newRegionNodeNeedsAppending:
			routine.appendChild(newRegionNode)

		if appliesTo != "GPU":
			continue

		#check our kernel callers. Rule: Their direct callees should not be a kernel caller themselves.
		kernelCallers = callNodesByCalleeName.get(routineName)
		if not kernelCallers:
			continue

		for kernelCaller in kernelCallers:
			kernelCallerName = kernelCaller.getAttribute("caller")
			kernelWrapperCall = getFirstKernelCallerInCalleesOf(kernelCallerName, callNodesByCallerName, parallelRegionNodesByRoutineName)
			if kernelWrapperCall != None:
				kernelWrapperName = kernelWrapperCall.getAttribute("callee")
				if not kernelCallerProblemFound:
					logging.warning("Subroutine %s calls at least one kernel (%s) and at least one kernel wrapper (%s). \
This may cause device attribute mismatch compiler errors. In this case please wrap all kernels called by %s, such that it does not call a mix of kernel wrappers and kernels.\n"
						%(kernelCallerName, routineName, kernelWrapperName, kernelCallerName)
					)
					kernelCallerProblemFound = True
					messagesPresentedFor.append(kernelCallerName)
				elif kernelCallerName not in messagesPresentedFor:
					messagesPresentedFor.append(kernelCallerName)
					logging.warning("...same for %s: calls kernel %s, kernel wrapper %s" %(kernelCallerName, routineName, kernelWrapperName))