From b6a816f8b280f88b66d059a1bacf0dbb26702983 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Thu, 3 Oct 2024 17:28:43 +0200 Subject: [PATCH] floogen: Support negative step sizes for connection ranges (#77) * floogen(graph): Allow negative increments when specifying `range` in `connections` * floogen(test): Extend tests with range tests * docs: Update CHANGELOG --- CHANGELOG.md | 1 + floogen/model/graph.py | 33 +++++++++++++-------------------- floogen/tests/graph_test.py | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9dddc2b..5826d6b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - The `data_width` and `user_width` fields for `protocols` are now also validated to be compatible with each other. - All the various `*Cfg`'s is now rendered by _FlooGen_, either in the `*_noc_pkg` or in the `*_noc` module itself. - Added support for single-AXI configuration networks. +- Support for negative increments when specifying a `src_range` or `dst_range` in the `connections` schema. ### Changed diff --git a/floogen/model/graph.py b/floogen/model/graph.py index 3544e613..9a1caf5e 100644 --- a/floogen/model/graph.py +++ b/floogen/model/graph.py @@ -151,26 +151,19 @@ def get_link_edges(self, with_name=False): def get_nodes_from_range(self, node: str, rng: List[Tuple[int]]): """Return the nodes from the range.""" nodes = [] - match rng: - # 2D range - case [(start1, end1), (start2, end2)]: - for x in range(start1, end1 + 1): - for y in range(start2, end2 + 1): - node_name = f"{node}_{x}_{y}" - if self.has_node(node_name): - nodes.append(node_name) - else: - raise ValueError(f"Node {node_name} does not exist") - # 1D range - case [(start, end)]: - for i in range(start, end + 1): - node_name = f"{node}_{i}" - if self.has_node(node_name): - nodes.append(node_name) - else: - raise ValueError(f"Node {node_name} does not exist") - case _: - raise NotImplementedError(f"Unsupported range {rng}") + if len(rng) == 0: + raise ValueError("Range is empty") + start, end = rng[0] + step = 1 if end > start else -1 + for i in range(start, end + step, step): + if len (rng) == 1: + node_name = f"{node}_{i}" + if self.has_node(node_name): + nodes.append(node_name) + else: + raise ValueError(f"Node {node_name} does not exist") + else: + nodes.extend(self.get_nodes_from_range(f"{node}_{i}", rng[1:])) return nodes def get_nodes_from_idx(self, node: str, idx: List[int]): diff --git a/floogen/tests/graph_test.py b/floogen/tests/graph_test.py index b4533647..b5e07e6b 100644 --- a/floogen/tests/graph_test.py +++ b/floogen/tests/graph_test.py @@ -248,6 +248,33 @@ def test_get_nodes_from_range3(graph): nodes = graph.get_nodes_from_range("A", [(0, 3)]) assert nodes == ["A_0", "A_1", "A_2", "A_3"] +def test_get_nodes_from_range4(graph): + """Test getting all nodes from a range""" + graph.add_node("A_0", type="router") + graph.add_node("A_1", type="router") + graph.add_node("A_2", type="router") + graph.add_node("A_3", type="router") + nodes = graph.get_nodes_from_range("A", [(2, 1)]) + assert nodes == ["A_2", "A_1"] + +def test_get_nodes_from_range_fail1(graph): + """Test getting all nodes from a range""" + graph.add_node("A_0", type="router") + graph.add_node("A_1", type="router") + graph.add_node("A_2", type="router") + graph.add_node("A_3", type="router") + with pytest.raises(ValueError): + graph.get_nodes_from_range("A", [(0, 1), (0, 1)]) + +def test_get_nodes_from_range_fail2(graph): + """Test getting all nodes from a range""" + graph.add_node("A_0", type="router") + graph.add_node("A_1", type="router") + graph.add_node("A_2", type="router") + graph.add_node("A_3", type="router") + with pytest.raises(ValueError): + graph.get_nodes_from_range("A", [(0, 99)]) + def test_get_nodes_from_idx(graph): """Test getting all nodes from an index"""