Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

floogen: Support endpoints with multiple non-contiguous address ranges #80

Merged
merged 3 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <[email protected]>

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
Loading