Ejemplo n.º 1
0
def elaborate_interconnect(his, scope, max_depth=None, project=None):
    """
    Evaluate top-level !His and every interconnect type it references, returning
    a DFProject. The top-level !His will be a principal node, whilst referenced
    interconnects will be reference nodes.

    Args:
        his      : The top-level !His to evaluate
        scope    : The ElaboratorScope object containing all referenced documents
        max_depth: Ignored at present, provided for compatibility (optional)
        project  : Project to append to, else a new one is created (optional)

    Returns:
        DFProject: Project containing the elaborated interconnect
    """
    # Build the top level interconnect
    df_intc = build_interconnect(his, scope)

    # If no project, create one and add the interconnect as principal
    if not project:
        project = DFProject(his.name, his.source.path)
        project.addPrincipalNode(df_intc)
    else:
        project.addReferenceNode(df_intc)

    # For any referenced interconnect types, build those as reference nodes
    for component in df_intc.components:
        if component.type == DFConstants.COMPONENT.COMPLEX:
            ref_his = scope.get_document(component.ref, expected=His)
            if not ref_his:
                raise ElaborationError(
                    report.error(f"Failed to resolve His {component.ref}"))
            elaborate_interconnect(ref_his, scope, project=project)

    # Return the project
    return project
Ejemplo n.º 2
0
def elaborate_module(top, scope, max_depth=None):
    """
    Elaborate a !Mod tag instance, expanding hierarchy and resolving connections
    up to the maximum requested depth.

    Args:
        top      : The top-level !Mod to elaborate from
        scope    : An ElaboratorScope object containing all documents included
                   directly or indirectly by the top module.
        max_depth: The maximum depth to elaborate to (optional, by default
                   performs a full depth elaboration - max_depth=None)

    Returns:
        DFProject: Contains the elaborated block and all interconnects used
    """
    # Build a new project
    project = DFProject(top.name, top.source.path)

    # Build the tree for the root block
    block = build_tree(
        top,                    # The top-level !Mod to evaluate
        top.name,               # Name to use for the top-level !Mod instance
        None,                   # No parent exists
        scope,                  # Scope to use for elaboration
        max_depth = max_depth   # Maximum depth to elaborate to
    )

    # Attach the block as a principal node to the project
    project.addPrincipalNode(block)

    # Get a list of all of the interconnection types directly used by the design
    def list_interconnects(block):
        types = [x.type for x in block.getAllPorts()]
        for child in block.children:
            types += list_interconnects(child)
        return types

    used_types = []

    for block in (x for x in project.nodes.values() if isinstance(x, DFBlock)):
        used_types += list_interconnects(block)

    # Expand the directly used types to include all referenced types
    def chase_his(his_ref):
        his = scope.get_document(his_ref, His)
        if not his:
            raise ElaborationError(report.error(f"Could not locate His {his_ref}"))
        sub_his  = [x for x in his.ports if isinstance(x, HisRef)]
        required = [his] + [scope.get_document(x.ref, His) for x in sub_his]
        for item in sub_his:
            required += chase_his(item.ref)
        return required

    all_required = []
    for his_type in used_types:
        all_required += chase_his(his_type)

    # Ensure the list of His types is unique
    all_required = list(set(all_required))

    # Build and attach descriptions of each interconnect type
    for his in all_required:
        project.addReferenceNode(build_interconnect(his, scope))

    # Log all of the interconnect types that were detected
    report.info(
        f"Identified {len(all_required)} interconnect types in the design",
        body="\n".join((x.name for x in all_required))
    )

    # Log the design hierarchy
    def chase_hierarchy(block, depth=0):
        intro = ""
        if depth > 0: intro += (" | " * (depth - 1)) + " |-"
        intro += block.id
        lines = [intro]
        for child in block.children: lines += chase_hierarchy(child, depth+1)
        return lines

    txt_hier = chase_hierarchy(block)
    report.info(
        f"Design hierarchy contains {len(txt_hier)} nodes", body="\n".join(txt_hier)
    )

    # Return the project
    return project