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))
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
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