def replace_class_references(ast, classrefs): """ This function performs rewrites for the HLS hardware design. Replace references to static class information with juniper_get_class_reference, a hardcoded syscall back to the host which fetches a juniper_ref of the class metadata. """ def recurse(node): for c in node.children(): recurse(c[1]) if isinstance(node, c_ast.ID): if node.name in classrefs.all: if not node.name in classrefs.referenced: classrefs.referenced[node.name] = len(classrefs.referenced) + 1 fcall = make_func_call_node("juniper_get_class_reference", ["1", str(classrefs.referenced[node.name])]) replace_node(node, fcall) recurse(ast) add_parent_links(ast)
def rewrite_RAM_structure_dereferences(ast): """ The replacement Jamaica headers use RAM_NAME as a global pointer to the external bus interface. Unfortunately, JamaicaBuilder assumes that the type of this pointer is a complex union-of-structs-of-arrays. This rewrites such accesses to use a set of memory access functions declared in fpgaporting.h that allow a more HLS-friendly representation of RAM. We are looking for structures like the following: ArrayRef: StructRef: . ArrayRef: ID: __juniper_ram_master <Anything else> ID: f Constant: int, 2 """ def rewrite_structref(node): """ Called by recurse to check a StructRef node for if rewrites are necessary, and if so, make them. """ deref_type = node.field.name # What was dereferenced ('i', 's', 'c', 'r', etc.) # When a subword type, there may be a higher level arrayref :- __juniper_ram_master[x].s[4] # Save the '4' ast in top_array_deref top_array_deref = None if isinstance(node.parent, c_ast.ArrayRef) and not node == node.parent.subscript: top_array_deref = node.parent.subscript nodetoreplace = node.parent else: nodetoreplace = node arf = node.name if isinstance(nodetoreplace.parent, c_ast.Assignment) and nodetoreplace.parent.op == "=" and nodetoreplace.parent.lvalue == nodetoreplace: callname = RAM_SET_NAME callargs = [arf.subscript, top_array_deref, nodetoreplace.parent.rvalue] nodetoreplace = nodetoreplace.parent # The top level Assignment else: callname = RAM_GET_NAME callargs = [arf.subscript, top_array_deref] callname = callname + str(deref_type) replacementnode = make_func_call_node(callname, callargs) replace_node(nodetoreplace, replacementnode) def recurse(node): """ Recurse depth-first through the provided AST down to the leaf nodes. Then, whilst popping off the stack, any StructRef nodes are passed to rewrite_structref If changes are made, returns True """ changemade = False for c in node.children(): if recurse(c[1]): changemade = True if isinstance(node, c_ast.StructRef): if node.type == "." and isinstance(node.name, c_ast.ArrayRef) and node.name.name.name == RAM_NAME: rewrite_structref(node) changemade = True return changemade while recurse(ast): # After moving nodes we need to correct the parent links. # TODO: Potential optimisation to fix the links only as they are moved, but this isn't too slow add_parent_links(ast)