Beispiel #1
0
 def set_input(self, input_ref: AsConnectionRef):
     """Set the data input reference for this layer.
     Each layer's input reference should be @ (0,0), with the layer.offset
     signifying the layer's offset from the base layer."""
     port = input_ref.port
     # Check data widths if the port's data width is already fixed
     if is_data_width_resolved(port.data_width):
         port_data_width = Port.data_width_to_string(port.data_width)
         if self.data_width != port_data_width:
             LOG.error(
                 ("Incompatiple layer input detected! '%s'(%s) -> "
                  "'%s'(%s)"),
                 port.code_name,
                 port_data_width,
                 self.name,
                 self.data_width,
             )
             raise AsConnectionError(
                 "Layer and input port data widths differ!")
     if ((input_ref.row < self.parent.rows)
             and (input_ref.col < self.parent.columns)
             and (input_ref.row >= 0 and input_ref.col >= 0)):
         self.input = input_ref
         LOG.debug("Set input for layer '%s' to %s.", self.name,
                   str(input_ref))
     else:
         LOG.error("Input '%s' is out of bounds!", str(input_ref))
Beispiel #2
0
def resolve_data_width(port: Port) -> tuple:
    """Analyse the data width of port and replace generics
    in the data width with the value of matching generics
    found in the module the port belongs to."""
    # Is it already resolved?
    if is_data_width_resolved(port.data_width):
        return port.data_width
    # "Variable" dictionary for 'eval_data_width'
    gvals = {}
    for gen in port.generics:
        # Get value
        val = gen.get_value(top_default=False)
        # If no static value is available,
        # use the code name of the linked generic
        if val is None:
            val = getattr(gen.value, "code_name", None)
            # If that couldn't be fetched, skip this generic
            if val is None:
                continue
        gvals[gen.code_name] = val
    # Evaluate the data width
    new_data_width = as_help.eval_data_width(port, gvals)
    # If the evaluation could not complete
    if not is_data_width_resolved(new_data_width):
        LOG.info(
            ("Can't automatically resolve data width of '%s' in '%s'. "
             "Generic(-s) in '%s' have no value set or is(are) external!"),
            port.code_name,
            port.parent.name,
            port.data_width_to_string(port.data_width),
        )
        return port.data_width
    return new_data_width
Beispiel #3
0
def manage_data_widths(source: Port, sink: Port) -> bool:
    """This function checks if the data widths of both ports are compatible.
    It resolves the data widths by replacing the generics with their respective
    values and compares the resolved versions. The port objects aren't modified.
    Exception: For toplevel modules an automatic propagation of generics is
    attempted if the specific case is clear cut.
    Parameters:
    source and sink: Both Port objects to compare and adjust.
    Returns: Boolean value: True on success, else False.
    """
    # Determine data flow direction
    if source.get_direction_normalized() == "in":
        pin = source
        pout = sink
    else:
        pin = sink
        pout = source

    # Get "state" of data widths (are they fixed?)
    pin_res = is_data_width_resolved(pin.data_width)
    pout_res = is_data_width_resolved(pout.data_width)

    # If fixed and matching -> OK
    if pin_res and pout_res:
        if pin.data_width == pout.data_width:
            return True

    LOG.debug(
        "Data widths of '%s' and '%s' not resolved, resolving...",
        pin.code_name,
        pout.code_name,
    )
    # Evaluate data widths
    pin_rdw = resolve_data_width(pin)
    pout_rdw = resolve_data_width(pout)

    # Do they match now? Yes -> OK
    if pin_rdw == pout_rdw:
        LOG.debug("Data widths resolved successfully!")
        return True
    # Else: Warn user; automatic adjustment requires more development!
    # The simple "beta" version caused more problems than it was worth...

    # For toplevel modules (AXI Master / Slave):
    # Attempt automatic management of the generics in very simple cases
    # as it is inconvenient for the user to manually resolve toplevel
    # problems (especially for auto-instantiated modules like AXI_Masters)
    pin_mod = AsModule.get_parent_module(pin)
    pout_mod = AsModule.get_parent_module(pout)
    # If either port's module is directly instantiated in toplevel
    if (pin_mod.modlevel < 2) or (pout_mod.modlevel < 2):
        igen = pin.generics
        ogen = pout.generics

        # If both ports have exactly one generic
        if len(igen) == 1 and len(ogen) == 1:
            igen = igen[0]
            ogen = ogen[0]
            # Store current values
            igen_v = igen.value
            ogen_v = ogen.value
            # Propagate the source generic to the sink port
            igen.value = ogen
            pin_rdw = resolve_data_width(pin)
            # Did that resolve the difference?
            if pin_rdw == pout_rdw:
                LOG.debug(
                    ("Generic Auto-Propagation: For ports '%s' and "
                     "'%s' of modules '%s' and '%s': Set value of "
                     "generic '%s' to generic '%s' of module '%s'."),
                    pout.code_name,
                    pin.code_name,
                    pin_mod.name,
                    pout_mod.name,
                    igen.code_name,
                    ogen.code_name,
                    pout_mod.name,
                )
                return True
            # If not, reverse the propagation and try the other way around
            igen.value = igen_v
            ogen.value = igen
            pin_rdw = resolve_data_width(pin)
            pout_rdw = resolve_data_width(pout)
            # Did that work?
            if pin_rdw == pout_rdw:
                LOG.debug(
                    ("Generic Auto-Propagation: For ports '%s' and "
                     "'%s' of modules '%s' and '%s': Set value of "
                     "generic '%s' to generic '%s' of module '%s'."),
                    pout.code_name,
                    pin.code_name,
                    pin_mod.name,
                    pout_mod.name,
                    ogen.code_name,
                    igen.code_name,
                    pin_mod.name,
                )
                return True
            # If not, reverse the propagation and print the user warning
            ogen.value = ogen_v
            pout_rdw = resolve_data_width(pout)
        # Gather some data to generate a useful user message
        # Involved Generic names
        all_gens = []
        all_gens.extend(pout.generics)
        all_gens.extend(pin.generics)
        all_gens = [gen.code_name for gen in all_gens]
        # Module names
        pout_mod = pout_mod.name
        pin_mod = pin_mod.name
        # Data width strings
        pout_dw = Port.data_width_to_string(pout.data_width)
        pout_rdw = Port.data_width_to_string(pout_rdw)
        pin_dw = Port.data_width_to_string(pin.data_width)
        pin_rdw = Port.data_width_to_string(pin_rdw)

        # User warning message
        LOG.error(
            ("Data widths between ports '%s' and '%s' of modules "
             "'%s' and '%s' differ and must be adjusted manually!\n"
             "Data widths: For port '%s': (%s) - resolved as (%s) | "
             "For port '%s': (%s) - resolved as (%s).\n"
             "Use generics '%s' of the respective modules."),
            pout.code_name,
            pin.code_name,
            pout_mod,
            pin_mod,
            pout.code_name,
            pout_dw,
            pout_rdw,
            pin.code_name,
            pin_dw,
            pin_rdw,
            all_gens,
        )

    # Special case for "slv_reg_interface" connections to as_regmgr
    if (pin.parent.type == "slv_reg_interface") and (pout.parent.type
                                                     == "slv_reg_interface"):
        if pin_mod.entity_name == "as_regmgr":
            pin.data_width = copy(pout.data_width)
            return True
        if pout_mod.entity_name == "as_regmgr":
            pout.data_width = copy(pin.data_width)
            return True

    return False