diff --git a/FABulous/fabric_generator/file_parser.py b/FABulous/fabric_generator/file_parser.py index 8c8cfed..78d08f1 100644 --- a/FABulous/fabric_generator/file_parser.py +++ b/FABulous/fabric_generator/file_parser.py @@ -349,6 +349,10 @@ def parseList( rightList = [] expandListPorts(left, leftList) expandListPorts(right, rightList) + if len(leftList) != len(rightList): + raise ValueError( + f"List file {filePath} does not have the same number of source and sink ports." + ) resultList += list(zip(leftList, rightList)) result = list(dict.fromkeys(resultList)) diff --git a/FABulous/fabric_generator/utilities.py b/FABulous/fabric_generator/utilities.py index b4da591..821abf8 100644 --- a/FABulous/fabric_generator/utilities.py +++ b/FABulous/fabric_generator/utilities.py @@ -20,13 +20,14 @@ def expandListPorts(port, PortList): Raises ------ ValueError - If the port entry contains "[" without matching "]". + If the port entry contains "[" or "{" without matching closing + bracket "]"/"}". """ + if port.count("[") != port.count("]") and port.count("{") != port.count("}"): + raise ValueError(f"Invalid port entry: {port}, mismatched brackets") + # a leading '[' tells us that we have to expand the list if "[" in port: - if "]" not in port: - logger.error("Error in function ExpandListPorts: cannot find closing ]") - raise ValueError # port.find gives us the first occurrence index in a string left_index = port.find("[") right_index = port.find("]") @@ -40,8 +41,20 @@ def expandListPorts(port, PortList): expandListPorts(ExpandListItem, PortList) else: - # print('DEBUG: else, just:',port) - PortList.append(port) + # Multiply ports by the number of multipliers, given in the curly braces. + # We let all curly braces in the port Expansion to be expanded and + # calculate the total number of ports to be added afterward, based on the number of multipliers. + # Also remove the multipliers from port name, before adding it to the list. + port = port.replace(" ", "") # remove spaces + multipliers = re.findall(r"\{(\d+)\}", port) + portMultiplier = sum([int(m) for m in multipliers]) + if portMultiplier != 0: + port = re.sub(r"\{(\d+)\}", "", port) + logger.debug(f"Port {port} has {portMultiplier} multipliers") + for i in range(portMultiplier): + PortList.append(port) + else: + PortList.append(port) # Default parameters (will be overwritten if defined in fabric between 'ParametersBegin' and 'ParametersEnd' diff --git a/docs/source/fabric_definition.rst b/docs/source/fabric_definition.rst index 0995599..aa6307b 100644 --- a/docs/source/fabric_definition.rst +++ b/docs/source/fabric_definition.rst @@ -429,6 +429,9 @@ Configurable connections are defined in either an adjacency list or an adjacency A switch matrix entry is specified by a line ,. For convenience, it is possible to specify multiple ports though a list operator [item1|item2|...]. +There is also a multiplier {N}, where N is the number of times the port should be repeated. +So a {4}N2BEG0 will be expanded to [N2BEG0|N2BEG0|N2BEG0|N2BEG0] + For instance, the following line in a list file .. code-block:: python @@ -468,7 +471,13 @@ A switch matrix multiplexer is modelled by having multiple connections for the s # the same in compact form: N2BEG[0|0|0|0],[N2END3|E2END2|S2END1|LB_O] + # or even more compact: + {4}N2BEG0,[N2END3|E2END2|S2END1|LB_O] + +For completion, the following expressions are all equivalent: +.. code-block:: python + N2BEG[0|0|0|0] <=> {4}N2BEG0 <=> N2BEG[{4}0] <=> {2}N2BEG[0|0] <=> {2}N2BEG[{2}0] <=> [N2BEG0|N2BEG0|N2BEG0|N2BEG0] The ``INCLUDE`` keyword can also be used to include another list file in the current list file. For example: