mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
rfnoc oot: Move fpga/ subdir into rfnoc/
During redesign of the OOT module directory layout, the block YAMLs and dts files were moved under `rfnoc/`, but the gateware was not. This causes an inconsistency in the directory layout before and after installation, making it hard to switch between installed and not-installed versions of RFNoC modules. For example, block YAMLs are in `./rfnoc/blocks/*.yml`, and gateware is in `fpga/gain/rfnoc_block_gain/*`. After installation, block YAMLs are in `$PREFIX/share/uhd/rfnoc/blocks/*.yml`, and gateware is in `$PREFIX/share/uhd/rfnoc/fpga/gain/rfnoc_block_gain/*` -- note the discrepancy. This fixes two immediate issues: - When building the X410 example in-tree, the DTS file was not being found because it used the same finding logic as the gateware source files. - When building any image core file post-installation, none of the gateware could be found because it used the same logic for finding gateware inside the OOT, which is in a different location relative to the block YAMLs. By removing the inconsistencies, both these use cases work. A note on backward compatibility: - Existing OOT modules already have the issue that building bitfiles post-install does not work, and that will continue to not work. However, otherwise, they will keep working as before. - Because people may have gotten accustomed to specifying the RFNoC OOT module as the include directory (e.g., `rfnoc_image_builder -I /path/to/rfnoc-gain`), we allow for this use case, and auto-correct the include path in this case with some backward compatibility code. - Building the rfnoc-gain/icores/x410_XG_200_rfnoc_image_core.yml example image core file now also works, even with older versions of rfnoc-gain.
This commit is contained in:
parent
332646f91f
commit
8684d3c15a
@ -17,6 +17,9 @@ Change Log for Releases
|
||||
* Bug Fixes
|
||||
- Calling `recv()` on an RX streamer connected to an RFNoC device with a
|
||||
zero timeout value now correctly returns immediately.
|
||||
- rfnoc-gain: Moved the fpga/ subdirectory under rfnoc/. This way, the
|
||||
directory structure inside the OOT module is identical to the directory
|
||||
structure after installation.
|
||||
* Removals / Deprecations
|
||||
- Removed tools/uhd_dump. This tool is obsolete, the USRP X3x0 is not even
|
||||
compatible with it any more. Dumps can be recorded and analyzed with wireshark
|
||||
|
||||
@ -11,8 +11,8 @@ steps:
|
||||
- "apps/*.cpp"
|
||||
- "build"
|
||||
- "examples/*.py"
|
||||
- "fpga/gain/ip"
|
||||
- "fpga/gain/rfnoc_block_gain"
|
||||
- "rfnoc/fpga/gain/ip"
|
||||
- "rfnoc/fpga/gain/rfnoc_block_gain"
|
||||
- "icores/*.yml"
|
||||
- "lib/*.cpp"
|
||||
- "gr-*"
|
||||
@ -39,14 +39,14 @@ steps:
|
||||
pattern: "^ .+py$"
|
||||
repl: " # Insert your example sources here if you want them to be installed"
|
||||
- comment_out:
|
||||
file: fpga/newmod/CMakeLists.txt
|
||||
file: rfnoc/fpga/newmod/CMakeLists.txt
|
||||
range: [9, 13]
|
||||
- search_and_replace:
|
||||
file: fpga/newmod/CMakeLists.txt
|
||||
file: rfnoc/fpga/newmod/CMakeLists.txt
|
||||
pattern: "add_subdirectory\\(([a-z0-9_]+)\\)"
|
||||
repl: "#add_subdirectory(rfnoc_block_myblock)"
|
||||
- insert_before:
|
||||
file: fpga/newmod/CMakeLists.txt
|
||||
file: rfnoc/fpga/newmod/CMakeLists.txt
|
||||
pattern: "# IP gets"
|
||||
text: "# Uncomment the following lines to add your own IP:\n"
|
||||
- search_and_replace:
|
||||
|
||||
@ -215,7 +215,6 @@ endif(NOT CMAKE_MODULES_DIR)
|
||||
########################################################################
|
||||
if(UHD_FPGA_DIR)
|
||||
add_subdirectory(rfnoc)
|
||||
add_subdirectory(fpga/gain)
|
||||
add_subdirectory(icores)
|
||||
endif()
|
||||
if(UHD_FOUND)
|
||||
|
||||
@ -18,7 +18,7 @@ out-of-tree blocks.
|
||||
Examples that are listed in CMake get installed into `share/rfnoc-gain/examples`
|
||||
within the installation prefix.
|
||||
|
||||
* `fpga/gain`: This directory contains the gateware for the HDL modules
|
||||
* `rfnoc/fpga/gain`: This directory contains the gateware for the HDL modules
|
||||
of the individual RFNoC blocks, along with their testbenches, and additional
|
||||
modules required to build the blocks. There is one subdirectory for every
|
||||
block (or module, or transport adapter). This is also where to define IP that
|
||||
@ -60,13 +60,81 @@ out-of-tree blocks.
|
||||
the UHD Python API is not found (or Python dependencies for building bindings,
|
||||
such as pybind11, are not found) no Python bindings will be generated.
|
||||
|
||||
* `rfnoc`: This directory contains all the block definitions (YAML files).
|
||||
* `rfnoc/blocks`: This directory contains all the block definitions (YAML files).
|
||||
These block definitions can be read by the RFNoC tools, and will get
|
||||
installed into the system for use by other out-of-tree modules.
|
||||
Within this directory, there needs to be one subdirectory for every type of
|
||||
RFNoC component that this out-of-tree module contains: `blocks` for regular
|
||||
RFNoC blocks, `modules` for generic Verilog modules, and `transport_adapters`
|
||||
for RFNoC transport adapters.
|
||||
If an out-of-tree module contains other types of RFNoC components, such as
|
||||
modules or transport adapters, they should be placed in the appropriate
|
||||
subdirectory of `rfnoc` (e.g., `rfnoc/modules` or `rfnoc/transport_adapters`).
|
||||
Like with the gateware, these get installed into the RFNoC package data
|
||||
directory, e.g., `/usr/share/uhd/rfnoc/blocks/*.yml`.
|
||||
|
||||
* `rfnoc/dts`: This is an example folder for when blocks or transport adapters
|
||||
require additional .dtsi files (DTS include files). The only file in here is
|
||||
empty, and is included for example purposes only.
|
||||
|
||||
A note on the directory structure: After installation, all files that are
|
||||
required by `rfnoc_image_builder` get installed into a common directory, e.g.
|
||||
`/usr/share/uhd/rfnoc`. The directory structure underneath is identical to the
|
||||
directory structure in this example, e.g., `/usr/share/uhd/rfnoc/fpga/gain` will
|
||||
have the same content as `./fpga/gain`. This allows the image builder to work
|
||||
with the OOT module as an include directory.
|
||||
|
||||
Files that are required for the software component (e.g., everything under `include`,
|
||||
`lib`, `apps` and so on) are installed like any other software (e.g., include
|
||||
files may go to `/usr/include/rfnoc`, shared libraries might go to `/usr/lib`,
|
||||
and so on).
|
||||
|
||||
|
||||
|
||||
## Building FPGA bitfiles from this OOT module
|
||||
|
||||
Building a bitfile requires an image core file, and those are stored under the
|
||||
`icores` directory. The image core files are YAML files that define the contents
|
||||
of the RFNoC image, including the blocks that are part of the image.
|
||||
|
||||
Inside the `icores` directory is a CMakeLists.txt file, inside which bitfile
|
||||
targets can be defined using the `RFNOC_REGISTER_IMAGE_CORE()` macro. For example,
|
||||
if we register the image core file `x310_rfnoc_image_core.yml` in the CMakeLists.txt
|
||||
file, we can build the bitfile using the following command (assuming CMake was
|
||||
executed beforehand):
|
||||
|
||||
```sh
|
||||
cd /path/to/rfnoc-gain/build
|
||||
make x310_rfnoc_image_core
|
||||
```
|
||||
|
||||
Note that this will build the bitfile with source files from this directory. This
|
||||
workflow is therefore a sensible way to build bitfiles during development.
|
||||
|
||||
Using `make` is not a requirement, it is merely a convenience. You can also
|
||||
directly run `rfnoc_image_builder` and point it to the `rfnoc` subdirectory:
|
||||
|
||||
```sh
|
||||
cd /path/to/rfnoc-gain/
|
||||
rfnoc_image_builder -y ./icores/x310_rfnoc_image_core.yml -I ./rfnoc
|
||||
```
|
||||
|
||||
This has the same effect, but let's you control the precise arguments to the
|
||||
image builder.
|
||||
|
||||
However, the design of the out-of-tree module is such that it is also possible
|
||||
to install, and then build bitfiles using the installed files. This is of value
|
||||
when installing multiple OOT modules, and not planning to modify their source
|
||||
files.
|
||||
|
||||
For example, the following workflow is valid:
|
||||
|
||||
```sh
|
||||
cd /path/to/rfnoc-gain # Switch to this file's directory
|
||||
mkdir build && cd build && cmake .. -F /path/to/uhd/fpga/usrp3 # Configure the project
|
||||
# Now, launch an image build and use all files from this directory:
|
||||
rfnoc_image_builder -y ../icores/x310_rfnoc_image_core.yml -I ../rfnoc
|
||||
make install # Install software and gateware
|
||||
# Build again, without -I:
|
||||
rfnoc_image_builder -y ../icores/x310_rfnoc_image_core.yml
|
||||
```
|
||||
|
||||
In this workflow, we launch `rfnoc_image_builder` once with `-I` on the current
|
||||
directory, and once without. In the latter case, the image builder will only
|
||||
use files that were installed into the right location.
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
|
||||
# This subdir contains all the gateware
|
||||
add_subdirectory(fpga/gain)
|
||||
# Add one subdirectory for every type of RFNoC components you have YAML files
|
||||
# for (e.g., blocks, transport_adapters, modules, ...)
|
||||
add_subdirectory(blocks)
|
||||
|
||||
@ -25,6 +25,7 @@ from mako import exceptions
|
||||
from . import grc, yaml_utils
|
||||
from .builder_config import ImageBuilderConfig
|
||||
from .template import Template
|
||||
from .utils import check_include_paths_backward_compat
|
||||
|
||||
### DATA ######################################################################
|
||||
# Directory under the FPGA repo where the device directories are
|
||||
@ -337,8 +338,7 @@ def load_module_yamls(include_paths):
|
||||
def load_module_descs(module_type):
|
||||
"""Load separate block/module defs."""
|
||||
paths = [
|
||||
os.path.abspath(os.path.normpath(os.path.join(x, "rfnoc", module_type)))
|
||||
for x in include_paths
|
||||
os.path.abspath(os.path.normpath(os.path.join(x, module_type))) for x in include_paths
|
||||
]
|
||||
logging.debug("Looking for %s descriptors in:", module_type[:-1])
|
||||
for path in paths:
|
||||
@ -423,9 +423,9 @@ def build_image(repo_fpga_path, config_path, device, **args):
|
||||
"""
|
||||
# We start by loading some core/standard files that are always needed.
|
||||
core_config_path = yaml_utils.get_core_config_path(config_path)
|
||||
|
||||
# TODO does this work for both block yamls and HDL sources?
|
||||
include_paths = args.get("include_paths", []) + [config_path]
|
||||
include_paths = check_include_paths_backward_compat(args.get("include_paths", [])) + [
|
||||
os.path.join(config_path, "rfnoc")
|
||||
]
|
||||
logging.debug("Include paths: %s", ";".join(include_paths))
|
||||
# A list of all known module descriptors
|
||||
known_modules = load_module_yamls(include_paths)
|
||||
|
||||
@ -163,3 +163,41 @@ def find_include_file(filename, include_paths):
|
||||
return os.path.realpath(candidate)
|
||||
|
||||
raise FileNotFoundError(f"File {filename} not found in include paths: {include_paths}")
|
||||
|
||||
|
||||
def check_include_paths_backward_compat(include_paths):
|
||||
"""Check if the include paths are plausible or maybe following an old style.
|
||||
|
||||
In an older version of the image builder, the include paths for OOT builds
|
||||
pointed to the OOT modules itself (e.g., `-I ./rfnoc-gain`). However, the
|
||||
correct path should be the `rfnoc` subdir (e.g., `-I ./rfnoc-gain/rfnoc`).
|
||||
|
||||
To make people's lives not unnecessarily hard, we allow the old behavior.
|
||||
This requires a heuristic to figure out if the user actually meant to use
|
||||
include_path + 'rfnoc' or not. This is done by checking if the include path
|
||||
contains expected subdirs (e.g., `blocks`, `fpga`) or if the path contains
|
||||
subdirs that are not expected (e.g., `cmake`, `rfnoc`).
|
||||
"""
|
||||
|
||||
def path_is_probably_old_style(path):
|
||||
"""Return True if a path is missing an 'rfnoc' subdir."""
|
||||
expected_subdirs_new_style = ["blocks", "fpga", "transport_adapters", "modules"]
|
||||
expected_subdirs_old_style = ["cmake", "rfnoc"]
|
||||
if any(os.path.isdir(os.path.join(path, p)) for p in expected_subdirs_new_style):
|
||||
return False
|
||||
if all(os.path.isdir(os.path.join(path, p)) for p in expected_subdirs_old_style):
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_and_fix(path):
|
||||
if path_is_probably_old_style(path):
|
||||
new_path = os.path.join(path, "rfnoc")
|
||||
logging.info(
|
||||
"Include path %s is likely missing an 'rfnoc' subdir. Changing to: %s",
|
||||
path,
|
||||
new_path,
|
||||
)
|
||||
return os.path.join(path, "rfnoc")
|
||||
return path
|
||||
|
||||
return [check_and_fix(path) for path in include_paths]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user