floogen
is a framework for generating FlooNoC networks on chip. It allows to generate SystemVerilog RTL code for a given network configuration given by a configuration file written in YAML format. This document describes the configuration file format and how write your own configuration file to generate a FlooNoC network.
The following is an example of a configuration file for a 4x4 mesh network:
name: example_system
description: "Example of a configuration file"
routing:
route_algo: "XY"
use_id_table: true
protocols:
- name: "example_axi"
type: "AXI4"
direction: "manager"
data_width: 64
addr_width: 32
id_width: 3
user_width: 1
- name: "example_axi"
type: "AXI4"
direction: "subordinate"
data_width: 64
addr_width: 32
id_width: 3
user_width: 1
endpoints:
- name: "cluster"
array: [4, 4]
addr_range:
base: 0x1000_0000
size: 0x0004_0000
mgr_port_protocol:
- "example_axi"
sbr_port_protocol:
- "example_axi"
routers:
- name: "router"
array: [4, 4]
connections:
- src: "cluster"
dst: "router"
src_range:
- [0, 3]
- [0, 3]
dst_range:
- [0, 3]
- [0, 3]
bidirectional: true
but let's go step by step.
The first part of the configuration file is the system description. It is composed by the following fields:
name
: name of the system. This will be used in the generated RTL code to name the top module and the top-level signals.description
: a short description of the system. This is optional and not used to generate any kind of code
The routing section describes the routing algorithm to be used in the generated network. It is composed by the following fields:
route_algo
: the routing algorithm to be used. Currently XY-Routing (XY
) and table-based (ID
) routing are supporteduse_id_table
: if set totrue
, a system address table will be generated in the package which is used to translate system addresses to endpoint IDs or coordinates. This is always used in table-based routing and can be used in XY-Routing to translate system addresses to XY-coordinates. If XY-Routing is used and this field is set tofalse
, the XY coordinates are automatically derived as address offsets. This is much simpler but requires that the system addresses are contiguous and the address width is large enough to address all endpoints.
The following fields are usually auto-generated by the framework, but can be overwritten if only the package is generated:
addr_offset_bits
: The offset bits to determine the endpoint ID or XY coordinates from the system address. For instance, if you want to use the 4 MSB bits of a 32-bit address to determine the endpoint ID, this field should be set to 28. This field is only used ifuse_id_table
is set tofalse
.num_id_bits
: The number of bits used to encode the endpoint ID. This field is only used ifuse_id_table
is set tofalse
.num_x_bits
: The number of bits used to encode the X-coordinate. This field is only used ifuse_id_table
is set tofalse
.num_y_bits
: The number of bits used to encode the Y-coordinate. This field is only used ifuse_id_table
is set tofalse
.
The protocols section describes the protocols used in the network. It is composed by a list of protocols, each one described by the following fields:
name
: name of the protocol. This will be used as a reference in the framework and in the generated RTL code to name the protocol module and the protocol signals. If the narrow-wide channels are used, they need to be namednarrow
andwide
respectively.type
: Currently onlyAXI4
is supporteddirection
: the direction of the protocol. It can be eithermanager
orsubordinate
. If an endpoint is both manager and subordinate, two protocols need to be defined.data_width
: the data width of the protocoladdr_width
: the address width of the protocolid_width
: the ID width of the protocol. Endpoints with different ID widths for themanager
andsubordinate
protocols are supported.user_width
: the user width of the protocol
The endpoints section describes the endpoints of the network. It is composed by a list of endpoints, each one described by the following fields:
name
: name of the endpoint. This will be used as a reference in the framework and in the generated RTL code to name the endpoint module and the endpoint signals.array
: the array of the endpoint. It can either be a 1D array (e.g.[4]
) or a 2D array (e.g.[4, 4]
). In the latter case, the first element of the array is the number of rows and the second element is the number of columns.adddr_range
: Every endpoint that is a subordinate needs an address range. This field describes the address range of the endpoint. See the Address Map section for more details.mgr_port_protocol
: the list of protocols used by the manager port of the endpoint (if any). The names defined in the protocols section need to be used here.sbr_port_protocol
: the list of protocols used by the subordinate port of the endpoint (if any). The names defined in the protocols section need to be used here.id_offset
: the ID offset of the endpoint. This is used to offset the ID of the endpoint. For instance, if the ID offset is 1, the ID of the first endpoint will be 1, the ID of the second endpoint will be 2, and so on. This is useful when the ID 0 is reserved for a special endpoint (e.g. DRAM). Theid_offset
can either be a single value (e.g.1
) in case ofID
routing or coordinates (e.g.x: 1, y: 1
) in case ofXY
routing. This is useful in meshes where the coordinate of the first endpoint is not(0, 0)
, but rather(1, 1)
. Theid_offset
is also used inXY
routing to determine the location of the endpoint in the network and how to connect it to the routers.
Each endpoint that is a subordinate needs an address range, which can be defined in different ways:
start
andend
: the start and end address of the endpoint. The size of the address range is automatically computed by the framework.start
andsize
: the start address and the size of the address range. The end address of the endpoint is automatically computed by the framework.
For arrays, it usually makes sense to define a base
address with an offset for each element of the array like this:
base
: the base address of the endpoint.size
: the size of the address range. This is the offset added to the address range of the next element of the array.idx
: the index of the endpoint in the array. This is optional and is usually automatically computed by the framework, but could be specified.
The routers section describes the routers of the network. It is composed by a list of routers, each one described by the following fields:
name
: name of the router. This will be used as a reference in the framework and in the generated RTL code to name the router module and the router signals.array
: the array of the router. It can either be a 1D array (e.g.[4]
) or a 2D array (e.g.[4, 4]
). In the latter case, the first element of the array is the number of rows and the second element is the number of columns.tree
: a router structure as a tree. This is mutually exclusive with thearray
field. It is a list of the number of children each level has. For instance[1, 6, 4]
means that one root router is created that has 6 children routers, which each have 4 children routers (in total, there will be1 + 6 + 4*6 = 31
routers). This is useful to create a tree structure of routers.auto_connect
: If theauto_connect
field is set totrue
, the framework will automatically connect the routers to each other. This is useful for meshes and trees. If theauto_connect
field is set tofalse
, the framework will not connect the routers to each other. This is useful for custom topologies. In this case, the connections need to be defined in theconnections
section.
The connections section describes the connections between the endpoints and the routers. It is composed by a list of connections, each one described by the following fields:
src
: the source of the connection. It can either be an endpoint or a router. The reference name of the endpoint or router needs to be used here.dst
: the destination of the connection. It can either be an endpoint or a router. The reference name of the endpoint or router needs to be used here.
In case of array endpoints or routers, one of the following fields needs to be specified:
src_range
and/ordst_range
: the range of the source and destination. This is a list of ranges. Each range is a list of two elements: the start and end index of the range. The first element of the list is the range of the first dimension of the array and the second element is the range of the second dimension of the array (if any). For instance, if the source is a 4x4 array and the source range is[[0, 3], [0, 3]]
, the connection will be made to all the endpoints of the array. If the source is a 4x4 array and the source range is[[0, 3], [0, 0]]
, the connection will be made to the first row of the array.src_idx
and/ordst_idx
: the actual index of a single endpoint or router. This is a list of indices. Each index is a list of two elements: the index of the first dimension of the array and the index of the second dimension of the array (if any). For instance, if the source is a 4x4 array and the source index is[0, 0]
, the connection will be made to the first endpoint of the array. If the source is a 4x4 array and the source index is[0, 1]
, the connection will be made to the second endpoint of the array.
In case of tree routers, you can also specify the following fields:
src_lvl
or dst_lvl
: the level of the source or destination. This is the level of the tree where the router is located. The root router is at level 0, the children routers are at level 1, and so on. This is useful to connect endpoints to the root router or to connect endpoints to the children routers.
floogen
is a Python package that can be installed with pip
:
pip install .
Once installed, you can run floogen
with the following command:
floogen -c <config_file> -o <output_dir>
where <config_file>
is the configuration file and <output_dir>
is the output directory where the generated RTL code will be placed.
Apart from the configuration file, floogen
supports additional options to customize the generated RTL code. The following options are supported:
--outdir
: the output directory where the generated RTL code will be placed. This is equivalent to the-o
option. If it is not specified, the output is printed to stdout.--only-pkg
: only generate the package. This is useful if you want to test single IPs without generating a whole network.--pkg-outdir
: the output directory where the generated package will be placed. By default, the package in thehw
folder is overwitten, since it is also the once that is used bybender
for compiling the IPs. If you want to keep the original package, you can specify a different output directory here.--no-format
: do not format the generated RTL code. By default, the generated RTL code is formatted with verible format, for which theverible-verilog-format
binary needs to be installed. If this option is set, the generated RTL code is not formatted.--visualize
: visualize the generated network. It will create a plot of the graph of the network. If the--outdir
option is specified, the plot is saved in the output directory. Otherwise, it is shown in a window. This is mainly intended for a quick check of the generated network, not a tool for debugging.