def amend_pinmux_io(top: Dict, name_to_block: Dict[str, IpBlock]): """ Process pinmux/pinout configuration and assign available IOs """ pinmux = top['pinmux'] pinout = top['pinout'] targets = top['targets'] temp = {} temp['inouts'] = [] temp['inputs'] = [] temp['outputs'] = [] for sig in pinmux['signals']: # Get the signal information from the IP block type of this instance/ mod_name = sig['instance'] m = lib.get_module_by_name(top, mod_name) if m is None: raise SystemExit("Module {} is not searchable.".format(mod_name)) block = name_to_block[m['type']] # If the signal is explicitly named. if sig['port'] != '': # If this is a bus signal with explicit indexes. if '[' in sig['port']: name_split = sig['port'].split('[') sig_name = name_split[0] idx = int(name_split[1][:-1]) else: idx = -1 sig_name = sig['port'] sig_inst = deepcopy(block.get_signal_by_name_as_dict(sig_name)) if idx >= 0 and idx >= sig_inst['width']: raise SystemExit("Index {} is out of bounds for signal {}" " with width {}.".format( idx, sig_name, sig_inst['width'])) if idx == -1 and sig_inst['width'] != 1: raise SystemExit( "Bus signal {} requires an index.".format(sig_name)) # If we got this far we know that the signal is valid and exists. # Augment this signal instance with additional information. sig_inst.update({ 'idx': idx, 'pad': sig['pad'], 'attr': sig['attr'], 'connection': sig['connection'], 'desc': sig['desc'] }) sig_inst['name'] = mod_name + '_' + sig_inst['name'] append_io_signal(temp, sig_inst) # Otherwise the name is a wildcard for selecting all available IO signals # of this block and we need to extract them here one by one signals here. else: sig_list = deepcopy(block.get_signals_as_list_of_dicts()) for sig_inst in sig_list: # If this is a multibit signal, unroll the bus and # generate a single bit IO signal entry for each one. if sig_inst['width'] > 1: for idx in range(sig_inst['width']): sig_inst_copy = deepcopy(sig_inst) sig_inst_copy.update({ 'idx': idx, 'pad': sig['pad'], 'attr': sig['attr'], 'connection': sig['connection'], 'desc': sig['desc'] }) sig_inst_copy['name'] = sig[ 'instance'] + '_' + sig_inst_copy['name'] append_io_signal(temp, sig_inst_copy) else: sig_inst.update({ 'idx': -1, 'pad': sig['pad'], 'attr': sig['attr'], 'connection': sig['connection'], 'desc': sig['desc'] }) sig_inst['name'] = sig['instance'] + '_' + sig_inst['name'] append_io_signal(temp, sig_inst) # Now that we've collected all input and output signals, # we can go through once again and stack them into one unified # list, and calculate MIO/DIO global indices. pinmux['ios'] = (temp['inouts'] + temp['inputs'] + temp['outputs']) # Remember these counts to facilitate the RTL generation pinmux['io_counts'] = { 'dedicated': { 'inouts': 0, 'inputs': 0, 'outputs': 0, 'pads': 0 }, 'muxed': { 'inouts': 0, 'inputs': 0, 'outputs': 0, 'pads': 0 } } for sig in pinmux['ios']: glob_idx = get_index_and_incr(pinmux['io_counts'], sig['connection'], sig['type']) sig['glob_idx'] = glob_idx # Calculate global indices for pads. j = k = 0 for pad in pinout['pads']: if pad['connection'] == 'muxed': pad['idx'] = j j += 1 else: pad['idx'] = k k += 1 pinmux['io_counts']['muxed']['pads'] = j pinmux['io_counts']['dedicated']['pads'] = k # For each target configuration, calculate the special signal indices. known_muxed_pads = {} for pad in pinout['pads']: if pad['connection'] == 'muxed': known_muxed_pads[pad['name']] = pad known_mapped_dio_pads = {} for sig in pinmux['ios']: if sig['connection'] in ['muxed', 'manual']: continue if sig['pad'] in known_mapped_dio_pads: raise SystemExit( 'Cannot have multiple IOs mapped to the same DIO pad {}'. format(sig['pad'])) known_mapped_dio_pads[sig['pad']] = sig for target in targets: for entry in target['pinmux']['special_signals']: # If this is a muxed pad, the resolution is # straightforward. I.e., we just assign the MIO index. if entry['pad'] in known_muxed_pads: entry['idx'] = known_muxed_pads[entry['pad']]['idx'] # Otherwise we need to find out which DIO this pad is mapped to. # Note that we can't have special_signals that are manual, since # there needs to exist a DIO connection. elif entry['pad'] in known_mapped_dio_pads: # This index refers to the stacked {dio, mio} array # on the chip-level, hence we have to add the amount of MIO pads. idx = (known_mapped_dio_pads[entry['pad']]['glob_idx'] + pinmux['io_counts']['muxed']['pads']) entry['idx'] = idx else: assert (0) # Entry should be guaranteed to exist at this point
def amend_pinmux_io(top): """ Check dio_modules/ mio_modules. If not exists, add all modules to mio """ pinmux = top["pinmux"] if "dio_modules" not in pinmux: pinmux['dio_modules'] = [] # list out dedicated IO pinmux['dio'] = [] for e in pinmux["dio_modules"]: # Check name if it is module or signal mname, sname = lib.get_ms_name(e["name"]) # Parse how many signals m = lib.get_module_by_name(top, mname) if m is None: raise SystemExit("Module {} in `dio_modules`" " is not searchable.".format(mname)) if sname is not None: signals = deepcopy([lib.get_signal_by_name(m, sname)]) else: # Get all module signals signals = deepcopy(m["available_input_list"] + m["available_output_list"] + m["available_inout_list"]) sig_width = sum([s["width"] for s in signals]) # convert signal with module name signals = list( map(partial(lib.add_module_prefix_to_signal, module=mname), signals)) # Parse how many pads are assigned if "pad" not in e: raise SystemExit("Should catch pad field in validate.py!") # pads are the list of individual pin, each entry is 1 bit width pads = [] for p in e["pad"]: pads += lib.get_pad_list(p) # check if #sig and #pads are matched if len(pads) != sig_width: raise SystemExit("# Pads and # Sig (%s) aren't same: %d" % (mname, sig_width)) # add info to pads["dio"] for s in signals: p = pads[:s["width"]] pads = pads[s["width"]:] s["pad"] = p pinmux["dio"].append(s) dio_names = [p["name"] for p in pinmux["dio"]] # Multiplexer IO if "mio_modules" not in pinmux: # Add all modules having available io to Multiplexer IO pinmux["mio_modules"] = [] for m in top["module"]: num_io = len(m["available_input_list"] + m["available_output_list"] + m["available_inout_list"]) if num_io != 0: # Add if not in dio_modules pinmux["mio_modules"].append(m["name"]) # List up the dedicated IO to exclude from inputs/outputs # Add port list to `inputs` and `outputs` fields if "inputs" not in pinmux: pinmux["inputs"] = [] if "outputs" not in pinmux: pinmux["outputs"] = [] for e in pinmux["mio_modules"]: tokens = e.split('.') if len(tokens) not in [1, 2]: raise SystemExit( "Cannot parse signal/module in mio_modules {}".format(e)) # Add all ports from the module to input/outputs m = lib.get_module_by_name(top, tokens[0]) if m is None: raise SystemExit("Module {} doesn't exist".format(tokens[0])) if len(tokens) == 1: pinmux["inputs"] += list( filter( lambda x: x["name"] not in dio_names, map( partial(lib.add_module_prefix_to_signal, module=m["name"].lower()), m["available_inout_list"]))) pinmux["inputs"] += list( filter( lambda x: x["name"] not in dio_names, map( partial(lib.add_module_prefix_to_signal, module=m["name"].lower()), m["available_input_list"]))) pinmux["outputs"] += list( filter( lambda x: x["name"] not in dio_names, map( partial(lib.add_module_prefix_to_signal, module=m["name"].lower()), m["available_inout_list"]))) pinmux["outputs"] += list( filter( lambda x: x["name"] not in dio_names, map( partial(lib.add_module_prefix_to_signal, module=m["name"].lower()), m["available_output_list"]))) elif len(tokens) == 2: # Current version doesn't consider signal in mio_modules # only in dio_modules raise SystemExit( "Curren version doesn't support signal in mio_modules {}". format(e))