project.yml Reference
Complete field reference for the RouteRTL SDK project configuration file.
Run
routertl init(orrr init) to generate a workingproject.ymlinteractively.
Quick Reference
| Section | Purpose |
|---|---|
project | Identity — name, top module, simulation top |
hardware | Target — vendor, FPGA part, HDL language |
linux | Embedded Linux overrides — board, custom repos, patches, and SW packages |
simulation | Simulation engine — test directory, waveforms, logs, backend |
paths | Directory layout — source, sim, constraints, verification |
build_options | Tool versions and synthesis tweaks |
features | Feature flags — regbank, etc. |
sources | Explicit file lists — syn, sim, xdc, sdc, ip, tcl |
dependencies | External git libraries — XPM, etc. |
hooks | Git hooks and pre-build code generation |
cicd | CI/CD pipeline generation |
vendor_overrides | Vendor-specific TCL variables |
makefile_overrides | Arbitrary Makefile variable injection |
system_config | Path to system YAML for sniffer/gather generation |
auto_sources | Automatic dependency resolution mode |
environment | Machine-specific env vars injected into .venv/bin/activate |
includes | Import other YAML fragments |
Sections
project
Project identity. Used for Vivado/Quartus project naming and simulation top selection.
project:
name: my_project # Project name (Vivado project, directory names)
top_module: my_top # Synthesis top-level entity/module
top_sim: tb_my_top # Simulation top-level (for VUnit, testgen)
path: project # Vivado .xpr project directory (default: project/)
| Field | Type | Default | Exported As |
|---|---|---|---|
name | string | system_top | PROJECT_NAME (Makefile), g_project_name (TCL) |
top_module | string | system_top | g_top_mod (TCL) |
top_sim | string | tb_system_top_sim | g_top_sim (TCL) |
path | string | project | PROJECT_DIR (Makefile), g_project_dir (TCL) |
pathbehavior: Controls where the Vivado/Quartus.xpr/.qpfproject is created. Build artifacts (dcp/,bitstream/,build/) remain at the project root — only the vendor project directory moves. Can also be set viamakefile_overrides.project_dir. Useful for multi-target setups where each target config uses a separate project directory.
hardware
FPGA target and HDL language selection.
hardware:
vendor: xilinx # xilinx, lattice, or altera
part: "xc7z020clg400-1" # Full part number (quoted for YAML safety)
family: artix7 # FPGA family (optional, for TCL hooks)
language: vhdl # vhdl, verilog, systemverilog, or mixed
platform: default # Board/platform identifier
tool_path: /opt/altera_std # Absolute path to vendor tool installation
| Field | Type | Default | Exported As |
|---|---|---|---|
vendor | string | xilinx | VENDOR (Makefile), used for build flow selection |
part | string | — | FPGA_PART (Makefile), g_fpga_part (TCL) |
family | string | "" | g_fpga_family (TCL) — e.g., "arria10", "zynq" |
language | enum | vhdl | HDL_LANGUAGE (Makefile) → derives HDL_EXT (.vhd or .sv) |
platform | string | default | PLATFORM (Makefile) |
tool_path | path | — | Not exported to build_env. Prepended to PATH at runtime by rr linting, rr bitstream, and pre-build hooks. |
tool_path behavior:
When set, the SDK probes the following subdirectories in order and prepends
the first match to PATH: quartus/bin, bin, bin/lin64, Libero/bin.
For Intel/Altera, QUARTUS_ROOTDIR is also set automatically.
This ensures vendor tools resolve correctly regardless of system PATH ordering.
Language behavior:
| Value | Stub Generated | Pre-Compilation | Notes |
|---|---|---|---|
vhdl | system_config_pkg.vhd | VHDL packages pre-compiled | Default |
verilog | system_config_pkg.sv | Skipped | Normalized to systemverilog internally |
systemverilog | system_config_pkg.sv | Skipped | Native SV path |
mixed | Both .vhd + .sv stubs | VHDL packages pre-compiled | Requires commercial simulator (Riviera-PRO, Questa, or Xcelium) |
simulation
Simulation engine configuration.
simulation:
test_dir: sim/cocotb/tests # Test discovery directory
simulator: nvc # Simulator backend
generics: # VHDL generics / Verilog parameters
G_DATA_WIDTH: 32
G_FIFO_DEPTH: 8
# Waveform output control
waves:
enabled: true # Generate waveforms (default: true)
formats: [fst] # Formats to produce: fst, vcd, ghw
output_dir: sim/waves # Output directory (relative to root)
# Log output control (NEW)
logs:
output_dir: sim/logs # Output directory (relative to root)
| Field | Type | Default | Exported As |
|---|---|---|---|
test_dir | path | sim/cocotb/tests | SIM_DIR (Makefile) |
simulator | string | nvc | SIM_BACKEND (Makefile) |
simulation.waves
Controls waveform generation format and output location.
| Field | Type | Default | Notes |
|---|---|---|---|
enabled | bool | true | Set false to skip waveform generation entirely |
formats | list of strings | ["fst"] | Formats to produce. Each backend only emits formats it supports (see table) |
output_dir | path | sim/waves | Output directory (relative to project root) |
Supported formats per simulator:
| Backend | Supported Formats | Notes |
|---|---|---|
| NVC | fst, vcd | Default: fst |
| GHDL | ghw, fst, vcd | Previously always produced all three |
| Verilator | vcd, fst | FST requires --trace-fst (auto-injected) |
| Icarus | vcd | Auto-injects `timescale 1ns/1ps if absent |
| Questa | wlf | Native format only |
| Riviera | asdb | Native format only |
Unsupported formats are silently skipped.
Precedence chain: run_simulation() kwarg > project.yml > env var (ROUTERTL_WAVES_DIR) > engine default.
simulation.logs
| Field | Type | Default | Notes |
|---|---|---|---|
output_dir | path | sim/logs | Override via env: ROUTERTL_LOGS_DIR |
The
simulatorfield determines which HDL compiler Cocotb uses. Usenvcfor Cocotb 2.0+ (required). GHDL is incompatible with Cocotb 2.0+.Legacy flat fields:
simulation.waves_dirandsimulation.logs_dir(strings) are accepted as flat aliases forsimulation.waves.output_dirandsimulation.logs.output_dirrespectively. They are exported asSIM_WAVES_DIRandSIM_LOGS_DIRinbuild_env.mk. Prefer the nested form in new projects.
simulation.tags
Named test groups for batch execution via routertl sim --tag <name>.
simulation:
tags:
smoke: [test_edge_counter, test_lfsr]
uart: [test_uart_sniffer, test_uart_master]
full: [test_edge_counter, test_lfsr, test_uart_sniffer, test_uart_master]
| Field | Type | Default | Used By |
|---|---|---|---|
tags | dict[string, list] | {} | routertl sim --tag <name> |
Each tag maps a name to a list of test module names. When invoked with
routertl sim --tag smoke, each test in the list is run sequentially and
a pass/fail summary is printed at the end.
simulation.generics
Override VHDL generics or Verilog/SystemVerilog parameters at simulation time. Works with all simulator backends.
simulation:
generics:
G_DATA_WIDTH: 32
G_FIFO_DEPTH: 8
DEFAULT_BUSY_HIGH: 1
| Field | Type | Default | Notes |
|---|---|---|---|
generics | dict[string, any] | {} | Passed to all simulator backends via -g flags or parameters= |
Values declared here are merged with any generics defined in the Python
test file's run_simulation() call. The Python kwarg takes precedence
over project.yml values — this allows project-wide defaults with
per-test overrides.
Precedence chain: project.yml < run_simulation() kwarg < CLI -g flag / $RR_SIM_GENERICS env var.
CLI override (highest priority):
rr sim test_cdc_bridge -g DEFAULT_BUSY_HIGH=1 rr sim test_fifo -g G_DATA_WIDTH=64 -g G_FIFO_DEPTH=16
Use
simulation.genericsfor project-wide defaults (bus widths, clock frequencies, feature enables). Use-gon the CLI for quick variant testing without editing files.
linux
Embedded Linux build configuration. Controls U-Boot, Kernel, FSBL, and external user-space software fetch operations.
linux:
board: zynq-zybo-z7 # Base board config for Xilinx makefiles
device_tree: zynq-zybo-z7 # Explit injection for U-Boot device tree
uboot_repo: https://github.com/my-fork/u-boot-xlnx.git # Override Xilinx upstream
kernel_repo: https://github.com/my-fork/linux-xlnx.git # Override Xilinx upstream
fsbl_repo: https://github.com/my-fork/embeddedsw.git # Override Xilinx upstream
kernel_config: config/kernel.cfg # Config fragments to merge before build
kernel_patch: config/patch.sh # Bash script to execute before kernel config
sw_repos: # Space-separated list of custom UI/App repos
- https://github.com/my-org/custom-ui.git
- https://github.com/my-org/video-server.git
| Field | Type | Default | Exported As | Effect |
|---|---|---|---|---|
board | string | — | LINUX_BOARD, BOARD | Passed downstream to FSBL and Buildroot/PetaLinux Makefile flows. |
device_tree | string | — | DEVICE_TREE | Injected into the U-Boot compilation sequence if set. |
uboot_repo | url string | Xilinx Upstream | UBOOT_REPO | Alters the git clone target for make build-uboot. |
kernel_repo | url string | Xilinx Upstream | KERNEL_REPO | Alters the git clone target for make build-kernel. |
fsbl_repo | url string | Xilinx Upstream | FSBL_REPO | Alters the git clone target for make build-fsbl. |
kernel_config | path | — | KERNEL_CONFIG_FRAGMENTS | Merged using scripts/kconfig/merge_config.sh before Kernel compile. |
kernel_patch | path | — | KERNEL_PATCH_SCRIPT | Executed dynamically inside the Kernel tree before olddefconfig. |
sw_repos | list | [] | SW_REPOS | Cloned automatically into linux/src/ by fetch_sw_repos.sh. |
paths
Directory layout overrides. All paths are relative to the project root.
These fields control where rr ws update scans for files;
they do not control which files are used for synthesis (that is sources.syn).
paths:
sources: src # Single directory
sources: [hw/rtl, vendor/routertl/src/units] # Multiple directories
simulation: sim
constraints: xdc
verification: verif
| Field | Type | Default | Exported As |
|---|---|---|---|
sources | string or list | src | SRC_DIR (Makefile) — used by rr ws update --src for scanning |
simulation | string | sim | SIM_PATH (Makefile) — used by rr ws update --sim for scanning |
constraints | string | xdc | XDC_DIR (Makefile) — used by rr ws update --xdc for scanning |
verification | string | verif | VERIFICATION_DIR (Makefile) |
Scan behavior (rr ws update / make update-src):
| Path Field | Scanned Recursively | Extensions Matched | Prefix Filter |
|---|---|---|---|
sources | Yes (os.walk) | *.vhd, *.v, *.sv | None |
simulation | Yes (os.walk) | *.vhd, *.v, *.sv | tb_* only |
constraints | Yes (os.walk) | Vendor-aware (see table below) | None |
When sources is a list, all directories are scanned and results are
unioned — files from each directory are deduplicated against existing
sources.syn entries before insertion.
paths.simulation≠simulation.test_dir.paths.simulationscans for RTL testbench wrappers (tb_*.vhd,tb_*.v,tb_*.sv) and populatessources.sim.simulation.test_diris the directory for Python Cocotb test scripts (test_*.py), used byrr simandhooks.pre_commit.tests: auto. These are different file types serving different purposes.
build_options
Synthesis tool versions and build behavior.
build_options:
tool_version: "2024.1" # Default version for all tools
vivado_version: "2024.2" # Override Vivado specifically
radiant_version: "2023.2" # Override Lattice Radiant
quartus_version: "23.1" # Override Intel Quartus
quick_impl: true # Fast implementation (fewer timing iterations)
edition: pro # Quartus edition override (pro/std)
| Field | Type | Default | Exported As |
|---|---|---|---|
tool_version | string | 2024.1 | VIVADO_VER, RADIANT_VER, QUARTUS_VER (all ?=) |
vivado_version | string | — | VIVADO_VER := (hard override) |
radiant_version | string | — | RADIANT_VER := (hard override) |
quartus_version | string | — | QUARTUS_VER := (hard override) |
quick_impl | bool | — | QUICK_IMPL (Makefile) |
edition | string | "" | g_quartus_edition (TCL) — enables TCL-side branching between Pro and Standard editions |
build_options.generics
Override top-level VHDL generics or SystemVerilog parameters at synthesis time.
Applies to the entity/module defined by project.top_module.
build_options:
generics:
DATA_WIDTH: 32
FIFO_DEPTH: 1024
ENABLE_DEBUG: false
| Property | Detail |
|---|---|
| Type | dict — flat name: value map |
| Scope | Top-level entity only (all vendor tools enforce this) |
| Exported as | g_generics TCL dict in build_env.tcl |
| Supported values | Integer, boolean. String overrides are not supported by Vivado synth_design -generic. |
Vendor-specific behaviour:
| Vendor | TCL mechanism | Notes |
|---|---|---|
| Xilinx (Vivado) | synth_design -generic NAME=VALUE (NPM) / set_property generic (project mode) | Works for both VHDL generics and SV parameters. VHDL booleans use 1'b0/1'b1 in mixed-language designs. |
| Intel (Quartus) | set_parameter -name NAME VALUE | Top-level only. Works for both VHDL generics and SV parameters. |
| Lattice (Radiant) | prj_set_strategy_value syn_cmdline_args → Synplify set_option -hdl_param | Generics injected into Synplify via strategy options. Language-agnostic. |
| Microchip (Libero) | configure_tool -name {SYNTHESIZE} with Synplify options | Generics passed via Synplify options. Language-agnostic. Not yet verified — use tcl_hooks.synthesis as fallback. |
Version precedence:
tool_version sets ?= (weak) defaults for all three tools. A vendor-specific
override like vivado_version emits := (unconditional), which takes priority.
Tool auto-discovery:
On native Linux, the SDK auto-discovers synthesis tools from PATH via check_env.py:
| Vendor | Tool | Env Flag | Auto-Discovery |
|---|---|---|---|
xilinx | vivado | SDK_HAS_VIVADO | VIVADO_PATH derived from which vivado |
altera | quartus_sh | SDK_HAS_QUARTUS_SH | QUARTUS_ROOT derived from which quartus_sh |
lattice | radiantc | — | Fallback to default path |
If the required tool is not found, make synthesis will fail with a clear error and instructions.
The tool_version / vivado_version fields select among multiple installed versions.
Users can override tool paths explicitly:
makefile_overrides:
VIVADO_PATH: /opt/Xilinx/Vivado/2024.2
features
Feature flags that enable or disable SDK capabilities.
features:
regbank: true # Enable register bank generation
| Field | Type | Default | Exported As |
|---|---|---|---|
regbank | bool | true | CONFIG_ENABLE_REGBANK (Makefile) — gates make synthesis regbank step |
When regbank: true, make synthesis automatically runs parse_regbank and rom_info
before project generation. Set to false for projects without a register bank.
sources
Explicit file lists for synthesis, simulation, constraints, and IP. These are the files tracked by the build system.
An empty list (
sources.syn: []) means zero synthesis files — there is no implicit auto-discovery frompaths.sources. Auto-discovery only happens whenauto_sources: trueis set.
sources:
syn:
- hw/rtl/pkg/system_config_pkg.vhd
- hw/rtl/sniffer/uart/uart_sniffer.vhd
sim:
- hw/sim/tb_uart_sniffer.vhd
xdc:
- xdc/system_timing.xdc
- xdc/system_pinout.xdc
sdc:
- constraints/timing.sdc
ip:
- ip/axi_dma/axi_dma.xci
ips:
- ip/uart_core/ip.yml
ip_paths:
- ip/vendor_ips
- ~/vivado_ip_repo
tcl: []
| Key | Exported As | Used By |
|---|---|---|
syn | SYN_FILES | Synthesis, linting, dependency resolution |
sim | SIM_FILES | Simulation source file list |
xdc | XDC_FILES | Xilinx constraint files |
sdc | SDC_FILES | Intel/Lattice constraint files |
ip | IP_FILES, XCI_FILES | Xilinx IP core files |
ips | SYN_FILES, XCI_FILES, NETLIST_FILES, OOC_DCP_FILES | IP manifests (ip.yml reference) |
ip_paths | g_user_ip_paths (TCL) | Directories scanned for IP-XACT component.xml — added to Vivado ip_repo_paths |
tcl | TCL_FILES | Auxiliary TCL scripts |
Auto-derived variables:
PKG_FILES— Auto-detected fromsynentries. Any.vhd/.vhdlfile containingpackage <name> isis classified as a package and pre-compiled before linting.
Populating source lists:
make update-src # Scan paths.sources for *.vhd, *.vhdl, *.v, *.sv
make update-sim # Scan paths.simulation for tb_*.vhd, tb_*.v, tb_*.sv
make update-dc # Scan paths.constraints for vendor-specific design constraints
make update-tcl # Scan tcl/ for *.tcl
make update-ips # Scan RTL-mode ip.yml manifests and update their sources
make update-all # Run all five scans (includes --ip-update)
Vendor-aware constraint scan (make update-dc):
| Vendor | Scanned Extensions |
|---|---|
xilinx | .xdc, .pcf |
altera | .sdc, .pcf |
lattice | .lpf, .sdc, .pcf |
make update-xdcis a backward-compatible alias formake update-dc.
Stale entry pruning:
Each make update-* command prunes stale entries (files that no longer exist on disk)
from the sources and hooks.pre_commit.exclude.lint sections automatically.
sources.libraries (Legacy Override)
Since v3.1, library membership is fully automatic via the dependency resolver's
--discover-libsscan. The section below documents the manual override mechanism for edge cases only.
Custom VHDL library assignments. Files listed here are compiled under a
named GHDL library (--work=<lib>) instead of the default work library.
sources:
libraries:
tich:
- hw/rtl/pkg/arbiter_pkg.vhd
- hw/rtl/pkg/axi_pkg.vhd
- hw/rtl/pkg/system_config_pkg.vhd
- hw/rtl/sniffer/infra/config_control.vhd
| Field | Type | Default | Used By |
|---|---|---|---|
libraries.<name> | list of paths | {} | Smart Linter Phase 1.5 (COMPILE_LIB) |
Behavior:
- Serialized to
.routertl_cache/libraries.jsonbyproject_manager.py. - Files are excluded from generic PRECOMPILE (Phase 1) to avoid
cannot find resource libraryerrors. - Each library is compiled into its own GHDL work directory
(
sim/work/<lib_name>/) with correct topological ordering. -P sim/work/<lib_name>is added to LINT search paths automatically.
You almost certainly do not need this section. The Smart Linter auto-discovers library memberships via
--discover-libs(scans forentity lib.Xinstantiations anduse lib.pkg.allclauses). Manual entries here act as overrides for edge cases — e.g. generated files not in the source scan path. Auto-discovered and manual entries are merged (union). See LINTER_PIPELINE.md §4 for the full data flow.
dependencies
External git libraries. Cloned automatically on first build.
dependencies:
xpm_vhdl: # Logical name (your choice)
url: https://github.com/fransschreuder/xpm_vhdl.git
fallback_url: https://github.com/djmazure/xpm_vhdl.git
path: libs/xpm_vhdl # Clone destination (relative to root)
library: xpm # VHDL library name
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | Primary git clone URL |
fallback_url | string | no | Fallback URL if primary fails |
path | string | yes | Local clone directory |
library | string | no | VHDL library name — if xpm, files exported as XPM_FILES |
Behavior:
- On
make update-config, the SDK checks ifpathexists. - If missing, it clones from
url(thenfallback_urlon failure). - VHDL files inside the cloned repo are scanned, topologically sorted,
and exported as
XPM_FILESfor thelibrary: xpmcase.
hooks
Git hooks and code generation hooks.
hooks.pre_commit
Pre-commit hook configuration. Install with make install-hooks.
hooks:
pre_commit:
enabled: true # Master switch for the hook
lint: true # Run smart linter
check_yaml: true # Validate project.yml syntax
lint_python: false # Run ruff check (requires pyproject.toml)
check_links: false # Run documentation link checker
check_docs: false # Run documentation structure checker
run_regression: false # Run full regression (slow!)
# Auto-discover all test_*.py in simulation.test_dir:
tests: auto
# Or use an explicit list:
# tests:
# - test_uart_sniffer_smoke
# - test_uart_precommit
exclude: # Exclusion lists
lint:
- vendor/legacy/old_file.vhd
tests:
- test_slow_integration
docs: # Doc directories excluded from check_links
- vendor/
frozen_dirs: # Directories that must not have uncommitted changes
- hw/rtl/generated
| Field | Type | Default | Exported As |
|---|---|---|---|
enabled | bool | true | HOOK_ENABLED (shell) |
lint | bool | false | HOOK_LINT (shell) |
check_yaml | bool | false | HOOK_CHECK_YAML (shell) |
lint_python | bool | false | HOOK_LINT_PYTHON (shell) |
check_links | bool | false | HOOK_CHECK_LINKS (shell) |
check_docs | bool | false | HOOK_CHECK_DOCS (shell) |
run_regression | bool | false | HOOK_RUN_REGRESSION (shell) |
tests | "auto", "inherit", or list | [] | HOOK_TESTS (shell, space-separated) |
exclude.lint | list of paths | [] | HOOK_EXCLUDE_LINT (shell) |
exclude.tests | list of strings | [] | HOOK_EXCLUDE_TESTS (shell) |
exclude.docs | list of paths | [] | HOOK_EXCLUDE_DOC_DIRS (shell) |
frozen_dirs | list of paths | [] | HOOK_FROZEN_DIRS (shell) — pre-commit rejects changes touching these dirs |
Test modes:
tests: auto— Discovers alltest_*.pyfiles undersimulation.test_dirvia recursive glob (rglob("test_*.py")). Only git-tracked files are included (prevents WIP scripts from leaking into the hook).exclude.testsis applied before emitting. Each file is converted to a dotted module path (e.g.,sim/cocotb/tests/units/test_edge.py→tests.units.test_edge).tests: [list]— Explicit module list.exclude.testsis applied by the hook script at runtime.tests: inherit— Inherits the test list fromcicd.tests. Use this when CI/CD is the source of truth.
When both
hooks.pre_commit.testsandcicd.testsare explicit lists with different contents, the SDK emits a divergence warning suggesting the use ofinheritto stay DRY.
Test naming rules:
- Tests are module names, not file paths:
test_uart_sniffer, nothw/sim/.../test_uart_sniffer.py - Dotted notation for namespaced tests:
tests.units.test_edge_counter
hooks.pre_build
Code generation hooks that run before make project / make synthesis.
hooks:
pre_build:
- name: sniffer-builder # Human-readable label
script: tools/sniffer-builder/sniffer_gather_gen.py # Script path
args: # Arguments
- tools/sniffer-builder/config/sniffer_config.yml
- --pkg-dir
- hw/rtl/pkg
expected_outputs: # Files that must exist after run
- hw/rtl/pkg/sniffer_config_pkg.vhd
- hw/rtl/sniffer/infra/sniffer_gather.vhd
watch: # Source globs — re-run if newer than outputs
- tools/sniffer-builder/**/*.py
- tools/sniffer-builder/config/*.yml
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | no | — | Display name for logging |
script | string | yes | — | Python script path (relative to root) |
args | list | no | [] | Command-line arguments |
expected_outputs | list | no | [] | Files validated after execution; auto-synced to .gitignore (see below) |
watch | list | no | [] | Source file globs — if all watched files are older than outputs, hook is skipped. Prevents stale firmware baked into bitstreams. |
clean_before_run | bool | no | true | Delete parent dirs of expected_outputs before hook execution — prevents stale generated files from persisting |
Auto-gitignore behavior:
rr ws update-config automatically syncs all expected_outputs entries into
.gitignore using an idempotent sentinel block. This prevents generated files
from being committed. If hooks are removed or outputs change, the sentinel
block is replaced (not duplicated). Paths containing .. or starting with /
are silently skipped for safety. See SDK_BEHAVIOR_CONTRACT.md §1.4.
clean_before_run behavior:
When true (default), the parent directory of each expected_output
is deleted before the hook runs — not just the file itself. This ensures no
stale artifacts survive from a previous code generation. Safety:
the project root itself is never deleted, and paths outside the project root
are skipped with a warning.
cicd
CI/CD pipeline configuration. Used by make update-cicd.
cicd:
platform: github # github, gitlab, or bitbucket
tests:
- tests.units.test_edge_counter
- tests.units.test_lfsr
| Field | Type | Default | Effect |
|---|---|---|---|
platform | enum | bitbucket | Generates .github/workflows/main.yml, .gitlab-ci.yml, or bitbucket-pipelines.yml |
tests | "inherit" or list of strings | [] | Injected as make sim MODULE=<test> commands |
Test list inheritance:
tests: inherit— Inherits the test list fromhooks.pre_commit.tests. This is the recommended DRY pattern.tests: [list]— Explicit module list for CI.
Declare tests once in
hooks.pre_commit.testsand setcicd.tests: inherit(or vice versa) to avoid duplicate lists drifting apart. A warning is emitted when both sections have explicit, differing lists.
vendor_overrides
Vendor-specific variables injected into the TCL environment.
vendor_overrides:
xilinx:
enable_pblocks: true # Exported as: set g_enable_pblocks true
lattice:
synthesis_tool: lse # Exported as: set g_synthesis_tool "lse"
Each key-value pair becomes a TCL variable: set g_<key> <value>.
makefile_overrides
Arbitrary Makefile variables injected into build_env.mk.
makefile_overrides:
CUSTOM_FLAG: fast
PARALLEL_JOBS: 4
USE_OOC: true # Booleans lowercase automatically
VIVADO_PATH: /opt/Xilinx/Vivado/2024.2 # Custom tool path
Each entry becomes a := assignment in build_env.mk:
CUSTOM_FLAG := fast PARALLEL_JOBS := 4 USE_OOC := true VIVADO_PATH := /opt/Xilinx/Vivado/2024.2
system_config
Path to a system-level YAML configuration (e.g., for sniffer/gather generation).
system_config: tools/sniffer-builder/config/sniffer_config.yml
Exported as CONFIG_YAML ?= $(ROOT_DIR)/<path> in build_env.mk.
auto_sources
Enable automatic dependency resolution from the top module.
auto_sources: true
| Field | Type | Default | Effect |
|---|---|---|---|
auto_sources | bool | false | When true, runs DependencyResolver from project.top_module |
Behavior:
- The resolver crawls from
project.top_moduleusing theDependencyResolver. - Resolved files are appended to
sources.syn— they do not replace existing entries. Duplicates are skipped. - Results are cached in
.routertl_cache/dependencies.json, keyed bytop_module. Subsequent runs reuse the cache (no timestamp invalidation). - If
sources.syndoes not exist, it is created as an empty list first.
This is an advanced feature. For most projects, explicit source lists populated via
rr ws update --srcare simpler and more predictable.The auto-sources resolver uses
paths.sourcesfor its search directories. Ifpaths.sourcesis not set, it falls back tosrc/.
linux
Embedded Linux build configuration. All keys are optional — they are only relevant
for SoC projects that target routertl linux build.
linux:
board: zybo # Board identifier
target: zynq-7000 # CPU target (from supported_targets.yml)
device_tree: zynq-zybo.dtb # Device tree filename
uboot_repo: https://... # Custom U-Boot repository
kernel_repo: https://... # Custom Linux Kernel repository
fsbl_repo: https://... # Custom embeddedsw fork (for FSBL)
dtg_repo: https://... # Custom Device Tree Generator fork
boot_script: linux/boot.txt # U-Boot boot script source (triggers boot.scr generation)
kernel_config: linux/kernel.cfg # Kernel config fragment
kernel_patch: linux/patch.sh # Kernel patch script
sw_repos: # Additional software repositories to clone
- https://github.com/org/repo.git
| Field | Type | Exported As | Notes |
|---|---|---|---|
board | string | LINUX_BOARD | Passed to U-Boot defconfig selection |
target | string | LINUX_TARGET | Selects ARCH, CROSS_COMPILE from supported_targets.yml |
device_tree | string | DEVICE_TREE | Override for device tree filename |
uboot_repo | string | UBOOT_REPO | Git URL for U-Boot sources |
kernel_repo | string | KERNEL_REPO | Git URL for Linux Kernel sources |
fsbl_repo | string | FSBL_REPO | Git URL for embeddedsw fork |
dtg_repo | string | DTG_REPO | Git URL for Device Tree Generator |
boot_script | string | BOOT_SCRIPT | Path to boot.txt (relative to project root). When set, build-bootscr compiles it to boot.scr via mkimage. Warns if the declared file is missing. |
kernel_config | string | KERNEL_CONFIG_FRAGMENTS | Kconfig fragment file |
kernel_patch | string | KERNEL_PATCH_SCRIPT | Post-clone patch script |
sw_repos | list | SW_REPOS | Space-separated list of Git URLs |
environment
Machine-specific environment variables injected into .venv/bin/activate.
Keeps per-machine paths (license files, tool roots) out of shell profiles.
environment:
LM_LICENSE_FILE: ~/Downloads/LR-291374_License.dat
QUARTUS_ROOTDIR: /opt/altera_std
| Field | Type | Effect |
|---|---|---|
<KEY> | string | Appended as export <KEY>="<value>" inside a sentinel block |
Behavior:
rr ws install,rr ws update-config, andrr ws repair-venvall call the injection helper.- Variables are written inside a sentinel block in
.venv/bin/activate:# --- RouteRTL project environment --- export LM_LICENSE_FILE="$HOME/Downloads/LR-291374_License.dat" export QUARTUS_ROOTDIR="/opt/altera_std" # --- end RouteRTL project environment --- - The sentinel block is idempotent — repeated runs replace the existing block, never duplicate it.
~in values is expanded to$HOMEfor portability.- Removing the
environment:key fromproject.ymlcleans the sentinel block from.venv/bin/activateon the nextupdate-config.
includes
Import other YAML fragments. Allows splitting configuration across files.
includes:
- config/hardware.yml
- config/sources.yml
Merge semantics:
| Type | Rule | Example |
|---|---|---|
| Lists | Appended (duplicates skipped) | syn: [a.vhd] + syn: [b.vhd] → syn: [a.vhd, b.vhd] |
| Dicts | Recursively merged | Nested keys from both files are combined |
| Scalars | Last writer wins | Parent file's value overrides included file's value |
Processing order:
- Includes are loaded depth-first (recursive).
- All included configs are merged into a combined dict first.
- The parent file's own config is then merged on top, giving it final say.
Safety:
- Cycle detection: Tracks visited absolute paths; circular includes are skipped with a warning.
- Max depth: 10 levels (hardcoded). Exceeding this emits a warning and stops recursion.
- Missing file: Prints a warning and returns an empty dict (non-fatal).
- Invalid YAML: Prints a parse error and returns an empty dict.
- Both absolute and relative paths are supported. Relative paths are resolved relative to the including file's directory.
tcl_hooks
Custom TCL scripts sourced during FPGA build stages.
tcl_hooks:
gen_project: # Sourced during project generation
- tcl/custom/my_block_design.tcl
- tcl/custom/my_ip_config.tcl
synthesis: # Sourced after project_open, before synthesis
- tcl/project_options.tcl
implementation: # Sourced after project_open, before fitter
- tcl/project_options.tcl
- tcl/impl_settings.tcl
bitstream: # Sourced after project_open, before assembler
- tcl/project_options.tcl
| Key | Exported As | When Sourced |
|---|---|---|
gen_project | g_gen_project_hooks | During gen_project.tcl execution |
synthesis | g_synthesis_hooks | After project_open in gen_synthesis.tcl |
implementation | g_implementation_hooks | After project_open in gen_implementation.tcl |
bitstream | g_bitstream_hooks | After project_open in gen_bitstream.tcl |
Each hook list is exported as a TCL list variable in build_env.tcl.
The stage scripts iterate over the list after project_open and source each
file. Missing files emit a warning but do not abort the build.
Use per-stage hooks to re-apply
project_options.tclsettings that may be lost from stale QSF files (e.g., after a Quartus GUI session). This prevents fitter OOM crashes caused byOPTIMIZATION_MODEreverting to defaults on large devices (Arria 10, Stratix 10).
branding
White-label the CLI with custom names. Affects binary alias, help text, version output, and shell completion.
branding:
cli_name: myrtl # Binary alias (symlinked in .venv/bin/)
display_name: My RTL SDK # Shown in --help and --version panels
| Field | Type | Default | Effect |
|---|---|---|---|
cli_name | string | routertl | Creates .venv/bin/<cli_name> → routertl symlink; used as prog_name for Click |
display_name | string | RouteRTL SDK | Shown in --version, --help panels, and dynamic CLI docstring |
Symlink behavior:
- Created by
rr initduring venv setup (_create_branded_symlink()). - Existing symlinks are replaced silently.
- No-op if
cli_nameisroutertl(the default) or unset. - The symlink is relative within
.venv/bin/for portability.
The
rrshortcut alias is always created regardless of branding. Bothrrand the branded name point to the sameroutertlentry point.
Full Example
# RouteRTL Project Configuration
project:
name: my_soc_project
top_module: my_soc_top
top_sim: tb_my_soc_top
hardware:
vendor: xilinx
part: "xc7z020clg400-1"
family: zynq
language: vhdl
platform: default
tool_path: /opt/Xilinx/Vivado
linux:
board: zybo
sw_repos:
- https://github.com/my-org/my-app.git
simulation:
test_dir: hw/sim/cocotb/tests
simulator: nvc
waves:
formats: [fst]
output_dir: hw/sim/waves
logs:
output_dir: hw/sim/logs
paths:
sources: [hw/rtl, vendor/routertl/src/units]
simulation: hw/sim
constraints: hw/xdc
verification: hw/verif
build_options:
tool_version: "2024.1"
edition: pro
features:
regbank: true
branding:
cli_name: myrtl
display_name: My RTL SDK
sources:
syn:
- hw/rtl/pkg/system_config_pkg.vhd
- hw/rtl/sniffer/uart/uart_sniffer.vhd
sim: []
xdc: []
environment:
LM_LICENSE_FILE: ~/Downloads/LR-291374_License.dat
QUARTUS_ROOTDIR: /opt/altera_std
dependencies:
xpm_vhdl:
url: https://github.com/fransschreuder/xpm_vhdl.git
fallback_url: https://github.com/djmazure/xpm_vhdl.git
path: libs/xpm_vhdl
library: xpm
hooks:
pre_commit:
enabled: true
lint: true
check_yaml: true
lint_python: false
check_links: false
tests:
- test_uart_sniffer_smoke
- test_uart_precommit
exclude:
lint:
- hw/rtl/sniffer/infra/sniffer_gather.vhd
tests: []
frozen_dirs:
- hw/rtl/generated
pre_build:
- name: sniffer-builder
script: tools/sniffer-builder/sniffer_gather_gen.py
args:
- tools/sniffer-builder/config/sniffer_config.yml
- --pkg-dir
- hw/rtl/pkg
expected_outputs:
- hw/rtl/pkg/sniffer_config_pkg.vhd
cicd:
platform: github
tests:
- tests.units.test_edge_counter
- tests.units.test_lfsr