Skip to content

Commit

Permalink
floogen: Support endpoints with multiple non-contiguous address ranges (
Browse files Browse the repository at this point in the history
#80)

* floogen(routing): Support multiple address ranges per endpoint

* floogen(examples): Update terapool example with multi address range

* docs: Update CHANGELOG
  • Loading branch information
fischeti authored Oct 16, 2024
1 parent b139479 commit 507bb0b
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- 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.
- Add support for multiple non-contiguous address ranges for endpoints.

### Changed

Expand Down
8 changes: 5 additions & 3 deletions floogen/examples/terapool.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ endpoints:
array: [16]
addr_range:
base: 0x0000_8000_0000
size: 0x0000_4000_0000
size: 0x0000_0400_0000
sbr_port_protocol:
- "wide_out"
- name: "peripherals"
addr_range:
start: 0x0000_0000_0000
end: 0x0000_0fff_ffff
- start: 0x0000_0000_0000
end: 0x0000_7fff_ffff
- start: 0x0000_C000_0000
end: 0x0000_C000_ffff
mgr_port_protocol:
- "wide_in"
sbr_port_protocol:
Expand Down
10 changes: 9 additions & 1 deletion floogen/model/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class EndpointDesc(BaseModel):
name: str
description: Optional[str] = ""
array: Optional[Union[Tuple[int], Tuple[int, int]]] = None
addr_range: Optional[AddrRange] = None
addr_range: List[AddrRange] = []
xy_id_offset: Optional[Id] = None
mgr_port_protocol: Optional[List[str]] = None
sbr_port_protocol: Optional[List[str]] = None
Expand All @@ -44,6 +44,14 @@ def dict_to_coord_obj(cls, v):
case {"x": x, "y": y}:
return Coord(x=x, y=y)

@field_validator("addr_range", mode="before")
@classmethod
def addr_range_to_list(cls, v):
"""Convert single AddrRange to list."""
if not isinstance(v, List):
return [v]
return v

@model_validator(mode="after")
def check_addr_range(self):
"""Check if the address range is valid."""
Expand Down
19 changes: 11 additions & 8 deletions floogen/model/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ def compile_nis(self):
"name": f"{ni_name}",
"endpoint": ep_desc,
"routing": self.routing,
"addr_range": ep_desc.addr_range.model_copy() if ep_desc.addr_range else None,
"addr_range": [rng.model_copy() for rng in ep_desc.addr_range],
"id": self.graph.get_node_id(node_name=ni_name).model_copy(),
"uid": self.graph.get_node_uid(node_name=ni_name).model_copy(),
}
Expand All @@ -505,16 +505,19 @@ def compile_nis(self):
case (_,):
node_idx = self.graph.get_node_arr_idx(ni_name)[0]
if ep_desc.is_sbr():
ni_dict["addr_range"] = ep_desc.addr_range.model_copy().set_idx(node_idx)
ni_dict["addr_range"] = [
rng.model_copy().set_idx(node_idx) for rng in ep_desc.addr_range
]

# 2D array case
case (_, n):
x, y = self.graph.get_node_arr_idx(ni_name)
idx = x * n + y
ni_dict["arr_idx"] = Coord(x=x, y=y)
if ep_desc.is_sbr():
ni_dict["addr_range"] = ep_desc.addr_range.model_copy().set_idx(idx)

ni_dict["addr_range"] = [
rng.model_copy().set_idx(idx) for rng in ep_desc.addr_range
]
# Invalid case
case _:
raise ValueError("Invalid endpoint array description")
Expand Down Expand Up @@ -605,7 +608,7 @@ def gen_xy_routing_info(self):
min_y = min(ni.id.y for ni in ni_nodes)
max_x = max(ni.id.x for ni in ni_nodes)
max_y = max(ni.id.y for ni in ni_nodes)
max_address = max(ni.addr_range.end for ni in ni_sbr_nodes)
max_address = max(max(rng.end for rng in ni.addr_range) for ni in ni_sbr_nodes)
xy_routing_info = {}
xy_routing_info["num_x_bits"] = clog2(max_x - min_x + 1)
xy_routing_info["num_y_bits"] = clog2(max_y - min_y + 1)
Expand Down Expand Up @@ -654,9 +657,9 @@ def gen_sam(self):
dest = ni.id
if self.routing.xy_id_offset is not None:
dest -= self.routing.xy_id_offset
addr_range = ni.addr_range
addr_rule = RouteMapRule(dest=dest, addr_range=addr_range, desc=ni.name)
addr_table.append(addr_rule)
for addr_range in ni.addr_range:
addr_rule = RouteMapRule(dest=dest, addr_range=addr_range, desc=ni.name)
addr_table.append(addr_rule)
return RouteMap(name="sam", rules=addr_table)

def render_ports(self, pkg_name=""):
Expand Down
4 changes: 2 additions & 2 deletions floogen/model/network_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# Author: Tim Fischer <fischeti@iis.ee.ethz.ch>

from typing import Optional, ClassVar
from typing import Optional, ClassVar, List
from importlib.resources import files, as_file

from pydantic import BaseModel
Expand All @@ -29,7 +29,7 @@ class NetworkInterface(BaseModel):
id: Optional[Id] = None
uid: Optional[SimpleId] = None
arr_idx: Optional[Id] = None
addr_range: Optional[AddrRange] = None
addr_range: Optional[List[AddrRange]] = None

def is_sbr(self) -> bool:
"""Return true if the network interface is a subordinate."""
Expand Down
2 changes: 1 addition & 1 deletion floogen/model/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def validate_input(self):
def validate_output(self):
"""Validate the address range."""
if self.start >= self.end:
raise ValueError("Invalid address range")
raise ValueError("Address range start must be less than end")
return self

def set_idx(self, idx):
Expand Down

0 comments on commit 507bb0b

Please sign in to comment.