def trace_from_functions(
    funcs, jamaicaoutputdir, additionalsourcefiles, filestobuild, all_reachable_functions, reachable_non_translated
):
    """
	Given a list of java signatures, search for its funcdecl, then trace from each function 
	flowing funccall nodes to determine all reachable functions.
	
	Returns the interfaceResolver which contains information about encountered interface calls
	"""
    interfaceResolver = InterfaceResolver(jamaicaoutputdir)

    for sig in funcs:
        filestosearch = get_files_to_search(sig, jamaicaoutputdir)

        if additionalsourcefiles != None:
            for f in additionalsourcefiles:
                if not f in filestosearch:
                    filestosearch.append(f)
                filestobuild.add(f)

        funcdecl = c_decl_node_of_java_sig(sig, jamaicaoutputdir)
        rf = ReachableFunctions(funcdecl.parent, filestosearch, jamaicaoutputdir, interfaceResolver)

        # Don't forget to include the starting point
        all_reachable_functions.add(funcdecl.parent)
        filestobuild.add(funcdecl.parent.coord.file)

        for f in rf.files:
            filestobuild.add(f)
        for f in rf.reachable_functions:
            all_reachable_functions.add(f)
        for r in rf.reachable_non_translated:
            reachable_non_translated.add(r)

    return interfaceResolver
def write_functions_c(functions, jamaicaoutputdir, outputfile):
    """
	Prepare functions.c, which contains the dispatch functions that calls the translated methods.
	"""
    bindings = {}
    callid = 0

    s = "#include <jamaica.h>\n"
    s += "#include <toplevel.h>\n"
    s += "#include <Main__.h>\n"
    s += "\n"
    s += "int __juniper_call(int call_id) {\n"
    s += "\tswitch(call_id) {\n"

    for f in functions:
        bindings[callid] = f  # Note the binding of index to function
        s += "\t\tcase " + str(callid) + ":\n"

        s += "\t\t\t__juniper_thread = (jamaica_thread) __juniper_args[0];\n"

        # The return type affects how we call it
        # TODO: Currently 64-bit return types are not supported
        declnode = c_decl_node_of_java_sig(f, jamaicaoutputdir)
        returntype = str(declnode.type.type.type.names[0])
        if returntype == "void":
            s += "\t\t\t" + str(call_code_for_sig(f, jamaicaoutputdir)) + "\n"
            s += "\t\t\treturn 0;\n"
        elif returntype in ["float", "jamaica_float"]:
            s += "\t\t\t" + returntype + " rv;\n"
            s += "\t\t\trv = " + str(call_code_for_sig(f, jamaicaoutputdir)) + "\n"
            s += "\t\t\treturn *(int *)&rv;"
        else:
            s += "\t\t\treturn (int) " + str(call_code_for_sig(f, jamaicaoutputdir)) + "\n"
        s += "\n"
        callid = callid + 1

    s += "\t\tdefault:\n"
    s += "\t\t\treturn 0;\n"
    s += "\t}\n"
    s += "}\n"
    hfile = open(outputfile, "w")
    hfile.write(s)
    hfile.close()
    return bindings
def call_code_for_sig(sig, jamaicaoutputdir):
    """
	Given a Java signature, return the code to call the translated C version of it, to be 
	placed in functions.cpp.
	Note: This function doesn't check the AST structure. This IS checked in get_paramlist_of_sig 
	so something will error if the AST is wrong, but this in general assumes a well-formed AST.
	"""
    declnode = c_decl_node_of_java_sig(sig, jamaicaoutputdir)
    funcdecl = declnode.children()[0][1]
    funcname = declnode.name
    paramlist = funcdecl.children()[0][1]
    rv = funcname + "("
    paramnum = 1  # Param 0 is always used to pass the current thread context
    for pid in xrange(len(paramlist.params)):
        # Insert an explicit cast to the target type
        # Handles single-stage pointers and base types only, no arrays, because
        # it is believed that this is all that Jamaica builder will output.
        prm = paramlist.params[pid]
        pointer = False
        if isinstance(prm.type, c_ast.PtrDecl):
            pointer = True
            pdec = prm.type.type
        else:
            pdec = prm.type

        if pointer and pdec.type.names[0] == "jamaica_thread":
            rv += "&__juniper_thread"
        else:
            rv += juniperrewrites.c_cast_for_type(prm.type) + " "
            # rv += "(" + str(pdec.type.names[0])
            # if pointer:
            # 	rv += "*"
            # rv += ") "
            rv += "__juniper_args[" + str(paramnum) + "]"
            paramnum = paramnum + 1

        if not pid == len(paramlist.params) - 1:
            rv += ", "

    rv += ");"
    return rv
def get_paramlist_of_sig(sig, jamaicaoutputdir):
    """
	Given a Java signature, find the corresponding C function declaration in the AST
	and then parse to the parameter list. Returns a c_ast.ParamList or None in the
	case of an error.
	"""
    declnode = c_decl_node_of_java_sig(sig, jamaicaoutputdir)
    funcdecl = declnode.children()[0][1]
    if not isinstance(funcdecl, c_ast.FuncDecl):
        raise juniperrewrites.CaicosError(
            "Unexpected function declaration format for signature "
            + str(sig)
            + ". Expected FuncDecl, got "
            + type(funcdecl).__name__
        )
    paramlist = funcdecl.children()[0][1]
    if not isinstance(paramlist, c_ast.ParamList):
        raise juniperrewrites.CaicosError(
            "Unexpected function declaration format for signature "
            + str(sig)
            + ". Expected ParamList, got "
            + type(funcdecl).__name__
        )
    return paramlist
Exemplo n.º 5
0
def refactor_src(bindings, jamaicaoutput, targetdir, debug):
	"""
	Copy the C source code for the Jamaica project. For files that contain functions that have
	been implemented on the FPGA, replace their contents with code to invoke the FPGA instead.
	
	Outputs files to targetdir
	"""
	
	#Which are the C files we will need to rewrite?
	filestoedit = set()
	for _, sig in bindings.iteritems():
		filestoedit.add(c_filename_of_java_method_sig(sig, jamaicaoutput))
		
	#Copy the C files over, rewriting those that contain functions we have passed to the hardware
	mkdir(targetdir)
	for item in os.listdir(jamaicaoutput):
		filepath = os.path.join(jamaicaoutput, item)
		if os.path.isfile(filepath) and (filepath.endswith(".c") or filepath.endswith(".h")):
			if not filepath in filestoedit:
				#Just copy the file, no edits required
				shutil.copy(filepath, targetdir)
			else:
				#Any previous edits to the AST need to be disregarded
				astcache.invalidate_ast_for(filepath)

				#Which sigs are in this file?
				toreplace = []
				for callid, sig in bindings.iteritems():
					if c_filename_of_java_method_sig(sig, jamaicaoutput) == filepath:
						decl = c_decl_node_of_java_sig(sig, jamaicaoutput)
						bounds = get_line_bounds_for_function(decl)
						toreplace.append((bounds, callid, sig, decl))

				toreplace.sort() #Sort by ascending line number

				filecontents = open(filepath).readlines()
				output = "#include <juniper_fpga_interface.h>\n#include <juniperoperations.h>\n#include \"jamaica.h\"\n#include <sys/mman.h>\n\n"
				output += "extern void caicos_handle_pcie_interrupt(jamaica_thread *ct, int devNo, int partNo);\n\n"
				if debug:
					output += "#include \"caicos_debug.h\"\n\n"
				lineno = 1

				for bounds, callid, sig, decl in toreplace:
					while lineno <= bounds[0]:
						output = output + filecontents[lineno-1]
						lineno += 1
					
					output += "\t//~~~~~~~~~~~~~~~~" + str(sig) + "  " + str(bounds) + "~~~~~~~~~~~~~~~~~~~~~\n"
					output += "\t" + str(generate_replacement_code(sig, decl, callid, jamaicaoutput, (0, 0)))
					
					if bounds[1] == None: #If a replacement is the last thing in the file we'll need to close some things
						#TODO: Is this branch required any more? Suspect not.
						output += "}\n\n#else\n#error 'jamaica.h' not found!\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n"
						lineno = len(filecontents) #Done copying
					else:
						output += "}\n"
						lineno = bounds[1] + 1
				
				#Copy the rest of the file in
				while lineno-1 < len(filecontents):
					output = output + filecontents[lineno-1]
					lineno += 1
				
				with open(os.path.join(targetdir, item), "w") as outf:
					outf.write(output)