From e0eeb3e221a3ec5288551600c3ddacccb425b512 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 5 Feb 2026 17:46:20 +0100 Subject: [PATCH 01/47] Copy README contents to initial book --- book/.gitignore | 1 + book/book.toml | 4 + book/src/SUMMARY.md | 12 + book/src/commands.md | 197 +++++++++++++++ book/src/configuration_format.md | 58 +++++ book/src/installation.md | 19 ++ book/src/manifest_format.md | 301 +++++++++++++++++++++++ book/src/manifest_format.md#dependencies | 1 + book/src/manifest_format.md#sources | 1 + book/src/manifest_format.md#targets | 1 + book/src/package_structure.md | 11 + book/src/principles.md | 20 ++ book/src/workflow.md | 7 + 13 files changed, 633 insertions(+) create mode 100644 book/.gitignore create mode 100644 book/book.toml create mode 100644 book/src/SUMMARY.md create mode 100644 book/src/commands.md create mode 100644 book/src/configuration_format.md create mode 100644 book/src/installation.md create mode 100644 book/src/manifest_format.md create mode 100644 book/src/manifest_format.md#dependencies create mode 100644 book/src/manifest_format.md#sources create mode 100644 book/src/manifest_format.md#targets create mode 100644 book/src/package_structure.md create mode 100644 book/src/principles.md create mode 100644 book/src/workflow.md diff --git a/book/.gitignore b/book/.gitignore new file mode 100644 index 00000000..e9c07289 --- /dev/null +++ b/book/.gitignore @@ -0,0 +1 @@ +book \ No newline at end of file diff --git a/book/book.toml b/book/book.toml new file mode 100644 index 00000000..b280d272 --- /dev/null +++ b/book/book.toml @@ -0,0 +1,4 @@ +[book] +title = "bender" +authors = ["Michael Rogenmoser", "Tim Fischer", "Fabian Schuiki", "Andreas Kurth"] +language = "en" diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md new file mode 100644 index 00000000..b4bf215e --- /dev/null +++ b/book/src/SUMMARY.md @@ -0,0 +1,12 @@ +# Summary + +- [Principles](./principles.md) +- [Installation](./installation.md) +- [Workflow](./workflow.md) +- [Package Structure](./package_structure.md) +- [Manifest Format (`Bender.yml`)](./manifest_format.md) + +- [Configuration Format (`bender.yml`, `Bender.local`)](./configuration_format.md) +- [Commands](./commands.md) diff --git a/book/src/commands.md b/book/src/commands.md new file mode 100644 index 00000000..24bec9da --- /dev/null +++ b/book/src/commands.md @@ -0,0 +1,197 @@ +# Commands + +`bender` is the entry point to the dependency management system. Bender always operates within a package; starting at the current working directory, search upwards the file hierarchy until a `Bender.yml` is found, which marks the package. + + +## `path` --- Get the path of a checked-out package + +The `bender path ` prints the path of the checked-out version of package `PKG`. + +Useful in scripts: + + #!/bin/bash + cat `bender path mydep`/src/hello.txt + + +## `packages` --- Display the dependency graph + +- `bender packages`: List the package dependencies. The list is sorted and grouped according to a topological sorting of the dependencies. That is, leaf dependencies are compiled first, then dependent ones. +- `bender packages -f`: Produces the same list, but flattened. +- `bender packages -g`: Produces a graph description of the dependencies of the form `TAB`. + + +## `sources` --- List source files +[Code](https://github.com/pulp-platform/bender/blob/master/src/cmd/sources.rs) + +Produces a *sources manifest*, a JSON description of all files needed to build the project. + +The manifest is recursive by default; meaning that dependencies and groups are nested. Use the `-f`/`--flatten` switch to produce a simple flat listing. + +To enable specific targets, use the `-t`/`--target` option. Adding a package and colon `:` before a target will apply the target only to that specific package. Prefixing a target with `-` will remove that specific target, even for predefined targets (e.g., `-t-` or `-t :-`). + +To get the sources for a subset of packages, exclude specific packages and their dependencies, or exclude all dependencies, the following flags exist: + +- `-p`/`--package`: Specify package to show sources for. +- `-e`/`--exclude`: Specify package to exclude from sources. +- `-n`/`--no-deps`: Exclude all dependencies, i.e. only top level or specified package(s). + +For multiple packages (or excludes), multiple `-p` (or `-e`) arguments can be added to the command. + + +## `config` --- Emit the current configuration + +The `bender config` command prints the currently active configuration as JSON to standard output. + + +## `script` --- Generate tool-specific scripts + +The `bender script ` command can generate scripts to feed the source code of a package and its dependencies into a vendor tool. These scripts are rendered using internally stored templates with the [tera](https://keats.github.io/tera/docs/) crate, but custom templates can also be used. + +Supported formats: + +- `flist`: A flat whitespace-separated file list. +- `flist-plus`: A flat file list amenable to be directly inlined into the invocation command of a tool, e.g. `verilate $(bender script flist)`. +- `vsim`: A Tcl compilation script for Mentor ModelSim/QuestaSim. +- `vcs`: A Tcl compilation script for VCS. +- `verilator`: Command line arguments for Verilator. +- `synopsys`: A Tcl compilation script for Synopsys DC and DE. +- `formality`: A Tcl compilation script for Formality (as reference design). +- `riviera`: A Tcl compilation script for Aldec Riviera-PRO. +- `genus`: A Tcl compilation script for Cadence Genus. +- `vivado`: A Tcl file addition script for Xilinx Vivado. +- `vivado-sim`: Same as `vivado`, but specifically for simulation targets. +- `precision`: A Tcl compilation script for Mentor Precision. +- `template`: A custom [tera](https://keats.github.io/tera/docs/) template, provided using the `--template` flag. +- `template_json`: The json struct used to render the [tera](https://keats.github.io/tera/docs/) template. + +Furthermore, similar flags to the `sources` command exist. + + +## `update` --- Re-resolve dependencies + +Whenever you update the list of dependencies, you likely have to run `bender update` to re-resolve the dependency versions, and recreate the `Bender.lock` file. + +Calling update with the `--fetch/-f` flag will force all git dependencies to be re-fetched from their corresponding urls. + +> Note: Actually this should be done automatically if you add a new dependency. But due to the lack of coding time, this has to be done manually as of now. + + +## `clone` --- Clone dependency to make modifications + +The `bender clone ` command checks out the package `PKG` into a directory (default `working_dir`, can be overridden with `-p / --path `). +To ensure the package is correctly linked in bender, the `Bender.local` file is modified to include a `path` dependency override, linking to the corresponding package. + +This can be used for development of dependent packages within the parent repository, allowing to test uncommitted and committed changes, without the worry that bender would update the dependency. + +To clean up once the changes are added, ensure the correct version is referenced by the calling packages and remove the path dependency in `Bender.local`, or have a look at `bender snapshot`. + +> Note: The location of the override may be updated in the future to prevent modifying the human-editable `Bender.local` file by adding a persistent section to `Bender.lock`. + +> Note: The newly created directory will be a git repo with a remote origin pointing to the `git` tag of the resolved dependency (usually evaluated from the manifest (`Bender.yml`)). You may need to adjust the git remote URL to properly work with your remote repository. + +## `snapshot` --- Relinks current checkout of cloned dependencies + +After working on a dependency cloned with `bender clone `, modifications are generally committed to the parent git repository. Once committed, this new hash can be quickly used by bender by calling `bender snapshot`. + +With `bender snapshot`, all dependencies previously cloned to a working directory are linked to the git repositories and commit hashes currently checked out. The `Bender.local` is modified correspondingly to ensure reproducibility. Once satisfied with the changes, it is encouraged to properly tag the dependency with a version, remove the override in the `Bender.local`, and update the required version in the `Bender.yml`. + +## `parents` --- Lists packages calling the specified package + +The `bender parents ` command lists all packages calling the `PKG` package. + +## `checkout` --- Checkout all dependencies referenced in the Lock file + +This command will ensure all dependencies are downloaded from remote repositories. This is usually automatically executed by other commands, such as `sources` and `script`. + +## `fusesoc` --- Create FuseSoC `.core` files + +This command will generate FuseSoC `.core` files from the bender representation for open-source compatibility to the FuseSoC tool. It is intended to provide a basic manifest file in a compatible format, such that any project wanting to include a bender package can do so without much overhead. + +If the `--single` argument is provided, only to top-level `Bender.yml` file will be parsed and a `.core` file generated. + +If the `--single` argument is *not* provided, bender will walk through all the dependencies and generate a FuseSoC `.core` file where none is present. If a `.core` file is already present in the same directory as the `Bender.yml` for the corresponding dependency, this will be used to link dependencies (if multiple are available, the user will be prompted to select one). Previously generated `.core` files will be overwritten, based on the included `Created by bender from the available manifest file.` comment in the `.core` file. + +The `--license` argument will allow you to add multiple comment lines at the top of the generated `.core` files, e.g. a License header string. + +The `--fuse-vendor` argument will assign a vendor string to all generated `.core` dependencies for the VLNV name. + +The `--fuse-version` argument will assign a version to the top package being handled for the VLNV name. + +## `vendor` --- Copy files from dependencies that do not support bender + +Collection of commands to manage monorepos. Requires a subcommand. + +Please make sure you manage the includes and sources required for these files separately, as this command only fetches the files and patches them. +This is in part based on [lowRISC's `vendor.py` script](https://github.com/lowRISC/opentitan/blob/master/util/vendor.py). + +### `vendor init` --- (Re-)initialize the vendorized dependencies + +This command will (re-)initialize the dependencies listed in the `vendor_package` section of the `Bender.yml` file, fetching the files from the remote repositories, applying the necessary patch files, and writing them to the respective `target_dir`. + +If the `-n/--no-patch` argument is passed, the dependency is initialized without applying any patches. + +### `vendor diff` --- Print a diff of local, unpatched changes + +This command will print a diff to the remote repository with the patches in `patch_dir` applied. + +### `vendor patch` --- Generate a patch file from local changes + +If there are local, *staged* changes in a vendored dependency, this command prompts for a commit message and generates a patch for that dependency. The patch is written into `patch_dir`. + +If the `--plain` argument is passed, this command will *not* prompt for a commit message and generate a patch of *all* (staged and unstaged) local changes of the vendored dependency. + +### Example workflow + +Let's assume we would like to vendor a dependency `my_ip` into a project `monorepo`. +A simple configuration in a `Bender.yml` could look as follows (see the `Bender.yml` description above for more information on this): + +```yaml +vendor_package: + - name: my_ip + target_dir: deps/my_ip + upstream: { git: "", rev: "" } + patch_dir: "deps/patches/my_ip" +``` + +Executing `bender vendor init` will now clone this dependency from `upstream` and place it in `target_dir`. + +Next, let's assume that we edit two files within the dependency, `deps/my_ip/a` and `deps/my_ip/b`. +We can print these changes with the command `bender vendor diff`. + +Now, we would like to generate a patch with the changes in `deps/my_ip/a` (but not those in `deps/my_ip/b`). +We stage the desired changes using `git add deps/my_ip/a` (of course, you can also just stage parts of a file using `git add --patch`). +The command `bender vendor patch` will now ask for a commit message that will be associated with this patch. +Then, it will place a patch that contains our changes in `deps/my_ip/a` into `deps/patches/my_ip/0001-commit-message.patch` (the number will increment if a numbered patch is already present). + +We can easily create a corresponding commit in the monorepo. +`deps/my_ip/a` is still staged from the previous step. +We only have to `git add deps/patches/my_ip/0001-commit-message.patch` and `git commit` for an atomic commit in the monorepo that contains both our changes to `deps/my_ip/a` and the corresponding patch. + +Upstreaming patches to the dependency is easy as well. +We clone the dependencies' repository, check out `` and create a new branch. +Now, `git am /path/to/monorepo/deps/patches/my_ip/0001-commit-message.patch` will create a commit out of this patch -- including all metadata such as commit message, author(s), and timestamp. +This branch can then be rebased and a pull request can be opened from it as usual. + +Note: when using mappings in your `vendor_package`, the patches will be relative to the mapped directory. +Hence, for upstreaming, you might need to use `git am --directory=` instead of plain `git am`. + +## `completion` --- Generate shell completion script + +The `bender completion ` command prints a completion script for the given shell. + +Installation and usage of these scripts is shell-dependent. Please refer to your shell's documentation +for information on how to install and use the generated script +([bash](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html), +[zsh](https://zsh.sourceforge.io/Doc/Release/Completion-System.html), +[fish](https://fishshell.com/docs/current/completions.html)). + +Supported shells: +- `bash` +- `elvish` +- `fish` +- `powershell` +- `zsh` + +[aur-bender]: https://aur.archlinux.org/packages/bender +[releases]: https://github.com/pulp-platform/bender/releases +[rust-installation]: https://doc.rust-lang.org/book/ch01-01-installation.html diff --git a/book/src/configuration_format.md b/book/src/configuration_format.md new file mode 100644 index 00000000..8f46d8da --- /dev/null +++ b/book/src/configuration_format.md @@ -0,0 +1,58 @@ +# Configuration Format (`bender.yml`, `Bender.local`) + +Bender looks for a configuration file in the following places: + +- `/etc/bender.yml` +- `$HOME/.config/bender.yml` + +It will also look recursively upwards from the current working directory for the following: + +- `.bender.yml` +- `Bender.local` + +The contents of these files are merged as they are encountered, such that a configuration in `foo/.bender.yml` will overwrite a configuration in `foo/bar/.bender.yml`. + +The configuration file generally looks as follows: + +```yaml +# Location of the cloned and checked-out dependencies. Optional. +# Default: ".bender" in the current package's root directory. +database: some/directory + +# The command to use to invoke `git`. Optional. +# Default: "git" +git: git-wrapper.sh + + +# Overrides for dependencies. Optional. +# Forces a dependencies to use specific versions or local paths. Useful for +# locally resolving dependency conflicts in a package's own Bender.local file. +# Format is the same as `dependencies` in a package manifest. +overrides: + common_cells: { path: "/var/magic/common_cells" } + apb_uart: { git: "git@github.com:pulp-platform/apb_uart.git"} + +# Auxiliary plugin dependencies. Optional. +# Additional dependencies that will be loaded for every package in order to +# provide the `plugins` listed in their manifests. +# Format is the same as `dependencies` in a package manifest. +# DEPRECATED: This will be removed at some point. +plugins: + additional-tools: { path: "/usr/local/additional-tools" } + +# Number of parallel git tasks. Optional. +# Default: 4 +# The number of parallel git operations executed by bender can be adjusted to +# manage performance and load on git servers. Can be overriden as a command +# line argument. +git_throttle: 2 + +# Enable git lfs. Optional. +# Default: true +# Some git dependencies may use git-lfs for additional source files. As +# fetching these files may not always be desired or requried, it can be +# disabled. For multiple conflicting settings will use true. +git_lfs: false +``` + +[Relevant code](https://github.com/pulp-platform/bender/blob/master/src/config.rs) diff --git a/book/src/installation.md b/book/src/installation.md new file mode 100644 index 00000000..ade3f1f1 --- /dev/null +++ b/book/src/installation.md @@ -0,0 +1,19 @@ +# Installation + +To use Bender for a single project, the simplest is to download and use a precompiled binary. We provide binaries for all current versions of Ubuntu and CentOS, as well as generic Linux, on each release. Open a terminal and enter the following command: +```sh +curl --proto '=https' --tlsv1.2 https://pulp-platform.github.io/bender/init -sSf | sh +``` +The command downloads and executes a script that detects your distribution and downloads the appropriate `bender` binary of the latest release to your current directory. If you need a specific version of Bender (e.g., `0.21.0`), append ` -s -- 0.21.0` to that command. Alternatively, you can manually download a precompiled binary from [our Releases on GitHub][releases]. + +If you prefer building your own binary, you need to [install Rust][rust-installation]. You can then build and install Bender for the current user with the following command: +```sh +cargo install bender +``` +If you need a specific version of Bender (e.g., `0.21.0`), append ` --version 0.21.0` to that command. + +To install Bender system-wide, you can simply copy the binary you have obtained from one of the above methods to one of the system directories on your `PATH`. Even better, some Linux distributions have Bender in their repositories. We are currently aware of: + +### [ArchLinux ![aur-shield](https://img.shields.io/aur/version/bender)][aur-bender] + +Please extend this list through a PR if you know additional distributions. diff --git a/book/src/manifest_format.md b/book/src/manifest_format.md new file mode 100644 index 00000000..af57ef05 --- /dev/null +++ b/book/src/manifest_format.md @@ -0,0 +1,301 @@ +# Manifest Format (`Bender.yml`) + +The package manifest describes the package, its metadata, its dependencies, and its source files. All paths in the manifest may be relative, in which case they are understood to be relative to the directory that contains the manifest. + +```yaml +# Package metadata. Required. +package: + # The name of the package. Required. + name: magic-chip + + # The list of package authors and contributors. Optional. + # By convention, authors should be listed in the form shown below. + authors: ["John Doe "] + + # A short description of the package. Optional. + description: "This is a magical chip" + +# Specify git remotes for dependencies. Optional. +remotes: + pulp: + url: "https://github.com/pulp-platform" + default: true # Only required if multiple remotes are specified. + + # Additional non-default remotes (HTTP or SSH). + openhw: "https://github.com/openhwgroup" + # Template remote URL where `{}` is a placeholder for dependency name. + # If no placeholder is found, "/{}.git" is used. + internal: "git@gitlab.company.com:internal-repo/{}/release" + +# Other packages this package depends on. Optional. +dependencies: + # Path dependency. + axi: { path: "../axi" } + + # Git version dependency from default remote. + apb: "0.2" + + # Git version dependency from non-default remote. + fll: { version: "0.8", remote: "internal" } + + # Git version dependency with explicit git url. + ara: { git: "https://github.com/john_doe/ara.git", version: "2" } + + # Git revision dependency (always requires explicit git url). + spatz: {git: "https://github.com/pulp-platform/spatz.git", rev: "fixes" } + + # Git version dependency, only included if target "test" or "regression_test" is set. + common_verification: { version: "0.2", target: "any(test, regression_test)" } + + # Git revision dependency, passing a custom target. + # (equivalent to `-t common_cells:cc_custom_target`). + common_cells: { version: "1.39", pass_targets: ["cc_custom_target"] } + + # Git version dependency, passing conditional targets to a dependency + # (equivalent to `-t cva6:cv64a6_imafdcv_sv39` if target 64bit is set, + # `-t cva6:cv32a6_imac_sv32` if target 32bit is set) + ariane: + remote: openhw + version: 5.3.0 + pass_targets: + - {target: 64bit, pass: "cv64a6_imafdcv_sv39"} + - {target: 32bit, pass: "cv32a6_imac_sv32"} + +# Freeze any dependency updates. Optional. False if omitted. +# Useful for chip packages. Once the chip is in final tapeout mode, and +# dependency updates would require disastrous amounts of re-verification. +frozen: true + +# List of source files in this package. Optional. +sources: + # Individual source files are simple string entries: + - src/package.sv + - src/file1.vhd + - src/file2.vhd + + # Source files can be grouped: + - files: + - src/stuff/pkg.sv + - src/stuff/top.sv + + # Grouped source files may have additional include dirs, defines, and target: + - include_dirs: + - src/include + - src/stuff/include + defines: + # Define without a value. + EXCLUDE_MAGIC: ~ + # Define with a value. + PREFIX_NAME: stuff + target: all(asic, synthesis, freepdk45) + files: + - src/core/pkg.sv + - src/core/alu.sv + - src/core/top.sv + + # Source files can use glob patterns to include all matching files: + - src/more_stuff/**/*.sv + + # Source files can have custom fileendings + - sv: vendor/encrypted_sv_src.svp + - v: vendor/encrypted_v_src.vp + - vhd: vendor/encrypted_vhd_src.e + + # File list in another external file, supporting simple file names, `+define+` and `+incdir+` + - external_flists: + - other_file_list.f + files: [] + +# A list of include directories which should implicitly be added to source +# file groups of packages that have the current package as a dependency. +# Optional. +export_include_dirs: + - include + - uvm/magic/include + +# Additional workspace configuration. Optional. +workspace: + # Create symlinks to dependencies. + # A list of paths at which bender will create a symlink to the checked-out + # version of the corresponding package. + package_links: + links/axi: axi + common: common_cells + + # A directory where the dependencies will be checked out. Optional. + # If specified, bender will check out the dependencies once and leave them + # for the user to modify and keep up to date. + # CAUTION: Bender will not touch these after the initial checkout. + # Useful for chip packages, if the intent is to commit all dependencies into + # the chip's version control. + checkout_dir: deps + +# Map of package-provided commands that can be called as `bender `. +# Optional. Only available in dependent packages. +plugins: + hello: scripts/hello.sh + +# List of vendorized files from external repositories not supporting bender. Optional. +vendor_package: + # package name + - name: lowrisc_opentitan + # target directory + target_dir: vendor/lowrisc_opentitan + # upstream dependency (i.e. git repository similar to dependencies, only supports commit hash) + upstream: { git: "https://github.com/lowRISC/opentitan.git", rev: "47a0f4798febd9e53dd131ef8c8c2b0255d8c139" } + # paths to include from upstream dependency. Per default, all paths are included. Optional. + include_from_upstream: + - "src/*" + # paths to exclude from upstream dependency. Paths that also match a pattern in include_from_upstream are excluded. Optional. + exclude_from_upstream: + - "ci/*" + # directory containing patch files. Optional. + patch_dir: "vendor/patches" + # custom file mapping from remote repository to local repository, with optional patch_dir containing patches. Optional. Note: mappings make upstreaming patches slightly more complicated. Avoid if not necessary. + mapping: + - {from: 'hw/ip/prim/rtl/prim_subreg.sv', to: 'src/prim_subreg.sv' } + - {from: 'hw/ip/prim/rtl/prim_subreg_arb.sv', to: 'src/prim_subreg_arb.sv' } + - {from: 'hw/ip/prim/rtl/prim_subreg_ext.sv', to: 'src/prim_subreg_ext.sv', patch_dir: 'lowrisc_opentitan' } + - {from: 'hw/ip/prim/rtl/prim_subreg_shadow.sv', to: 'src/prim_subreg_shadow.sv' } +``` + +[Relevant code](https://github.com/pulp-platform/bender/blob/master/src/config.rs) + + +## Dependencies + +Dependencies are specified in the `dependencies` section of the package manifest, or the `overrides` section in the configuration file. There are different kinds of dependencies, as described in the following. + +### Path + + mydep: { path: "../path/to/mydep" } + +Path dependencies are not considered versioned. Either all versions of dependency `mydep` point to the same path, or otherwise the resolution will fail. + +### Git + + mydep: { git: "git@github.com:pulp-platform/common_verification.git", rev: "" } + mydep: { git: "git@github.com:pulp-platform/common_verification.git", version: "1.1" } + +Git dependencies are automatically checked out and cloned, and are considered for version resolution. The `rev` field can be a git "commit-ish", which essentially is a commit hash, a tag name, or a branch name, where the newest name that starts with the indicated revision is selected. The `version` field can be any of the [semver predicates](https://docs.rs/semver/#requirements), such as a simple version `X.Y.Z` (or `X.Y`), prefixing `=` to only allow that specific version, `~` to limit updates to patches, or defining custom ranges with `>=U.V.W, Note: Git tags without the `v` prefix will not be detected by bender. eg: use `v1.2.3`, and **NOT** `1.2.3` + +[Relevant dependency resolution code](https://github.com/pulp-platform/bender/blob/master/src/resolver.rs) + +### Git LFS Support + +Bender detects if a repository requires Git LFS and if the `git-lfs` tool is installed on your system. + +- If the repository uses LFS (detected via `.gitattributes`) and `git-lfs` is installed, Bender will automatically configure LFS and pull the required files. +- If the repository appears to use LFS but `git-lfs` is **not** installed, Bender will print a warning (`W33`) but proceed with the checkout. In this case, you may end up with pointer files instead of the actual large files, which can cause build failures. +- If the repository does not use LFS, Bender skips LFS operations entirely to save time. + +### Target handling + +Specified dependencies can be filtered, similar to the sources below. For consistency, this filtering does **NOT** apply during an update, i.e., all dependencies will be accounted for in the Bender.lock file. The target filtering only applies for sources and script outputs. This can be used e.g., to include specific IP only for testing. + +### Passing targets + +For sources and script generation, targets can be passed from a package to its dependency directly in the `Bender.yml` file. This allows for enabling and disabling of specific features. Furthermore, these passed targets can be again filtered with a target specification applied to the specific target. This can be used e.g., to enable specific features of dependencies. + + +## Sources + +The source files listed in the `sources` section of the package manifest are a recursive structure. Each entry in the list can either be a single source file, or a group of source files: + +```yaml +# Format of the `sources` section in the manifest: +sources: + - + - + - ... + + # A source file is formatted as follows: + - src/top.sv + + # A source group is formatted as follows. + # Be careful about the `-`, which may appear on the same line as the first + # field of the source group. + - + # List of include directories. Optional. + include_dirs: + - + - + - ... + # List of defines. Optional. + defines: + # Defines without value: + : ~ + : ~ + # Defines with value: + : + : + ... + # Target specifier. Optional. + target: + # Recursive list of source files and groups: + files: + - + - + - ... +``` + +The `target` specification configures a source group to be included or excluded under certain circumstances. See below for details. The `include_dirs` field specifies the `+incdir+...` statements to be added to any compilation command for the group. The `defines` field specifies the `+define+...` statements to be added add to any compilation command for this group. + + +## Targets + +Targets are flags that can be used to filter source files and dependencies. They are used to differentiate the steps in the ASIC/FPGA design flow, the EDA tools, technology targets, and more. They can also be used to have different versions of an IP optimized for different chips or technologies. + +Targets specify a simple expression language, as follows: + +- `*` matches any target +- `name` matches the target "name" +- `all(T1, ..., TN)` matches if all of the targets T1 to TN match (boolean *AND*) +- `any(T1, ..., TN)` matches if any of the targets T1 to TN match (boolean *OR*) +- `not(T)` matches if target T does *not* match (boolean *NOT*) + +The following targets are automatically set by various bender subcommands: + +- `synthesis` for synthesis tool script generation +- `simulation` for simulation tool script generation + +Individual commands may also set tool-specific targets: + +- `vsim` +- `vcs` +- `verilator` +- `synopsys` +- `riviera` +- `genus` +- `vivado` + +Individual commands may also set vendor-specific targets: + +- `xilinx` +- `synopsys` + +Individual commands may also set technology-specific targets: + +- `asic` +- `fpga` + +Additionally, we suggest to use the following targets to identify source code and netlists at different stages in the design process: + +- `test` for testbench code +- `rtl` for synthesizable RTL code +- `gate` for gate-level netlists + +Do not use `:` in your custom targets, as this is used to separate targets to apply to individual packages. + +Do not start the target name with `-`, as this is used to remove target application. + +[Relevant code](https://github.com/pulp-platform/bender/blob/master/src/target.rs) + +## Vendor + +Section to list files and directories copied and patched within this repository from external repositories not supporting bender. +To update, see below `vendor` command. diff --git a/book/src/manifest_format.md#dependencies b/book/src/manifest_format.md#dependencies new file mode 100644 index 00000000..3c3f15c7 --- /dev/null +++ b/book/src/manifest_format.md#dependencies @@ -0,0 +1 @@ +# Dependencies diff --git a/book/src/manifest_format.md#sources b/book/src/manifest_format.md#sources new file mode 100644 index 00000000..e70306d4 --- /dev/null +++ b/book/src/manifest_format.md#sources @@ -0,0 +1 @@ +# Sources diff --git a/book/src/manifest_format.md#targets b/book/src/manifest_format.md#targets new file mode 100644 index 00000000..01d0a4c8 --- /dev/null +++ b/book/src/manifest_format.md#targets @@ -0,0 +1 @@ +# Targets diff --git a/book/src/package_structure.md b/book/src/package_structure.md new file mode 100644 index 00000000..163e120c --- /dev/null +++ b/book/src/package_structure.md @@ -0,0 +1,11 @@ +# Package Structure + +Bender looks for the following three files in a package: + +- `Bender.yml`: This is the main **package manifest**, and the only required file for a directory to be recognized as a Bender package. It contains metadata, dependencies, and source file lists. + +- `Bender.lock`: The **lock file** is generated once all dependencies have been successfully resolved. It contains the exact revision of each dependency. This file *may* be put under version control to allow for reproducible builds. This is handy for example upon taping out a design. If the lock file is missing or a new dependency has been added, it is regenerated. + +- `Bender.local`: This optional file contains **local configuration overrides**. It should be ignored in version control, i.e. added to `.gitignore`. This file can be used to override dependencies with local variants. It is also used when the user asks for a local working copy of a dependency. + +[Relevant code](https://github.com/pulp-platform/bender/blob/master/src/cli.rs) diff --git a/book/src/principles.md b/book/src/principles.md new file mode 100644 index 00000000..f3e514eb --- /dev/null +++ b/book/src/principles.md @@ -0,0 +1,20 @@ +# Principles + +Bender is built around the following core principles: + +- **Be as opt-in as possible.** We do not assume any specific EDA tool, workflow, or directory layout (besides a few key files). All features are designed to be as modular as possible, such that the user can integrate them into their respective flow. + +- **Allow for reproducible builds.** Bender maintains a precise *lock file* which tracks the exact git hash a dependency has been resolved to. This allows the source code of a package to be reliable reconstructed after the fact. + +- **Collect source files.** The first feature tier of Bender is to collect the source files in a hardware IP. In doing this, it shall do the following: + - Maintain the required order across source files, e.g. for package declarations before their use. + - Be as language-agnostic as possible, supporting both SystemVerilog and VHDL. + - Allow source files to be organized into recursive groups. + - Track defines and include directories individually for each group. + +- **Manage dependencies.** The second feature tier of Bender is to maintain other packages an IP may depend on, and to provide a local checkout of the necessary source files. Specifically, it shall: + - Support transitive dependencies + - Not rely on a central package registry, unlike e.g. npm, cargo, or brew (necessary because parts of a project are usually under NDA) + - Enforce strict use of [semantic versioning](https://semver.org/) + +- **Generate tool scripts.** The third feature tier of Bender is the ability to generate source file listings and compilation scripts for various tools. diff --git a/book/src/workflow.md b/book/src/workflow.md new file mode 100644 index 00000000..c238a84d --- /dev/null +++ b/book/src/workflow.md @@ -0,0 +1,7 @@ +# Workflow + +The workflow of bender is based on a configuration and a lock file. The configuration file lists the sources, dependencies, and tests of the package at hand. The lock file is used by the tool to track which exact version of a package is being used. Adding this file to version control, e.g. for chips that will be taped out, makes it easy to reconstruct the exact IPs that were used during a simulation, synthesis, or tapeout. + +Upon executing any command, bender checks to see if dependencies have been added to the configuration file that are not in the lock file. It then tries to find a revision for each added dependency that is compatible with the other dependencies and add that to the lock file. In a second step, bender tries to ensure that the checked out revisions match the ones in the lock file. If not possible, appropriate errors are generated. + +The update command reevaluates all dependencies in the configuration file and tries to find for each a revision that satisfies all recursive constraints. If semantic versioning is used, this will update the dependencies to newer versions within the bounds of the version requirement provided in the configuration file. From 0dcf3ef5d6d770451bd8ba46885b6e5c4bf4be2f Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 12 Feb 2026 13:14:01 +0100 Subject: [PATCH 02/47] Update book --- README.md | 2 +- book/src/commands.md | 4 ---- book/src/installation.md | 4 ++++ book/src/manifest_format.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3947c274..eaaa997b 100644 --- a/README.md +++ b/README.md @@ -283,7 +283,7 @@ All git tags of the form `vX.Y.Z` are considered a version of the package. [Relevant dependency resolution code](https://github.com/pulp-platform/bender/blob/master/src/resolver.rs) -#### Git LFS Support +##### Git LFS Support Bender detects if a repository requires Git LFS and if the `git-lfs` tool is installed on your system. diff --git a/book/src/commands.md b/book/src/commands.md index 24bec9da..b4503c13 100644 --- a/book/src/commands.md +++ b/book/src/commands.md @@ -191,7 +191,3 @@ Supported shells: - `fish` - `powershell` - `zsh` - -[aur-bender]: https://aur.archlinux.org/packages/bender -[releases]: https://github.com/pulp-platform/bender/releases -[rust-installation]: https://doc.rust-lang.org/book/ch01-01-installation.html diff --git a/book/src/installation.md b/book/src/installation.md index ade3f1f1..2202eaf6 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -17,3 +17,7 @@ To install Bender system-wide, you can simply copy the binary you have obtained ### [ArchLinux ![aur-shield](https://img.shields.io/aur/version/bender)][aur-bender] Please extend this list through a PR if you know additional distributions. + +[aur-bender]: https://aur.archlinux.org/packages/bender +[releases]: https://github.com/pulp-platform/bender/releases +[rust-installation]: https://doc.rust-lang.org/book/ch01-01-installation.html diff --git a/book/src/manifest_format.md b/book/src/manifest_format.md index af57ef05..5e79045a 100644 --- a/book/src/manifest_format.md +++ b/book/src/manifest_format.md @@ -185,7 +185,7 @@ All git tags of the form `vX.Y.Z` are considered a version of the package. [Relevant dependency resolution code](https://github.com/pulp-platform/bender/blob/master/src/resolver.rs) -### Git LFS Support +#### Git LFS Support Bender detects if a repository requires Git LFS and if the `git-lfs` tool is installed on your system. From c8de02aab886ea21fdca99aa4e8e32daba4e0727 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 11 Mar 2026 13:27:11 +0100 Subject: [PATCH 03/47] Update book --- book/src/SUMMARY.md | 28 +++++++++++++++++++++++----- book/src/concepts.md | 1 + book/src/dependencies.md | 1 + book/src/getting_started.md | 1 + book/src/index.md | 1 + book/src/installation.md | 9 +++++++++ book/src/local.md | 1 + book/src/lockfile.md | 1 + book/src/manifest.md | 1 + book/src/sources.md | 1 + book/src/targets.md | 1 + book/src/workflow/dependencies.md | 1 + book/src/workflow/init.md | 1 + book/src/workflow/package_dev.md | 1 + book/src/workflow/scripts.md | 1 + book/src/workflow/sources.md | 1 + book/src/workflow/vendor.md | 1 + book/src/workflows.md | 1 + 18 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 book/src/concepts.md create mode 100644 book/src/dependencies.md create mode 100644 book/src/getting_started.md create mode 100644 book/src/index.md create mode 100644 book/src/local.md create mode 100644 book/src/lockfile.md create mode 100644 book/src/manifest.md create mode 100644 book/src/sources.md create mode 100644 book/src/targets.md create mode 100644 book/src/workflow/dependencies.md create mode 100644 book/src/workflow/init.md create mode 100644 book/src/workflow/package_dev.md create mode 100644 book/src/workflow/scripts.md create mode 100644 book/src/workflow/sources.md create mode 100644 book/src/workflow/vendor.md create mode 100644 book/src/workflows.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index b4bf215e..ab79d08f 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -1,12 +1,30 @@ # Summary -- [Principles](./principles.md) +- [Overview](./index.md) - [Installation](./installation.md) +- [Getting Started](./getting_started.md) +- [Concepts](./concepts.md) + - [Principles](./principles.md) + - [Manifest](./manifest.md) + - [Lockfile](./lockfile.md) + - [Local](./local.md) + - [Targets](./targets.md) + - [Dependencies](./dependencies.md) + - [Sources](./sources.md) +- [Workflows](./workflows.md) + - [Initialization](./workflow/init.md) + - [Dependencies](./workflow/dependencies.md) + - [Sources](./workflow/sources.md) + - [Scripts](./workflow/scripts.md) + - [Package Development](./workflow/package_dev.md) + - [Vendor](./workflow/vendor.md) +- [Commands](./commands.md) + + -- [Configuration Format (`bender.yml`, `Bender.local`)](./configuration_format.md) -- [Commands](./commands.md) + - [Targets](./manifest_format.md) +- [Configuration Format (`bender.yml`, `Bender.local`)](./configuration_format.md)--> diff --git a/book/src/concepts.md b/book/src/concepts.md new file mode 100644 index 00000000..74d42e13 --- /dev/null +++ b/book/src/concepts.md @@ -0,0 +1 @@ +# Concepts diff --git a/book/src/dependencies.md b/book/src/dependencies.md new file mode 100644 index 00000000..3c3f15c7 --- /dev/null +++ b/book/src/dependencies.md @@ -0,0 +1 @@ +# Dependencies diff --git a/book/src/getting_started.md b/book/src/getting_started.md new file mode 100644 index 00000000..bad55622 --- /dev/null +++ b/book/src/getting_started.md @@ -0,0 +1 @@ +# Getting Started diff --git a/book/src/index.md b/book/src/index.md new file mode 100644 index 00000000..07dd0c5c --- /dev/null +++ b/book/src/index.md @@ -0,0 +1 @@ +# Overview diff --git a/book/src/installation.md b/book/src/installation.md index 2202eaf6..5547367c 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -12,6 +12,15 @@ cargo install bender ``` If you need a specific version of Bender (e.g., `0.21.0`), append ` --version 0.21.0` to that command. +To compile bender from source, clone the git project and run the following command inside the bender project: +```sh +cargo build +``` +To install the local sources, you can run the following: +```sh +cargo install --path . +``` + To install Bender system-wide, you can simply copy the binary you have obtained from one of the above methods to one of the system directories on your `PATH`. Even better, some Linux distributions have Bender in their repositories. We are currently aware of: ### [ArchLinux ![aur-shield](https://img.shields.io/aur/version/bender)][aur-bender] diff --git a/book/src/local.md b/book/src/local.md new file mode 100644 index 00000000..fb3c6063 --- /dev/null +++ b/book/src/local.md @@ -0,0 +1 @@ +# Local diff --git a/book/src/lockfile.md b/book/src/lockfile.md new file mode 100644 index 00000000..f6823be4 --- /dev/null +++ b/book/src/lockfile.md @@ -0,0 +1 @@ +# Lockfile diff --git a/book/src/manifest.md b/book/src/manifest.md new file mode 100644 index 00000000..243e07a6 --- /dev/null +++ b/book/src/manifest.md @@ -0,0 +1 @@ +# Manifest diff --git a/book/src/sources.md b/book/src/sources.md new file mode 100644 index 00000000..e70306d4 --- /dev/null +++ b/book/src/sources.md @@ -0,0 +1 @@ +# Sources diff --git a/book/src/targets.md b/book/src/targets.md new file mode 100644 index 00000000..01d0a4c8 --- /dev/null +++ b/book/src/targets.md @@ -0,0 +1 @@ +# Targets diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md new file mode 100644 index 00000000..3c3f15c7 --- /dev/null +++ b/book/src/workflow/dependencies.md @@ -0,0 +1 @@ +# Dependencies diff --git a/book/src/workflow/init.md b/book/src/workflow/init.md new file mode 100644 index 00000000..7597c975 --- /dev/null +++ b/book/src/workflow/init.md @@ -0,0 +1 @@ +# Initialization diff --git a/book/src/workflow/package_dev.md b/book/src/workflow/package_dev.md new file mode 100644 index 00000000..e20e4b55 --- /dev/null +++ b/book/src/workflow/package_dev.md @@ -0,0 +1 @@ +# Package Development diff --git a/book/src/workflow/scripts.md b/book/src/workflow/scripts.md new file mode 100644 index 00000000..59d9cb4b --- /dev/null +++ b/book/src/workflow/scripts.md @@ -0,0 +1 @@ +# Scripts diff --git a/book/src/workflow/sources.md b/book/src/workflow/sources.md new file mode 100644 index 00000000..e70306d4 --- /dev/null +++ b/book/src/workflow/sources.md @@ -0,0 +1 @@ +# Sources diff --git a/book/src/workflow/vendor.md b/book/src/workflow/vendor.md new file mode 100644 index 00000000..38225bd0 --- /dev/null +++ b/book/src/workflow/vendor.md @@ -0,0 +1 @@ +# Vendor diff --git a/book/src/workflows.md b/book/src/workflows.md new file mode 100644 index 00000000..307ef403 --- /dev/null +++ b/book/src/workflows.md @@ -0,0 +1 @@ +# Workflows From f11d651de374d005e0aba46a1051b5772ae60e67 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 13:57:39 +0100 Subject: [PATCH 04/47] book: Target documentation --- book/src/targets.md | 144 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/book/src/targets.md b/book/src/targets.md index 01d0a4c8..2198dac4 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -1 +1,145 @@ # Targets + +Targets are the primary mechanism in Bender for managing project configurations. They allow you to conditionally include source files, include directories, and dependencies based on the current context (e.g., simulation vs. synthesis, or FPGA vs. ASIC). + +## Target Expressions + +Bender uses a simple boolean expression language for targets: + +- `*`: Matches any target (wildcard). +- `name`: Matches if the target `name` is active. +- `all(T1, T2, ...)`: Matches if **all** listed targets are active (AND). +- `any(T1, T2, ...)`: Matches if **any** of the listed targets are active (OR). +- `not(T)`: Matches if target `T` is **not** active (NOT). +- `(T)`: Parentheses for grouping. + +Target names are case-insensitive and cannot contain colons (`:`) or start with a hyphen (`-`). + +## Usage in Bender.yml + +### Source Groups +You can wrap a group of files in a `target` specification. This allows you to manage different implementations or verification components within the same package. + +#### Testbench Inclusion +Ensures that verification-only code is never included in the synthesis or production flow: + +```yaml +sources: + # RTL sources + - files: + - src/core.sv + - src/alu.sv + + # Testbench only + - target: test + files: + - tb/driver.sv + - tb/tb_top.sv +``` + +#### Simulation vs. Synthesis +Commonly used to swap between an actual hardware macro and a fast behavioral model for simulation: + +```yaml +sources: + # Behavioral model for faster simulation + - target: all(simulation, not(synthesis)) + files: + - src/behavioral/ip_model.sv +``` + +#### Technology Selection +Useful when choosing between different physical implementations, such as ASIC standard cells versus FPGA primitives: + +```yaml +sources: + - target: asic + files: + - target/asic/clock_gate.sv + - target: fpga + files: + - target/fpga/clock_gate.sv +``` + +#### Core Configuration +Targets can be used to select between different hardware architectures or feature sets: + +```yaml +sources: + # 32-bit architecture + - target: rv32 + files: + - src/core/alu_32.sv + - src/core/regfile_32.sv + # 64-bit architecture + - target: rv64 + files: + - src/core/alu_64.sv + - src/core/regfile_64.sv +``` + +### Dependencies +Dependencies can also be conditional. This is useful for verification IP that is only needed during testing: + +```yaml +dependencies: + common_verification: { version: "0.2", target: any(test, simulation) } +``` + +## Built-in Targets + +Bender automatically activates certain targets based on the subcommand and output format. These "default targets" ensure that tool-specific workarounds or flow-specific files are included correctly. You can disable this behavior with the `--no-default-target` flag. + +### Script Format Targets + +The `bender script` command activates the following targets based on the chosen format: + +| Format | Default Targets | +| :--- | :--- | +| `flist`, `flist-plus` | `flist` | +| `vsim` | `vsim`, `simulation` | +| `vcs` | `vcs`, `simulation` | +| `verilator` | `verilator`, `synthesis` | +| `synopsys` | `synopsys`, `synthesis` | +| `formality` | `synopsys`, `synthesis`, `formality` | +| `riviera` | `riviera`, `simulation` | +| `genus` | `genus`, `synthesis` | +| `vivado` | `vivado`, `fpga`, `xilinx`, `synthesis` | +| `vivadosim` | `vivado`, `fpga`, `xilinx`, `simulation` | +| `precision` | `precision`, `fpga`, `synthesis` | + +### Special Targets + +- **RTL:** If you use the `--assume-rtl` flag, Bender will automatically assign the `rtl` target to any source group that does not have an explicit target specification. +- **ASIC:** While `asic` is a common convention, it is **not** set automatically by Bender. It should be manually activated via `-t asic` when needed. + +## Activating Targets via CLI + +Use the `-t` or `--target` flag with Bender commands: + +```bash +# Enable the 'test' target +bender script vsim -t test + +# Enable multiple targets +bender script vivado -t synthesis -t fpga +``` + +### Advanced CLI Syntax +- **Package-specific:** `-t my_pkg:my_target` activates `my_target` only for `my_pkg`. +- **Negative targets:** `-t -old_target` explicitly disables `old_target`. + +## Passing Targets Hierarchically + +A parent package can pass targets to its dependencies using `pass_targets`. This is useful for propagating configuration flags or selecting specific implementations in sub-modules: + +```yaml +dependencies: + ariane: + version: 5.3.0 + pass_targets: + - {target: rv64, pass: "cv64a6_imafdcv_sv39"} + - {target: rv32, pass: "cv32a6_imac_sv32"} +``` + +In this example, if the `rv64` target is active globally, Bender will ensure the `cv64a6_imafdcv_sv39` target is active specifically for the `ariane` dependency. From 8aeaf6cd5ab1bd3bfcb4d227971b0f776e3edb68 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 13:58:15 +0100 Subject: [PATCH 05/47] book: Targets after dependencies and sources --- book/src/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index ab79d08f..075aafde 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -8,9 +8,9 @@ - [Manifest](./manifest.md) - [Lockfile](./lockfile.md) - [Local](./local.md) - - [Targets](./targets.md) - [Dependencies](./dependencies.md) - [Sources](./sources.md) + - [Targets](./targets.md) - [Workflows](./workflows.md) - [Initialization](./workflow/init.md) - [Dependencies](./workflow/dependencies.md) From c9564cab439263f26c5c8406183d24f29c08582a Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 11 Mar 2026 14:08:50 +0100 Subject: [PATCH 06/47] book: Manifest documentation --- book/src/manifest.md | 102 +++++++++++++++++++++++++++++++- tests/cli_regression/Bender.yml | 4 ++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/book/src/manifest.md b/book/src/manifest.md index 243e07a6..bdacf5e7 100644 --- a/book/src/manifest.md +++ b/book/src/manifest.md @@ -1 +1,101 @@ -# Manifest +# Manifest (`Bender.yml`) + +The package manifest describes the package, its metadata, its dependencies, and its source files. All paths in the manifest may be relative, in which case they are understood to be relative to the directory that contains the manifest. + +It is strongly recommended to start the Manifest file with a license header (open-source or proprietary) as a comment. This provides clarity on the project's usage. + +```yaml +# Copyright (c) 2026 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +``` + +The first section of the manifest should be the package description, outlining the package itself. The package name is required and must match with the name used to call this bender package as a dependency. The name is interpreted in a case-insensitive manner within bender, so additional care should be taken to avoid name conflicts. + +Additionally, authors and a description can be specified. Bender currently does not use these fields but supports their existence. + +```yaml +# Package metadata. Required. +package: + # The name of the package. Required. + name: magic-chip + + # The list of package authors and contributors. Optional. + # By convention, authors should be listed in the form shown below. + authors: ["John Doe "] + + # A short description of the package. Optional. + description: "This is a magical chip" +``` + +The next section in the manifest is the dependencies. Basic projects not requiring any modules from dependencies can omit this section. All packages this bender project depends on should be listed here for proper functionality, including the version requirements. More details on the specific format can be found [here](./dependencies.md). + +```yaml +# Other packages this package depends on. Optional. +dependencies: + common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: "1.39" } +``` + +The sources section lists the HDL source files belonging to this package. It is optional for packages that only provide headers or are otherwise used without their own source files. More details on the format can be found [here](./sources.md). + +```yaml +# List of source files in this package. Optional. +sources: + # Individual source files. + - src/pkg.sv + - src/top.sv +``` + +Include directories that should be passed to all packages depending on this one are listed under `export_include_dirs`. This is the standard mechanism for sharing header files. The include directories listed here also apply to all files in the current package. + +```yaml +# Include directories exported to dependent packages. Optional. +export_include_dirs: + - include +``` + +Setting `frozen` to `true` prevents Bender from updating dependencies beyond what is recorded in the lockfile. This is useful for chip packages in tapeout mode where dependency changes would require disastrous amounts of re-verification. + +```yaml +# Freeze dependency updates. Optional. Defaults to false. +frozen: true +``` + +The workspace section provides additional options for the local working environment. It is not relevant for library packages and is typically only used in the top-level chip package. Package links creates symlinks for the specified dependencies to known locations, while checkout_dir enforces the checkout of all dependencies to a specific location. + +```yaml +# Additional workspace configuration. Optional. +workspace: + # Create symlinks to checked-out dependencies. + package_links: + links/axi: axi + common: common_cells + + # Directory where dependencies will be checked out. Optional. + # Once set, Bender performs the initial checkout and then leaves the directory + # untouched. Useful for chip packages that commit all dependencies into their + # own version control. + checkout_dir: deps +``` + +Packages can expose shell scripts as bender subcommands using the `plugins` section. These commands are available to packages that depend on this one and can be invoked as `bender `. + +```yaml +# Package-provided commands callable as `bender `. Optional. +plugins: + hello: scripts/hello.sh +``` + +The `vendor_package` section lists files copied from external repositories that do not support Bender. Vendored files are managed with the `bender vendor` command. More details on the workflow can be found [here](./workflow/vendor.md). + +```yaml +# Vendorized files from external repositories not supporting Bender. Optional. +vendor_package: + - name: lowrisc_opentitan + target_dir: vendor/lowrisc_opentitan + # Only commit hashes are supported for the upstream revision. + upstream: { git: "https://github.com/lowRISC/opentitan.git", rev: "47a0f4798febd9e53dd131ef8c8c2b0255d8c139" } + # Custom file mappings from upstream paths to local paths. Optional. + mapping: + - { from: "hw/ip/prim/rtl/prim_subreg.sv", to: "src/prim_subreg.sv" } +``` diff --git a/tests/cli_regression/Bender.yml b/tests/cli_regression/Bender.yml index a4200b04..5dd69d9b 100644 --- a/tests/cli_regression/Bender.yml +++ b/tests/cli_regression/Bender.yml @@ -1,3 +1,7 @@ +# Copyright (c) 2026 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + package: name: regression_repo From 45e9599fb519a57c75a244de370e37918c65f98b Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 14:22:17 +0100 Subject: [PATCH 07/47] book: Update targets --- book/src/targets.md | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/book/src/targets.md b/book/src/targets.md index 2198dac4..b85d93ee 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -6,14 +6,25 @@ Targets are the primary mechanism in Bender for managing project configurations. Bender uses a simple boolean expression language for targets: -- `*`: Matches any target (wildcard). -- `name`: Matches if the target `name` is active. -- `all(T1, T2, ...)`: Matches if **all** listed targets are active (AND). -- `any(T1, T2, ...)`: Matches if **any** of the listed targets are active (OR). -- `not(T)`: Matches if target `T` is **not** active (NOT). +- `*`: Wildcard, matches all target sets. +- `name`: Matches if the target `name` is active (case-insensitive). +- `all(T1, T2, ...)`: Matches if **all** arguments match (boolean AND). +- `any(T1, T2, ...)`: Matches if **at least one** argument matches (boolean OR). +- `not(T)`: Matches if `T` does **not** match (boolean NOT). - `(T)`: Parentheses for grouping. -Target names are case-insensitive and cannot contain colons (`:`) or start with a hyphen (`-`). +### Syntax Rules +Target names can contain alphanumeric characters, dots (`.`), underscores (`_`), and hyphens (`-`). + +**Restrictions:** +- They **cannot** contain colons (`:`), as colons are used for package-specific targets in the CLI. +- They **cannot** start with a hyphen (`-`), as leading hyphens are used to disable targets in the CLI. + +### Logical Examples +- `all(asic, synthesis)`: Matches when both 'asic' and 'synthesis' are set. +- `any(vsim, vcs, riviera)`: Matches if any of the listed simulation tools are active. +- `not(simulation)`: Matches only when 'simulation' is **not** set. +- `any(test, all(rtl, simulation))`: Matches for testbenches, or for RTL code during simulation. ## Usage in Bender.yml @@ -79,10 +90,13 @@ sources: ``` ### Dependencies -Dependencies can also be conditional. This is useful for verification IP that is only needed during testing: +You can make a dependency conditional using target expressions. This is commonly used to include verification IP or platform-specific components only when needed: ```yaml dependencies: + # Included only during simulation + uvm: { version: "1.2.0", target: simulation } + # Included for either test or simulation common_verification: { version: "0.2", target: any(test, simulation) } ``` @@ -131,7 +145,20 @@ bender script vivado -t synthesis -t fpga ## Passing Targets Hierarchically -A parent package can pass targets to its dependencies using `pass_targets`. This is useful for propagating configuration flags or selecting specific implementations in sub-modules: +Bender allows you to "configure" your dependencies by passing specific targets down to them using the `pass_targets` field. This is a powerful way to propagate global settings or select implementations in sub-modules. + +### Simple Passing +You can pass a target name as a string, which will then always be active for that specific dependency: + +```yaml +dependencies: + my_submodule: + version: "1.0.0" + pass_targets: ["enable_debug"] # 'enable_debug' is always active for my_submodule +``` + +### Conditional Passing +You can also pass targets conditionally, based on the targets active in the parent package: ```yaml dependencies: From d3efe80703b8c59788d991f68a0c0a2481a8b4bb Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 14:22:22 +0100 Subject: [PATCH 08/47] book: Write dependencies --- book/src/dependencies.md | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 3c3f15c7..28cb3f3a 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -1 +1,82 @@ # Dependencies + +Bender is designed to manage complex, hierarchical dependency trees for hardware projects. A dependency is any external package that provides its own `Bender.yml` manifest. + +## Dependency Types + +Dependencies are defined in the `dependencies` section of your `Bender.yml`. + +### Git Dependencies +Git is the primary way to distribute Bender packages. You can specify them in two ways: + +> **Important:** The shorthand notation (e.g., `common_cells: "1.21.0"`) is only available if you have defined at least one [remote](#remotes) in your manifest. If no remote is specified, you must use the full `git` URL (see [revision](#revision-based)) + +#### Version-based (Recommended) +Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use standard [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges: + +```yaml +dependencies: + common_cells: "1.21.0" + axi: { version: ">=0.23.0, <0.26.0" } +``` +> **Note:** Bender only recognizes Git tags that follow the `vX.Y.Z` format (e.g., `v1.2.1`). + +#### Revision-based +Use this for specific commits, branches, or tags that don't follow SemVer. +```yaml +dependencies: + pulp_soc: { git: "https://github.com/pulp-platform/pulp_soc.git", rev: "develop" } +``` + +### Path Dependencies +Path dependencies point to a local directory. They are never versioned; Bender simply uses the code found at that location. +```yaml +dependencies: + my_local_ip: { path: "../local_ips/my_ip" } +``` + +## Remotes + +To avoid repeating full Git URLs, you can define `remotes` in your manifest. + +### Single Remote +If you only define a single remote, it is automatically treated as the default: + +```yaml +remotes: + pulp: "https://github.com/pulp-platform" + +dependencies: + common_cells: "1.21.0" # Automatically searched in the 'pulp' remote +``` + +### Multiple Remotes +When using multiple remotes, you must explicitly mark one as the `default` if you want to use shortened dependency syntax: + +```yaml +remotes: + pulp: + url: "https://github.com/pulp-platform" + default: true + openhw: "https://github.com/openhwgroup" + +dependencies: + common_cells: "1.21.0" # Uses the default 'pulp' remote + cva6: { version: "4.0.0", remote: openhw } # Explicitly uses 'openhw' +``` + +## Targets + +Dependencies can be conditionally included or configured using targets. For details on how to use target expressions or pass targets to dependencies, see the [Targets](./targets.md) documentation. + +## Git LFS Support + +Bender automatically detects if a dependency uses **Git Large File Storage (LFS)**. If `git-lfs` is installed on your system, Bender will automatically pull the required large files during the checkout process. + +## Version Resolution and the Lockfile + +When you run `bender update`, Bender performs the following: +1. **Resolution:** It scans the entire dependency tree and finds a set of versions that satisfy all constraints. +2. **Locking:** The exact versions and Git commit hashes are written to `Bender.lock`. + +**Reproducibility:** Once a `Bender.lock` exists, running `bender checkout` will always download the exact same code, even if newer compatible versions have been released. Always commit your `Bender.lock` to version control. From 418a883bfa02ad31cac02ed38bba4b05e530ecc0 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 14:41:13 +0100 Subject: [PATCH 09/47] book: Write sources --- book/src/sources.md | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/book/src/sources.md b/book/src/sources.md index e70306d4..973705ed 100644 --- a/book/src/sources.md +++ b/book/src/sources.md @@ -1 +1,103 @@ # Sources + +The `sources` section in `Bender.yml` defines the source files, include directories, and preprocessor definitions that make up your package. + +## Basic File Listing + +The simplest way to include files is to list them as strings. All paths are relative to the location of the `Bender.yml` file. + +```yaml +sources: + - src/my_pkg.sv + - src/my_ip.sv + - src/my_vhdl.vhd +``` + +## Source Groups + +You can group files together to apply common settings like include directories, preprocessor defines, or [targets](./targets.md). + +```yaml +sources: + - include_dirs: + - include + - src/common/include + defines: + USE_FAST_ALU: ~ # Define without a value + BIT_WIDTH: 64 # Define with a value + target: synthesis + files: + - src/rtl/alu.sv + - src/rtl/top.sv +``` + +- **include_dirs**: Paths added to the `+incdir+` flag during compilation. +- **defines**: Preprocessor macros added via `+define+`. +- **target**: A [target expression](./targets.md) that determines if this entire group is included in the current flow. + +## Glob Patterns + +Bender supports glob patterns for automatically including multiple files without listing them individually: + +```yaml +sources: + - src/*.sv # All .sv files in the src directory + - src/submodules/**/*.sv # All .sv files in all subdirectories (recursive) +``` + +## Custom File Types + +While Bender automatically detects file types by standard extensions (`.sv`, `.v`, `.vhd`), you can explicitly specify the type for encrypted or non-standard files: + +```yaml +sources: + - sv: vendor/encrypted_src.svp + - v: vendor/legacy_code.vp + - vhd: vendor/encrypted_vhdl.e +``` + +## External File Lists (`external_flists`) + +If you have existing EDA tool file lists (often `.f` or `.flist`), you can include them directly. Bender will attempt to parse them for source files, include directories, and defines: + +```yaml +sources: + - external_flists: + - scripts/files.f + files: [] +``` + +## File Overrides + +The `override_files: true` flag allows a source group to replace files with the same basename from other parts of the dependency tree. This is a powerful mechanism for "patching" dependencies or swapping implementations at the top level. + +```yaml +sources: + - override_files: true + files: + - patches/axi_fifo.sv # Will replace any 'axi_fifo.sv' found in the dependency tree +``` + +## Exported Include Directories + +If your package provides headers that its *dependents* need (e.g., UVM macros or shared packages), use the `export_include_dirs` section at the top level of the manifest: + +```yaml +package: + name: my_utils + +export_include_dirs: + - include +``` + +Any package that depends on `my_utils` will automatically have the `include` directory added to its include search path. + +> **Best Practice:** To avoid naming collisions, place your headers in a sub-folder named after your package. +> +> **The Problem:** If two packages (`axi` and `apb`) both export a header named `typedefs.svh`, a file including `` `include "typedefs.svh" `` will be ambiguous, and the compiler will pick whichever directory it finds first in the include path. +> +> **The Solution:** Structure your files as `include/axi/typedefs.svh` and `include/apb/typedefs.svh`, then include them with the package prefix: +> ```systemverilog +> `include "axi/typedefs.svh" +> `include "apb/typedefs.svh" +> ``` From 398973b58f434bf7373ccf991065aa1b46cf301c Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 11 Mar 2026 14:38:43 +0100 Subject: [PATCH 10/47] book: Some workflow items --- book/src/dependencies.md | 8 +++++++- book/src/manifest.md | 2 +- book/src/workflow/dependencies.md | 16 +++++++++++++++- book/src/workflow/init.md | 8 ++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 28cb3f3a..91c91cb5 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -73,10 +73,16 @@ Dependencies can be conditionally included or configured using targets. For deta Bender automatically detects if a dependency uses **Git Large File Storage (LFS)**. If `git-lfs` is installed on your system, Bender will automatically pull the required large files during the checkout process. +## Submodules + +TODO + ## Version Resolution and the Lockfile When you run `bender update`, Bender performs the following: 1. **Resolution:** It scans the entire dependency tree and finds a set of versions that satisfy all constraints. -2. **Locking:** The exact versions and Git commit hashes are written to `Bender.lock`. +2. **Locking:** The exact versions and Git commit hashes are written to [`Bender.lock`](./lockfile.md). + +For details on updating dependencies, see [Adding and Updating Dependencies](./workflow/dependencies.md) **Reproducibility:** Once a `Bender.lock` exists, running `bender checkout` will always download the exact same code, even if newer compatible versions have been released. Always commit your `Bender.lock` to version control. diff --git a/book/src/manifest.md b/book/src/manifest.md index bdacf5e7..7800f8fd 100644 --- a/book/src/manifest.md +++ b/book/src/manifest.md @@ -1,6 +1,6 @@ # Manifest (`Bender.yml`) -The package manifest describes the package, its metadata, its dependencies, and its source files. All paths in the manifest may be relative, in which case they are understood to be relative to the directory that contains the manifest. +The package manifest describes the package, its metadata, its dependencies, and its source files. All paths in the manifest may be relative, in which case they are understood to be relative to the directory that contains the manifest. A manifest is required for each bender package. It is strongly recommended to start the Manifest file with a license header (open-source or proprietary) as a comment. This provides clarity on the project's usage. diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md index 3c3f15c7..97aed915 100644 --- a/book/src/workflow/dependencies.md +++ b/book/src/workflow/dependencies.md @@ -1 +1,15 @@ -# Dependencies +# Adding and Updating Dependencies + +As working with dependencies is one of bender's main features, there are a few commands to ensure functionality and assist with understanding the dependency structure. + +## New dependencies +Once new dependencies are added to the manifest, bender needs to first be made aware of their existence. Otherwise, some commands will not work correctly and return an error. To update dependencies, run the following command: + +```sh +bender update +``` + +In case other dependencies already exist and you do not want to re-resolve these, you can add the `--new-only` flag to the update command. + +## Updating dependencies +Similar to when adding new dependencies, updating existing dependencies to more recent versions is also done with the `update` command. diff --git a/book/src/workflow/init.md b/book/src/workflow/init.md index 7597c975..90d2d340 100644 --- a/book/src/workflow/init.md +++ b/book/src/workflow/init.md @@ -1 +1,9 @@ # Initialization + +To initialize a project, bender provides a convenience command to set up an initial empty manifest. + +```sh +bender init +``` + +This creates an initial `Bender.yml` manifest file containing the required package information and a harness for adding dependencies and sources. From ef2cefde81b6089301edcab5332b98a9310958dc Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 15:14:16 +0100 Subject: [PATCH 11/47] book: Update Lockfile --- book/src/lockfile.md | 58 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/book/src/lockfile.md b/book/src/lockfile.md index f6823be4..5828308c 100644 --- a/book/src/lockfile.md +++ b/book/src/lockfile.md @@ -1 +1,57 @@ -# Lockfile +# Lockfile (`Bender.lock`) + +The lockfile, named `Bender.lock`, is a machine-generated file that records the exact version and Git revision (commit hash) of every dependency in your project's tree. + +## Why a Lockfile? + +While `Bender.yml` specifies your *intent* (e.g., "I need `common_cells` version 1.21.x"), the lockfile specifies the *reality* (e.g., "`common_cells` is version 1.21.5 at commit `a1b2c3d`"). + +The lockfile ensures: +- **Reproducible Builds:** Everyone on your team is working with the exact same code. +- **CI Stability:** Your CI pipeline won't suddenly fail because a dependency released a new (but incompatible) version. +- **Speed:** Bender doesn't need to re-resolve the entire dependency tree if the lockfile is already present. + +## How it Works + +The lockfile is managed by two primary commands: + +- **[`bender update`](./workflow/dependencies.md#updating-dependencies):** Scans manifests, resolves constraints, and **updates** the `Bender.lock`. +- **[`bender checkout`](./workflow/dependencies.md#checking-out-dependencies):** Reads the `Bender.lock` and ensures the local state matches the exact recorded revisions. + +## Structure of the Lockfile + +The lockfile is written in YAML. For each package, it stores: + +```yaml +packages: + common_cells: + revision: 290c010c26569ec18683510e1688536f98768000 + version: 1.21.0 + source: + git: "https://github.com/pulp-platform/common_cells.git" + dependencies: + - tech_cells_generic +``` + +- **revision:** The full 40-character Git commit hash. +- **version:** The SemVer version that was resolved. +- **source:** Where to download the package from. +- **dependencies:** A list of other packages that this specific package depends on, ensuring the entire tree is captured. + +## Best Practices + +- **Commit it:** Always check `Bender.lock` into your version control (Git). +- **Update with intention:** Only run `bender update` when you actually want to pull in newer versions of your dependencies. +- **Review changes:** When `Bender.lock` changes, review the diff to see exactly which packages were upgraded. + +## Frozen Manifests + +If you want to prevent accidental updates to your project's dependency tree, you can set `frozen: true` in your `Bender.yml`. + +```yaml +package: + name: my_chip + frozen: true # Prevents 'bender update' from running +``` + +When `frozen: true` is set, `bender update` will fail, ensuring that your `Bender.lock` remains unchanged until you explicitly unfreeze the manifest. This is mostly recommended for late-stage tapeouts. From 97d822dd1d4f7942be2a780671b5db2b77debcb5 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 15:24:26 +0100 Subject: [PATCH 12/47] book: Write local --- book/src/local.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/book/src/local.md b/book/src/local.md index fb3c6063..168c2457 100644 --- a/book/src/local.md +++ b/book/src/local.md @@ -1 +1,44 @@ -# Local +# Local Configuration (`Bender.local`) + +`Bender.local` is an optional, user-specific configuration file used to override the project's default settings. Its primary purpose is to allow local development of dependencies without modifying the shared `Bender.yml` or `Bender.lock`. + +## Overriding Dependencies + +The most common use for `Bender.local` is the `overrides` section. This forces Bender to use a specific version or a local path for a dependency, regardless of what the manifest requires. + +```yaml +overrides: + # Force a local path for 'common_cells' + common_cells: { path: "../local_development/common_cells" } + + # Force a specific git URL/revision + axi: { git: "https://github.com/my_fork/axi.git", rev: "experimental_branch" } +``` + +When an override is present, Bender will prioritize it over any other version resolution. + +## Management + +`Bender.local` can be managed both manually and automatically. Several Bender commands manage it for you during the development process: + +- **[`bender clone`](./workflow/package_dev.md#cloning-dependencies):** Automates moving a dependency to a local working directory and adds a `path` override. +- **[`bender snapshot`](./workflow/package_dev.md#snapshotting):** Updates `Bender.local` with the current Git hashes of your local checkouts. + +For a detailed guide on using these commands for multi-package development, see the [Package Development Workflow](./workflow/package_dev.md). + +## Other Configurations + +`Bender.local` can also be used to configure tool-specific settings: + +```yaml +# Change the directory where dependencies are stored (default is .bender) +database: my_deps_cache + +# Use a custom git binary or wrapper +git: /usr/local/bin/git-wrapper.sh +``` + +## Best Practices + +- **Don't Commit It:** `Bender.local` should **rarely** be checked into version control. It contains paths and settings specific to your local machine. Always add it to your `.gitignore`. +- **Use for Development:** Think of it as your "scratchpad" for multi-package development. Once your changes to a dependency are stable and released (tagged), remember to remove the override from `Bender.local` and update your `Bender.yml` with the new version. From 8be5eb492d3f4d4bd2b08d16ad41429d2d89151d Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 17:40:03 +0100 Subject: [PATCH 13/47] book: Add comparison between three files --- book/src/SUMMARY.md | 1 + book/src/bender_files.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 book/src/bender_files.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 075aafde..e90bd3ee 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -8,6 +8,7 @@ - [Manifest](./manifest.md) - [Lockfile](./lockfile.md) - [Local](./local.md) + - [Manifest vs. Lock vs. Local](./bender_files.md) - [Dependencies](./dependencies.md) - [Sources](./sources.md) - [Targets](./targets.md) diff --git a/book/src/bender_files.md b/book/src/bender_files.md new file mode 100644 index 00000000..047a347a --- /dev/null +++ b/book/src/bender_files.md @@ -0,0 +1,31 @@ +# Bender Files + +Bender relies on three core files to manage your hardware project. While they all use the YAML format, they serve very different roles in the development lifecycle. + +## Comparison Overview + +| Feature | `Bender.yml` | `Bender.lock` | `Bender.local` | +| :--- | :--- | :--- | :--- | +| **Role** | Manifest (Intent) | Lockfile (Reality) | Local Overrides | +| **Main Content** | Dependencies & Version Ranges | Exact Git Revisions | Local Paths & Tool Config | +| **Managed By** | User (Manual) | `bender update` (Auto) | User or `bender clone` | +| **Version Control** | **Commit** | **Commit** | **Ignore** (`.gitignore`) | +| **Shared?** | Yes, with everyone | Yes, for reproducibility | No, unique to your machine | + +## Summary of Roles + +### `Bender.yml` (The Manifest) +This is your **Intent**. It defines the requirements of your package. You use it to specify which other packages you need (e.g., "I need `axi` version `0.21.x`"). It is the only file required to define a Bender package. + +### `Bender.lock` (The Lockfile) +This is the **Reality**. It is a machine-generated file that captures the exact state of your dependency tree. It records the specific Git commit hash for every dependency. By committing this file, you ensure that every developer and CI machine works with the exact same source code. + +### `Bender.local` (Local Overrides) +This is your **Workspace**. It allows you to override the shared configuration for your local environment. Its most common use is to point a dependency to a local directory (via `bender clone`) so you can modify its code and see the effects immediately in your top-level project. + +## Interaction Flow + +1. **Define** your requirements in `Bender.yml`. +2. Run `bender update` to resolve those requirements into a fixed `Bender.lock`. +3. Run `bender checkout` to download the exact source code specified in the lockfile. +4. (Optional) Use `Bender.local` to temporarily swap a dependency for a local version during development. From e830eb4bf1907d70a27276569c6ea631b1627398 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 11 Mar 2026 19:08:56 +0100 Subject: [PATCH 14/47] book: Add CI workflow --- book/src/SUMMARY.md | 2 + book/src/workflow/ci.md | 83 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 book/src/workflow/ci.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index e90bd3ee..38d62a66 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -19,6 +19,8 @@ - [Scripts](./workflow/scripts.md) - [Package Development](./workflow/package_dev.md) - [Vendor](./workflow/vendor.md) + - [Continuous Integration](./workflow/ci.md) + - [Commands](./commands.md) From f51de7a5db297f6611ed267f265ee31d85683a40 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 1 Apr 2026 15:38:03 +0200 Subject: [PATCH 34/47] docs: only deploy on releases --- .github/workflows/docs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d5e78113..98953e3c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,6 +3,8 @@ name: Deploy Documentation on: push: branches: [master] + tags: + - 'v*.*.*' workflow_dispatch: permissions: @@ -45,6 +47,7 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build + if: startsWith(github.ref, 'refs/tags/v') steps: - name: Deploy to GitHub Pages id: deployment From 53bebe12eabf0d4a5aabf16213b46ce3c9922b4f Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 1 Apr 2026 15:50:56 +0200 Subject: [PATCH 35/47] docs: Add PULP logo to README --- README.md | 4 + website/pulp_logo_icon.svg | 194 +++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 website/pulp_logo_icon.svg diff --git a/README.md b/README.md index 6b664ced..1f6c034a 100644 --- a/README.md +++ b/README.md @@ -77,4 +77,8 @@ at your option. --- + +PULP Platform + + Bender is maintained by the [PULP Platform](https://pulp-platform.org/) at ETH Zurich and the University of Bologna. diff --git a/website/pulp_logo_icon.svg b/website/pulp_logo_icon.svg new file mode 100644 index 00000000..1437e65d --- /dev/null +++ b/website/pulp_logo_icon.svg @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ce6f949809810be5f40ede73deaed45a800a86f7 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Wed, 29 Apr 2026 21:11:29 +0200 Subject: [PATCH 36/47] book: implement PR feeback Co-authored-by: Michael Rogenmoser Update book/src/workflow/ci.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/dependencies.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/package_dev.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/scripts.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/dependencies.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/dependencies.md Co-authored-by: Michael Rogenmoser Update book/src/workflow/dependencies.md Co-authored-by: Michael Rogenmoser Update book/src/dependencies.md Co-authored-by: Michael Rogenmoser Update book/src/index.md Co-authored-by: Michael Rogenmoser Update book/src/local.md Co-authored-by: Michael Rogenmoser Update book/src/manifest.md Co-authored-by: Michael Rogenmoser Update book/src/principles.md Co-authored-by: Michael Rogenmoser Update book/src/targets.md Co-authored-by: Michael Rogenmoser --- book/src/dependencies.md | 2 +- book/src/index.md | 6 +++--- book/src/local.md | 2 +- book/src/manifest.md | 4 ++-- book/src/principles.md | 2 +- book/src/targets.md | 2 +- book/src/workflow/ci.md | 2 +- book/src/workflow/dependencies.md | 10 +++++++--- book/src/workflow/package_dev.md | 2 +- book/src/workflow/scripts.md | 2 +- book/src/workflows.md | 1 - 11 files changed, 19 insertions(+), 16 deletions(-) diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 91c91cb5..77b0c29c 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -12,7 +12,7 @@ Git is the primary way to distribute Bender packages. You can specify them in tw > **Important:** The shorthand notation (e.g., `common_cells: "1.21.0"`) is only available if you have defined at least one [remote](#remotes) in your manifest. If no remote is specified, you must use the full `git` URL (see [revision](#revision-based)) #### Version-based (Recommended) -Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use standard [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges: +Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges: ```yaml dependencies: diff --git a/book/src/index.md b/book/src/index.md index f5c57e08..037b6180 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -6,10 +6,10 @@ Bender helps you manage complex hardware IP hierarchies, ensuring that every mem ## Key Features -- **Hierarchical Dependency Management:** Resolve and manage transitive dependencies across multiple Git repositories or local paths. -- **Reproducible Builds:** A precise lockfile mechanism (`Bender.lock`) ensures bit-identical design states across environments. +- **Hierarchical Dependency Management:** Resolve and manage transitive dependencies across multiple Git repositories or local paths, allowing for IPs to be used across projects. +- **Reproducible Builds:** A precise lockfile mechanism (`Bender.lock`) ensures identical design states across environments. - **HDL-Aware Source Collection:** Automatically manages file ordering, include directories, and preprocessor defines for SystemVerilog and VHDL. -- **Target-Based Filtering:** Use powerful boolean expressions to include or exclude files based on your flow (simulation, synthesis, etc.). +- **Target-Based Filtering:** Use powerful boolean expressions to include or exclude files based on your flow (simulation, synthesis, etc.) or design configuration. - **Local Development Workflow:** Easily modify dependencies in-place using the `clone` and `snapshot` flow without breaking official manifests. - **Tool Script Generation:** Generate compilation and simulation scripts for major EDA tools like QuestaSim, VCS, Vivado, Verilator, and more. diff --git a/book/src/local.md b/book/src/local.md index 168c2457..d5cf7e99 100644 --- a/book/src/local.md +++ b/book/src/local.md @@ -40,5 +40,5 @@ git: /usr/local/bin/git-wrapper.sh ## Best Practices -- **Don't Commit It:** `Bender.local` should **rarely** be checked into version control. It contains paths and settings specific to your local machine. Always add it to your `.gitignore`. +- **Don't Commit It:** `Bender.local` should **rarely** be checked into version control. It can contain paths and settings specific to your local machine. Always add it to your `.gitignore`. - **Use for Development:** Think of it as your "scratchpad" for multi-package development. Once your changes to a dependency are stable and released (tagged), remember to remove the override from `Bender.local` and update your `Bender.yml` with the new version. diff --git a/book/src/manifest.md b/book/src/manifest.md index d3297941..69b69925 100644 --- a/book/src/manifest.md +++ b/book/src/manifest.md @@ -84,8 +84,8 @@ workspace: # Directory where dependencies will be checked out. Optional. # Once set, Bender performs the initial checkout and then leaves the directory - # untouched. Useful for chip packages that commit all dependencies into their - # own version control. + # untouched if any modification is detected. Useful for chip packages that commit + # all dependencies into their own version control. checkout_dir: deps ``` diff --git a/book/src/principles.md b/book/src/principles.md index 91368fa3..2a6307dd 100644 --- a/book/src/principles.md +++ b/book/src/principles.md @@ -3,7 +3,7 @@ Bender was created to solve the challenges of managing large-scale hardware designs with complex, nested dependencies. It is built around four core principles that guide its development and usage. ## 1. Modular and Opt-in -Bender is designed to be a "pre-build" tool. It does not replace your EDA tools (synthesis, simulation, formal); it orchestrates them. +Bender is designed to be a "pre-build" tool. It does not replace your EDA tools (synthesis, simulation, formal); it helps orchestrate them. - **Tool Agnostic:** Whether you use Vivado, Questa, VCS, or Verilator, Bender provides the necessary file lists and configurations. - **Flexible Layout:** We do not enforce a strict directory structure. As long as a `Bender.yml` is present, Bender can manage it. diff --git a/book/src/targets.md b/book/src/targets.md index b85d93ee..abb3b50f 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -1,6 +1,6 @@ # Targets -Targets are the primary mechanism in Bender for managing project configurations. They allow you to conditionally include source files, include directories, and dependencies based on the current context (e.g., simulation vs. synthesis, or FPGA vs. ASIC). +Targets are the primary mechanism in Bender for managing project configurations. They allow you to conditionally include source files, include directories, and dependencies based on the current context (e.g., simulation vs. synthesis, or FPGA vs. ASIC) or the desired configuration (e.g., with/without cache). ## Target Expressions diff --git a/book/src/workflow/ci.md b/book/src/workflow/ci.md index 76d85991..1a2b3e2a 100644 --- a/book/src/workflow/ci.md +++ b/book/src/workflow/ci.md @@ -32,7 +32,7 @@ steps: ## GitLab CI -For GitLab CI, you can use the standard [installation script](../installation.md) to fetch the Bender binary at the start of your job. +For GitLab CI, you can use the standard [installation script](../installation.md) to fetch the Bender binary at the start of your job if bender is not already installed in the system. ### Example Workflow diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md index a987de65..34516c54 100644 --- a/book/src/workflow/dependencies.md +++ b/book/src/workflow/dependencies.md @@ -3,7 +3,7 @@ As working with dependencies is one of bender's main features, there are a few commands to ensure functionality and assist with understanding the dependency structure. ## New dependencies -Once new dependencies are added to the manifest, bender needs to first be made aware of their existence. Otherwise, some commands will not work correctly and return an error. To update dependencies, run the following command: +Once new dependencies are added to the manifest, bender needs to first be made aware of their existence. Otherwise, the internally used dependency tree will be incorrect or mismatched, and some commands will not work correctly, returning an error. To update dependencies, run the following command: ```sh bender update @@ -11,6 +11,10 @@ bender update In case other dependencies already exist and you do not want to re-resolve these, you can add the `--new-only` flag to the update command. +> **Note:** On update, bender creates or modifies the [`Bender.lock` lockfile](./lockfile.md), which keeps track of the currently selected dependency versions. + +> **Note:** Most bender commands will automatically run an update if no `Bender.lock` lockfile is found. + ## Updating dependencies Similar to when adding new dependencies, updating existing dependencies to more recent versions is also done with the `update` command. @@ -40,7 +44,7 @@ Bender will download the exact revisions specified in `Bender.lock`. This comman > **Note:** Many other commands (like `sources` or `script`) will automatically trigger a checkout if they detect missing dependencies. -## Inspecting the Dependency Tree +## Inspecting the Dependency Tree (`packages`) To see the full list of dependencies and how they relate to each other, use the `packages` command: @@ -50,7 +54,7 @@ bender packages This prints a tree structure showing every package in your project, its resolved version, and its source. Use the `-f/--flat` flag if you just want a simple list of names and versions. -## Finding Package Paths +## Finding Package Paths (`path`) If you need to know where a specific dependency is stored (e.g., to point an external tool to it), use: diff --git a/book/src/workflow/package_dev.md b/book/src/workflow/package_dev.md index 11144aec..ba0ee2d4 100644 --- a/book/src/workflow/package_dev.md +++ b/book/src/workflow/package_dev.md @@ -41,6 +41,6 @@ The main benefit of a snapshot is portability. Because the lockfile is updated w Once your changes are stable and you are ready to "release" them: 1. **Tag the Dependency:** Push your changes to the remote repository and create a new version tag (e.g., `v1.2.2`). -2. **Update Manifest:** Update the version requirement in your top-level `Bender.yml` to include the new version. +2. **Update Manifest:** Update the version requirement in your `Bender.yml` to include the new version. 3. **Clean Up:** Remove the local overrides from your `Bender.local` file. 4. **Resolve:** Run `bender update` to re-resolve the dependency tree and update `Bender.lock` to point to the new official version. diff --git a/book/src/workflow/scripts.md b/book/src/workflow/scripts.md index a0fde802..f93d4b53 100644 --- a/book/src/workflow/scripts.md +++ b/book/src/workflow/scripts.md @@ -54,7 +54,7 @@ The `script` command provides several flags to fine-tune the generated output: - **`-e/--exclude `**: Exclude a specific package from the generated script. ### RTL Assumption -- **`--assume-rtl`**: Automatically adds the `rtl` target to any source group that does not have an explicit target specification. This is a common shorthand for generating synthesis scripts without having to tag every RTL file. +- **`--assume-rtl`**: Automatically adds the `rtl` target to any source group that does not have an explicit target specification. This is an optional shorthand for generating synthesis scripts without having to tag every RTL file. ### Compilation Control - **`--compilation-mode `**: diff --git a/book/src/workflows.md b/book/src/workflows.md index 8ec5971e..93cc2e20 100644 --- a/book/src/workflows.md +++ b/book/src/workflows.md @@ -4,7 +4,6 @@ This section provides practical guides on how to use Bender for common hardware - **[Initialization](./workflow/init.md):** Setting up a new Bender package from scratch. - **[Adding and Updating Dependencies](./workflow/dependencies.md):** Managing external packages and ensuring reproducible builds. -- **[Inspecting Source Files](./workflow/sources.md):** Exploring and filtering the source files in your project. - **[Generating Tool Scripts](./workflow/scripts.md):** Creating compilation and simulation scripts for various EDA tools. - **[Package Development](./workflow/package_dev.md):** Developing multiple packages simultaneously using the `clone` and `snapshot` flow. - **[Vendorizing External Code](./workflow/vendor.md):** Managing external repositories that don't natively support Bender. From 821f24adeec7765294be14bef446443376e8aaa4 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Thu, 30 Apr 2026 16:59:36 +0200 Subject: [PATCH 37/47] gitinore: add missing newline --- book/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/.gitignore b/book/.gitignore index e9c07289..7585238e 100644 --- a/book/.gitignore +++ b/book/.gitignore @@ -1 +1 @@ -book \ No newline at end of file +book From 07cc3079a787c3577c1fa23858406b924f3b4c35 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Thu, 30 Apr 2026 17:01:03 +0200 Subject: [PATCH 38/47] book: add CI worfklow to overview --- book/src/workflows.md | 1 + 1 file changed, 1 insertion(+) diff --git a/book/src/workflows.md b/book/src/workflows.md index 93cc2e20..3dc3c6fc 100644 --- a/book/src/workflows.md +++ b/book/src/workflows.md @@ -7,3 +7,4 @@ This section provides practical guides on how to use Bender for common hardware - **[Generating Tool Scripts](./workflow/scripts.md):** Creating compilation and simulation scripts for various EDA tools. - **[Package Development](./workflow/package_dev.md):** Developing multiple packages simultaneously using the `clone` and `snapshot` flow. - **[Vendorizing External Code](./workflow/vendor.md):** Managing external repositories that don't natively support Bender. +- **[Continuous Integration](./workflow/ci.md):** Optimizing CI pipelines. From 18001a84ad3b2e71b9ccf9ea1adce5d2607e8a9d Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Thu, 30 Apr 2026 17:18:38 +0200 Subject: [PATCH 39/47] book: link bender files to its section --- book/src/bender_files.md | 14 +++++++------- book/src/commands.md | 22 +++++++++++----------- book/src/configuration.md | 8 ++++---- book/src/dependencies.md | 6 +++--- book/src/getting_started.md | 6 +++--- book/src/index.md | 2 +- book/src/local.md | 8 ++++---- book/src/lockfile.md | 8 ++++---- book/src/principles.md | 6 +++--- book/src/sources.md | 4 ++-- book/src/targets.md | 2 +- book/src/workflow/ci.md | 8 ++++---- book/src/workflow/dependencies.md | 8 ++++---- book/src/workflow/init.md | 4 ++-- book/src/workflow/package_dev.md | 14 +++++++------- book/src/workflow/vendor.md | 4 ++-- 16 files changed, 62 insertions(+), 62 deletions(-) diff --git a/book/src/bender_files.md b/book/src/bender_files.md index 047a347a..c1c62083 100644 --- a/book/src/bender_files.md +++ b/book/src/bender_files.md @@ -4,7 +4,7 @@ Bender relies on three core files to manage your hardware project. While they al ## Comparison Overview -| Feature | `Bender.yml` | `Bender.lock` | `Bender.local` | +| Feature | [`Bender.yml`](./manifest.md) | [`Bender.lock`](./lockfile.md) | [`Bender.local`](./local.md) | | :--- | :--- | :--- | :--- | | **Role** | Manifest (Intent) | Lockfile (Reality) | Local Overrides | | **Main Content** | Dependencies & Version Ranges | Exact Git Revisions | Local Paths & Tool Config | @@ -14,18 +14,18 @@ Bender relies on three core files to manage your hardware project. While they al ## Summary of Roles -### `Bender.yml` (The Manifest) +### [`Bender.yml`](./manifest.md) (The Manifest) This is your **Intent**. It defines the requirements of your package. You use it to specify which other packages you need (e.g., "I need `axi` version `0.21.x`"). It is the only file required to define a Bender package. -### `Bender.lock` (The Lockfile) +### [`Bender.lock`](./lockfile.md) (The Lockfile) This is the **Reality**. It is a machine-generated file that captures the exact state of your dependency tree. It records the specific Git commit hash for every dependency. By committing this file, you ensure that every developer and CI machine works with the exact same source code. -### `Bender.local` (Local Overrides) +### [`Bender.local`](./local.md) (Local Overrides) This is your **Workspace**. It allows you to override the shared configuration for your local environment. Its most common use is to point a dependency to a local directory (via `bender clone`) so you can modify its code and see the effects immediately in your top-level project. ## Interaction Flow -1. **Define** your requirements in `Bender.yml`. -2. Run `bender update` to resolve those requirements into a fixed `Bender.lock`. +1. **Define** your requirements in [`Bender.yml`](./manifest.md). +2. Run `bender update` to resolve those requirements into a fixed [`Bender.lock`](./lockfile.md). 3. Run `bender checkout` to download the exact source code specified in the lockfile. -4. (Optional) Use `Bender.local` to temporarily swap a dependency for a local version during development. +4. (Optional) Use [`Bender.local`](./local.md) to temporarily swap a dependency for a local version during development. diff --git a/book/src/commands.md b/book/src/commands.md index b4503c13..d4c176b9 100644 --- a/book/src/commands.md +++ b/book/src/commands.md @@ -1,6 +1,6 @@ # Commands -`bender` is the entry point to the dependency management system. Bender always operates within a package; starting at the current working directory, search upwards the file hierarchy until a `Bender.yml` is found, which marks the package. +`bender` is the entry point to the dependency management system. Bender always operates within a package; starting at the current working directory, search upwards the file hierarchy until a [`Bender.yml`](./manifest.md) is found, which marks the package. ## `path` --- Get the path of a checked-out package @@ -69,7 +69,7 @@ Furthermore, similar flags to the `sources` command exist. ## `update` --- Re-resolve dependencies -Whenever you update the list of dependencies, you likely have to run `bender update` to re-resolve the dependency versions, and recreate the `Bender.lock` file. +Whenever you update the list of dependencies, you likely have to run `bender update` to re-resolve the dependency versions, and recreate the [`Bender.lock`](./lockfile.md) file. Calling update with the `--fetch/-f` flag will force all git dependencies to be re-fetched from their corresponding urls. @@ -79,21 +79,21 @@ Calling update with the `--fetch/-f` flag will force all git dependencies to be ## `clone` --- Clone dependency to make modifications The `bender clone ` command checks out the package `PKG` into a directory (default `working_dir`, can be overridden with `-p / --path `). -To ensure the package is correctly linked in bender, the `Bender.local` file is modified to include a `path` dependency override, linking to the corresponding package. +To ensure the package is correctly linked in bender, the [`Bender.local`](./local.md) file is modified to include a `path` dependency override, linking to the corresponding package. This can be used for development of dependent packages within the parent repository, allowing to test uncommitted and committed changes, without the worry that bender would update the dependency. -To clean up once the changes are added, ensure the correct version is referenced by the calling packages and remove the path dependency in `Bender.local`, or have a look at `bender snapshot`. +To clean up once the changes are added, ensure the correct version is referenced by the calling packages and remove the path dependency in [`Bender.local`](./local.md), or have a look at `bender snapshot`. -> Note: The location of the override may be updated in the future to prevent modifying the human-editable `Bender.local` file by adding a persistent section to `Bender.lock`. +> Note: The location of the override may be updated in the future to prevent modifying the human-editable [`Bender.local`](./local.md) file by adding a persistent section to [`Bender.lock`](./lockfile.md). -> Note: The newly created directory will be a git repo with a remote origin pointing to the `git` tag of the resolved dependency (usually evaluated from the manifest (`Bender.yml`)). You may need to adjust the git remote URL to properly work with your remote repository. +> Note: The newly created directory will be a git repo with a remote origin pointing to the `git` tag of the resolved dependency (usually evaluated from the manifest ([`Bender.yml`](./manifest.md))). You may need to adjust the git remote URL to properly work with your remote repository. ## `snapshot` --- Relinks current checkout of cloned dependencies After working on a dependency cloned with `bender clone `, modifications are generally committed to the parent git repository. Once committed, this new hash can be quickly used by bender by calling `bender snapshot`. -With `bender snapshot`, all dependencies previously cloned to a working directory are linked to the git repositories and commit hashes currently checked out. The `Bender.local` is modified correspondingly to ensure reproducibility. Once satisfied with the changes, it is encouraged to properly tag the dependency with a version, remove the override in the `Bender.local`, and update the required version in the `Bender.yml`. +With `bender snapshot`, all dependencies previously cloned to a working directory are linked to the git repositories and commit hashes currently checked out. The [`Bender.local`](./local.md) is modified correspondingly to ensure reproducibility. Once satisfied with the changes, it is encouraged to properly tag the dependency with a version, remove the override in the [`Bender.local`](./local.md), and update the required version in the [`Bender.yml`](./manifest.md). ## `parents` --- Lists packages calling the specified package @@ -107,9 +107,9 @@ This command will ensure all dependencies are downloaded from remote repositorie This command will generate FuseSoC `.core` files from the bender representation for open-source compatibility to the FuseSoC tool. It is intended to provide a basic manifest file in a compatible format, such that any project wanting to include a bender package can do so without much overhead. -If the `--single` argument is provided, only to top-level `Bender.yml` file will be parsed and a `.core` file generated. +If the `--single` argument is provided, only to top-level [`Bender.yml`](./manifest.md) file will be parsed and a `.core` file generated. -If the `--single` argument is *not* provided, bender will walk through all the dependencies and generate a FuseSoC `.core` file where none is present. If a `.core` file is already present in the same directory as the `Bender.yml` for the corresponding dependency, this will be used to link dependencies (if multiple are available, the user will be prompted to select one). Previously generated `.core` files will be overwritten, based on the included `Created by bender from the available manifest file.` comment in the `.core` file. +If the `--single` argument is *not* provided, bender will walk through all the dependencies and generate a FuseSoC `.core` file where none is present. If a `.core` file is already present in the same directory as the [`Bender.yml`](./manifest.md) for the corresponding dependency, this will be used to link dependencies (if multiple are available, the user will be prompted to select one). Previously generated `.core` files will be overwritten, based on the included `Created by bender from the available manifest file.` comment in the `.core` file. The `--license` argument will allow you to add multiple comment lines at the top of the generated `.core` files, e.g. a License header string. @@ -126,7 +126,7 @@ This is in part based on [lowRISC's `vendor.py` script](https://github.com/lowRI ### `vendor init` --- (Re-)initialize the vendorized dependencies -This command will (re-)initialize the dependencies listed in the `vendor_package` section of the `Bender.yml` file, fetching the files from the remote repositories, applying the necessary patch files, and writing them to the respective `target_dir`. +This command will (re-)initialize the dependencies listed in the `vendor_package` section of the [`Bender.yml`](./manifest.md) file, fetching the files from the remote repositories, applying the necessary patch files, and writing them to the respective `target_dir`. If the `-n/--no-patch` argument is passed, the dependency is initialized without applying any patches. @@ -143,7 +143,7 @@ If the `--plain` argument is passed, this command will *not* prompt for a commit ### Example workflow Let's assume we would like to vendor a dependency `my_ip` into a project `monorepo`. -A simple configuration in a `Bender.yml` could look as follows (see the `Bender.yml` description above for more information on this): +A simple configuration in a [`Bender.yml`](./manifest.md) could look as follows (see the [`Bender.yml`](./manifest.md) description above for more information on this): ```yaml vendor_package: diff --git a/book/src/configuration.md b/book/src/configuration.md index 765b4908..8128b34b 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -9,9 +9,9 @@ Bender looks for configuration files in the following order, merging them as the 1. **System-wide:** `/etc/bender.yml` 2. **User-specific:** `$HOME/.config/bender.yml` (or the equivalent on your OS) 3. **Project-specific (checked in):** `.bender.yml` in your project root. -4. **Local Workspace (ignored):** `Bender.local` in your project root. +4. **Local Workspace (ignored):** [`Bender.local`](./local.md) in your project root. -The contents of these files are merged such that a configuration in a lower-level file (like `Bender.local`) will overwrite a configuration in a higher-level file (like `/etc/bender.yml`). +The contents of these files are merged such that a configuration in a lower-level file (like [`Bender.local`](./local.md)) will overwrite a configuration in a higher-level file (like `/etc/bender.yml`). ## Configuration Fields @@ -38,7 +38,7 @@ Enable or disable Git Large File Storage (LFS) support. - **Example:** `git_lfs: false` ### `overrides` -Forces specific dependencies to use a particular version or local path. This is primarily used in `Bender.local` for development. +Forces specific dependencies to use a particular version or local path. This is primarily used in [`Bender.local`](./local.md) for development. - **Example:** ```yaml overrides: @@ -50,7 +50,7 @@ Auxiliary plugin dependencies that are loaded for every package. These allow you ## Usage Example -A typical `Bender.local` file used for local development might look like this: +A typical [`Bender.local`](./local.md) file used for local development might look like this: ```yaml # Speed up git operations locally diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 77b0c29c..365cfb5d 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -1,10 +1,10 @@ # Dependencies -Bender is designed to manage complex, hierarchical dependency trees for hardware projects. A dependency is any external package that provides its own `Bender.yml` manifest. +Bender is designed to manage complex, hierarchical dependency trees for hardware projects. A dependency is any external package that provides its own [`Bender.yml`](./manifest.md) manifest. ## Dependency Types -Dependencies are defined in the `dependencies` section of your `Bender.yml`. +Dependencies are defined in the `dependencies` section of your [`Bender.yml`](./manifest.md). ### Git Dependencies Git is the primary way to distribute Bender packages. You can specify them in two ways: @@ -85,4 +85,4 @@ When you run `bender update`, Bender performs the following: For details on updating dependencies, see [Adding and Updating Dependencies](./workflow/dependencies.md) -**Reproducibility:** Once a `Bender.lock` exists, running `bender checkout` will always download the exact same code, even if newer compatible versions have been released. Always commit your `Bender.lock` to version control. +**Reproducibility:** Once a [`Bender.lock`](./lockfile.md) exists, running `bender checkout` will always download the exact same code, even if newer compatible versions have been released. Always commit your [`Bender.lock`](./lockfile.md) to version control. diff --git a/book/src/getting_started.md b/book/src/getting_started.md index 3d2a602e..37e1daf9 100644 --- a/book/src/getting_started.md +++ b/book/src/getting_started.md @@ -12,11 +12,11 @@ cd my_new_ip bender init ``` -This creates a default `Bender.yml` file. Bender will automatically try to fill in your name and email from your Git configuration. +This creates a default [`Bender.yml`](./manifest.md) file. Bender will automatically try to fill in your name and email from your Git configuration. ## 2. Add a Dependency -Open `Bender.yml` in your editor and add the `common_cells` library to the `dependencies` section: +Open [`Bender.yml`](./manifest.md) in your editor and add the `common_cells` library to the `dependencies` section: ```yaml package: @@ -38,7 +38,7 @@ Now, tell Bender to resolve the version of `common_cells` and download it: bender update ``` -This command creates a `Bender.lock` file (the "exact" version chosen) and downloads the source code into a hidden `.bender` directory. +This command creates a [`Bender.lock`](./lockfile.md) file (the "exact" version chosen) and downloads the source code into a hidden `.bender` directory. ## 4. Add Source Code diff --git a/book/src/index.md b/book/src/index.md index 037b6180..94c39044 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -7,7 +7,7 @@ Bender helps you manage complex hardware IP hierarchies, ensuring that every mem ## Key Features - **Hierarchical Dependency Management:** Resolve and manage transitive dependencies across multiple Git repositories or local paths, allowing for IPs to be used across projects. -- **Reproducible Builds:** A precise lockfile mechanism (`Bender.lock`) ensures identical design states across environments. +- **Reproducible Builds:** A precise lockfile mechanism ([`Bender.lock`](./lockfile.md)) ensures identical design states across environments. - **HDL-Aware Source Collection:** Automatically manages file ordering, include directories, and preprocessor defines for SystemVerilog and VHDL. - **Target-Based Filtering:** Use powerful boolean expressions to include or exclude files based on your flow (simulation, synthesis, etc.) or design configuration. - **Local Development Workflow:** Easily modify dependencies in-place using the `clone` and `snapshot` flow without breaking official manifests. diff --git a/book/src/local.md b/book/src/local.md index d5cf7e99..c1fba492 100644 --- a/book/src/local.md +++ b/book/src/local.md @@ -1,6 +1,6 @@ # Local Configuration (`Bender.local`) -`Bender.local` is an optional, user-specific configuration file used to override the project's default settings. Its primary purpose is to allow local development of dependencies without modifying the shared `Bender.yml` or `Bender.lock`. +`Bender.local` is an optional, user-specific configuration file used to override the project's default settings. Its primary purpose is to allow local development of dependencies without modifying the shared [`Bender.yml`](./manifest.md) or [`Bender.lock`](./lockfile.md). ## Overriding Dependencies @@ -21,8 +21,8 @@ When an override is present, Bender will prioritize it over any other version re `Bender.local` can be managed both manually and automatically. Several Bender commands manage it for you during the development process: -- **[`bender clone`](./workflow/package_dev.md#cloning-dependencies):** Automates moving a dependency to a local working directory and adds a `path` override. -- **[`bender snapshot`](./workflow/package_dev.md#snapshotting):** Updates `Bender.local` with the current Git hashes of your local checkouts. +- [`bender clone`](./workflow/package_dev.md#cloning-dependencies): Automates moving a dependency to a local working directory and adds a `path` override. +- [`bender snapshot`](./workflow/package_dev.md#snapshotting): Updates `Bender.local` with the current Git hashes of your local checkouts. For a detailed guide on using these commands for multi-package development, see the [Package Development Workflow](./workflow/package_dev.md). @@ -41,4 +41,4 @@ git: /usr/local/bin/git-wrapper.sh ## Best Practices - **Don't Commit It:** `Bender.local` should **rarely** be checked into version control. It can contain paths and settings specific to your local machine. Always add it to your `.gitignore`. -- **Use for Development:** Think of it as your "scratchpad" for multi-package development. Once your changes to a dependency are stable and released (tagged), remember to remove the override from `Bender.local` and update your `Bender.yml` with the new version. +- **Use for Development:** Think of it as your "scratchpad" for multi-package development. Once your changes to a dependency are stable and released (tagged), remember to remove the override from `Bender.local` and update your [`Bender.yml`](./manifest.md) with the new version. diff --git a/book/src/lockfile.md b/book/src/lockfile.md index 5828308c..bfaf404c 100644 --- a/book/src/lockfile.md +++ b/book/src/lockfile.md @@ -4,7 +4,7 @@ The lockfile, named `Bender.lock`, is a machine-generated file that records the ## Why a Lockfile? -While `Bender.yml` specifies your *intent* (e.g., "I need `common_cells` version 1.21.x"), the lockfile specifies the *reality* (e.g., "`common_cells` is version 1.21.5 at commit `a1b2c3d`"). +While [`Bender.yml`](./manifest.md) specifies your *intent* (e.g., "I need `common_cells` version 1.21.x"), the lockfile specifies the *reality* (e.g., "`common_cells` is version 1.21.5 at commit `a1b2c3d`"). The lockfile ensures: - **Reproducible Builds:** Everyone on your team is working with the exact same code. @@ -15,8 +15,8 @@ The lockfile ensures: The lockfile is managed by two primary commands: -- **[`bender update`](./workflow/dependencies.md#updating-dependencies):** Scans manifests, resolves constraints, and **updates** the `Bender.lock`. -- **[`bender checkout`](./workflow/dependencies.md#checking-out-dependencies):** Reads the `Bender.lock` and ensures the local state matches the exact recorded revisions. +- [`bender update`](./workflow/dependencies.md#updating-dependencies): Scans manifests, resolves constraints, and **updates** the `Bender.lock`. +- [`bender checkout`](./workflow/dependencies.md#checking-out-dependencies): Reads the `Bender.lock` and ensures the local state matches the exact recorded revisions. ## Structure of the Lockfile @@ -46,7 +46,7 @@ packages: ## Frozen Manifests -If you want to prevent accidental updates to your project's dependency tree, you can set `frozen: true` in your `Bender.yml`. +If you want to prevent accidental updates to your project's dependency tree, you can set `frozen: true` in your [`Bender.yml`](./manifest.md). ```yaml package: diff --git a/book/src/principles.md b/book/src/principles.md index 2a6307dd..4567699f 100644 --- a/book/src/principles.md +++ b/book/src/principles.md @@ -5,11 +5,11 @@ Bender was created to solve the challenges of managing large-scale hardware desi ## 1. Modular and Opt-in Bender is designed to be a "pre-build" tool. It does not replace your EDA tools (synthesis, simulation, formal); it helps orchestrate them. - **Tool Agnostic:** Whether you use Vivado, Questa, VCS, or Verilator, Bender provides the necessary file lists and configurations. -- **Flexible Layout:** We do not enforce a strict directory structure. As long as a `Bender.yml` is present, Bender can manage it. +- **Flexible Layout:** We do not enforce a strict directory structure. As long as a [`Bender.yml`](./manifest.md) is present, Bender can manage it. ## 2. Reproducibility as Ground Truth In hardware design, knowing exactly what was taped out or simulated is critical. -- **Precise Locking:** The `Bender.lock` file tracks every dependency down to its specific Git commit hash. +- **Precise Locking:** The [`Bender.lock`](./lockfile.md) file tracks every dependency down to its specific Git commit hash. - **Immutable States:** By committing the lockfile, you ensure that everyone on the team—and every CI runner—is using identical source code. ## 3. Decentralized and Secure @@ -19,7 +19,7 @@ Unlike many software package managers (like npm or cargo), Bender does not rely ## 4. Local-First Development Hardware development often requires modifying an IP and its dependencies simultaneously. -- **Zero-Friction Overrides:** The `Bender.local` mechanism allows you to temporarily swap a remote dependency for a local working copy without changing the project's official manifest. +- **Zero-Friction Overrides:** The [`Bender.local`](./local.md) mechanism allows you to temporarily swap a remote dependency for a local working copy without changing the project's official manifest. - **Seamless Snapshots:** Captured states can be shared or moved to CI easily, bridging the gap between local development and official releases. --- diff --git a/book/src/sources.md b/book/src/sources.md index 973705ed..ebcdc702 100644 --- a/book/src/sources.md +++ b/book/src/sources.md @@ -1,10 +1,10 @@ # Sources -The `sources` section in `Bender.yml` defines the source files, include directories, and preprocessor definitions that make up your package. +The `sources` section in [`Bender.yml`](./manifest.md) defines the source files, include directories, and preprocessor definitions that make up your package. ## Basic File Listing -The simplest way to include files is to list them as strings. All paths are relative to the location of the `Bender.yml` file. +The simplest way to include files is to list them as strings. All paths are relative to the location of the [`Bender.yml`](./manifest.md) file. ```yaml sources: diff --git a/book/src/targets.md b/book/src/targets.md index abb3b50f..c5a86bf8 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -26,7 +26,7 @@ Target names can contain alphanumeric characters, dots (`.`), underscores (`_`), - `not(simulation)`: Matches only when 'simulation' is **not** set. - `any(test, all(rtl, simulation))`: Matches for testbenches, or for RTL code during simulation. -## Usage in Bender.yml +## Usage in [`Bender.yml`](./manifest.md) ### Source Groups You can wrap a group of files in a `target` specification. This allows you to manage different implementations or verification components within the same package. diff --git a/book/src/workflow/ci.md b/book/src/workflow/ci.md index 1a2b3e2a..0dbc5531 100644 --- a/book/src/workflow/ci.md +++ b/book/src/workflow/ci.md @@ -4,9 +4,9 @@ Integrating Bender into your CI/CD pipeline ensures that your hardware project i ## Reproducibility -In a CI environment, you should never run `bender update`. Instead, your pipeline should rely on the `Bender.lock` file to fetch the exact revisions of your dependencies. +In a CI environment, you should never run `bender update`. Instead, your pipeline should rely on the [`Bender.lock`](../lockfile.md) file to fetch the exact revisions of your dependencies. -1. **Commit** `Bender.lock`: Ensure the lockfile is checked into your repository. +1. **Commit** [`Bender.lock`](../lockfile.md): Ensure the lockfile is checked into your repository. 2. **Use** `bender checkout`: This command reads the lockfile and reconstructs the dependency tree without changing any versions. ## GitHub Actions @@ -55,7 +55,7 @@ sim_job: ## Caching -Since `Bender.lock` uniquely identifies the state of all dependencies, it is theoretically possible to cache the `.bender` directory to speed up pipelines. However, for most projects, the overhead of managing the cache (uploading/downloading) might outweigh the time saved by `bender checkout`, especially with fast network connections to Git remotes. +Since [`Bender.lock`](../lockfile.md) uniquely identifies the state of all dependencies, it is theoretically possible to cache the `.bender` directory to speed up pipelines. However, for most projects, the overhead of managing the cache (uploading/downloading) might outweigh the time saved by `bender checkout`, especially with fast network connections to Git remotes. Caching is only recommended for projects with exceptionally large dependency trees or slow network access. @@ -80,4 +80,4 @@ cache: - .bender/ ``` -> **Note on Cache Keys:** We use the hash of `Bender.lock` as the cache key. This ensures the cache is only reused when the dependencies haven't changed. +> **Note on Cache Keys:** We use the hash of [`Bender.lock`](../lockfile.md) as the cache key. This ensures the cache is only reused when the dependencies haven't changed. diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md index 34516c54..4da83615 100644 --- a/book/src/workflow/dependencies.md +++ b/book/src/workflow/dependencies.md @@ -11,9 +11,9 @@ bender update In case other dependencies already exist and you do not want to re-resolve these, you can add the `--new-only` flag to the update command. -> **Note:** On update, bender creates or modifies the [`Bender.lock` lockfile](./lockfile.md), which keeps track of the currently selected dependency versions. +> **Note:** On update, bender creates or modifies the [`Bender.lock`](../lockfile.md), which keeps track of the currently selected dependency versions. -> **Note:** Most bender commands will automatically run an update if no `Bender.lock` lockfile is found. +> **Note:** Most bender commands will automatically run an update if no [`Bender.lock`](../lockfile.md) is found. ## Updating dependencies Similar to when adding new dependencies, updating existing dependencies to more recent versions is also done with the `update` command. @@ -34,13 +34,13 @@ bender update --recursive ## Checking out Dependencies -While `bender update` resolves versions and updates the lockfile, it does not necessarily download all the source code. To ensure all dependencies are locally available, use: +While `bender update` resolves versions and updates the [`Bender.lock`](../lockfile.md), it does not necessarily download all the source code. To ensure all dependencies are locally available, use: ```sh bender checkout ``` -Bender will download the exact revisions specified in `Bender.lock`. This command is safe to run multiple times; it will only download missing packages or update those that have changed in the lockfile. +Bender will download the exact revisions specified in [`Bender.lock`](../lockfile.md). This command is safe to run multiple times; it will only download missing packages or update those that have changed in the [`Bender.lock`](../lockfile.md). > **Note:** Many other commands (like `sources` or `script`) will automatically trigger a checkout if they detect missing dependencies. diff --git a/book/src/workflow/init.md b/book/src/workflow/init.md index 7e84d802..92558964 100644 --- a/book/src/workflow/init.md +++ b/book/src/workflow/init.md @@ -8,14 +8,14 @@ bender init ## How it Works -Bender attempts to intelligently pre-fill your `Bender.yml` with the following information: +Bender attempts to intelligently pre-fill your [`Bender.yml`](../manifest.md) with the following information: - **Package Name:** Set to the name of the current working directory. - **Authors:** Pulled automatically from your global Git configuration (`git config user.name` and `git config user.email`). ## The Generated Manifest -The command creates a `Bender.yml` file with a structure similar to this: +The command creates a [`Bender.yml`](../manifest.md) file with a structure similar to this: ```yaml package: diff --git a/book/src/workflow/package_dev.md b/book/src/workflow/package_dev.md index ba0ee2d4..94e3bd22 100644 --- a/book/src/workflow/package_dev.md +++ b/book/src/workflow/package_dev.md @@ -13,7 +13,7 @@ bender clone By default, the package is checked out into a `working_dir` folder (you can change this with `-p/--path`). Bender automatically: 1. Performs a `git clone` of the dependency into that folder. -2. Adds a `path` override to your **`Bender.local`** file. +2. Adds a `path` override to your [`Bender.local`](../local.md) file. Now, any changes you make in that folder are immediately reflected in your top-level project when you run Bender commands. @@ -30,17 +30,17 @@ bender snapshot Bender will: 1. Detect all dependencies that are currently overridden by a local path. 2. Check the current Git commit hash of those local repositories. -3. Update **`Bender.local`** to use a `git` override with that specific `rev` (commit hash). -4. Automatically update **`Bender.lock`** to include these exact revisions. +3. Update [`Bender.local`](../local.md) to use a `git` override with that specific `rev` (commit hash). +4. Automatically update [`Bender.lock`](../lockfile.md) to include these exact revisions. **Why use Snapshot?** -The main benefit of a snapshot is portability. Because the lockfile is updated with the specific commit hashes, you can commit `Bender.lock` and share it with colleagues or run it in CI. The other environments will download the exact revisions you were working on from the Git remotes, without needing access to your local development paths. +The main benefit of a snapshot is portability. Because the lockfile is updated with the specific commit hashes, you can commit [`Bender.lock`](../lockfile.md) and share it with colleagues or run it in CI. The other environments will download the exact revisions you were working on from the Git remotes, without needing access to your local development paths. ## Finalizing Changes Once your changes are stable and you are ready to "release" them: 1. **Tag the Dependency:** Push your changes to the remote repository and create a new version tag (e.g., `v1.2.2`). -2. **Update Manifest:** Update the version requirement in your `Bender.yml` to include the new version. -3. **Clean Up:** Remove the local overrides from your `Bender.local` file. -4. **Resolve:** Run `bender update` to re-resolve the dependency tree and update `Bender.lock` to point to the new official version. +2. **Update Manifest:** Update the version requirement in your [`Bender.yml`](../manifest.md) to include the new version. +3. **Clean Up:** Remove the local overrides from your [`Bender.local`](../local.md) file. +4. **Resolve:** Run `bender update` to re-resolve the dependency tree and update [`Bender.lock`](../lockfile.md) to point to the new official version. diff --git a/book/src/workflow/vendor.md b/book/src/workflow/vendor.md index a11513e0..c52e681b 100644 --- a/book/src/workflow/vendor.md +++ b/book/src/workflow/vendor.md @@ -6,7 +6,7 @@ This flow is heavily inspired by the `vendor.py` script used in the [OpenTitan]( ## Configuration -Vendorized packages are defined in the `vendor_package` section of your `Bender.yml`: +Vendorized packages are defined in the `vendor_package` section of your [`Bender.yml`](../manifest.md): ```yaml vendor_package: @@ -86,6 +86,6 @@ If you want to contribute your fix back to the upstream repository: ## When to use Vendor? Use the vendor flow when: -- The external IP does not have its own `Bender.yml`. +- The external IP does not have its own [`Bender.yml`](../manifest.md). - You need to include only a small subset of a massive repository. - You must maintain local modifications (bug fixes or tool workarounds) that haven't been merged upstream yet. From 2052cfe6c8b2400015688072b91c9a0e9efd454e Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Thu, 30 Apr 2026 17:50:14 +0200 Subject: [PATCH 40/47] book: add env variable information to configuration section --- book/src/configuration.md | 70 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 8128b34b..c1064431 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -1,44 +1,55 @@ # Global and Local Configuration -Bender uses a cascading configuration system that allows you to set global defaults while still providing the flexibility to override settings for specific projects or local environments. +Bender uses a flexible configuration system that combines files, environment variables, and command-line flags. -## Configuration Files +## Configuration Methods and Precedence -Bender looks for configuration files in the following order, merging them as they are encountered: +When resolving a configuration setting, Bender follows this order of precedence (highest to lowest): -1. **System-wide:** `/etc/bender.yml` -2. **User-specific:** `$HOME/.config/bender.yml` (or the equivalent on your OS) -3. **Project-specific (checked in):** `.bender.yml` in your project root. -4. **Local Workspace (ignored):** [`Bender.local`](./local.md) in your project root. +1. **Command-Line Flags:** Explicitly passed arguments (e.g., `--git-throttle 8`). +2. **Environment Variables:** System-level variables (e.g., `BENDER_GIT_THROTTLE=8`). +3. **Configuration Files:** Settings loaded from YAML files. These files are merged, with lower-level files overwriting higher-level ones: + - [`Bender.local`](./local.md) (Local workspace, ignored by Git) + - `.bender.yml` (Project-specific, checked into Git) + - `$HOME/.config/bender.yml` (User-specific) + - `/etc/bender.yml` (System-wide) -The contents of these files are merged such that a configuration in a lower-level file (like [`Bender.local`](./local.md)) will overwrite a configuration in a higher-level file (like `/etc/bender.yml`). +### Path Substitution +On Unix-like systems, paths within configuration files can use environment variables (e.g., `$HOME` or `${VAR}`). These will be automatically substituted when the configuration is loaded. -## Configuration Fields +--- -The configuration files use the YAML format and support the following fields: +## Configuration Fields ### `database` The directory where Bender stores cloned and checked-out dependencies. +- **Config Key:** `database` - **Default:** `.bender` in the project root. - **Example:** `database: /var/cache/bender_dependencies` ### `git` The command or path used to invoke Git. +- **Config Key:** `git` - **Default:** `git` - **Example:** `git: /usr/local/bin/git-wrapper.sh` ### `git_throttle` The maximum number of concurrent Git operations. +- **Config Key:** `git_throttle` +- **CLI Flag:** `--git-throttle` +- **Env Var:** `BENDER_GIT_THROTTLE` - **Default:** `4` -- **Example:** `git_throttle: 2` +- **Example:** `git_throttle: 8` ### `git_lfs` -Enable or disable Git Large File Storage (LFS) support. +Enable or disable Git Large File Storage (LFS) support. Requires `git-lfs` to be installed on the system. +- **Config Key:** `git_lfs` - **Default:** `true` - **Example:** `git_lfs: false` ### `overrides` Forces specific dependencies to use a particular version or local path. This is primarily used in [`Bender.local`](./local.md) for development. +- **Config Key:** `overrides` - **Example:** ```yaml overrides: @@ -47,6 +58,41 @@ Forces specific dependencies to use a particular version or local path. This is ### `plugins` Auxiliary plugin dependencies that are loaded for every package. These allow you to provide additional Bender subcommands across your entire environment. +- **Config Key:** `plugins` + +--- + +## Global CLI Options + +The following options can be set via command-line flags or environment variables, but do not have a corresponding key in the configuration files. + +### `dir` +Sets a custom root working directory. This directory is used as the starting point to search for `Bender.yml` and configuration files. It also determines the default location of the `database`. +- **CLI Flag:** `-d`, `--dir` +- **Env Var:** `BENDER_DIR` +- **Default:** Current working directory. + +### `local` +Disables fetching of remotes. Useful for working on air-gapped computers or when you want to ensure no network operations occur. +- **CLI Flag:** `--local` +- **Env Var:** `BENDER_LOCAL` + +### `verbose` +Increases logging verbosity. +- **CLI Flag:** `-v`, `-vv`, `-vvv` (info, debug, trace) +- **Env Var:** `BENDER_VERBOSE` (set to `1`, `2`, or `3`) + +### `no_progress` +Disables interactive progress bars. +- **CLI Flag:** `--no-progress` +- **Env Var:** `BENDER_NO_PROGRESS` + +### `suppress` +Suppresses specific warnings. +- **CLI Flag:** `--suppress ` (can be used multiple times) +- **Env Var:** `BENDER_SUPPRESS_WARNINGS` (comma-separated list) + +--- ## Usage Example From 732987fa7a6cb679bbdcbb4c04b01f4c6e950bdf Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 18 May 2026 15:32:24 +0200 Subject: [PATCH 41/47] book: Extend to address review comments --- book/src/configuration.md | 2 +- book/src/dependencies.md | 33 ++++++++++++++++++++++++++++--- book/src/local.md | 6 ++++++ book/src/workflow/ci.md | 16 +++++++++++++++ book/src/workflow/dependencies.md | 26 +++++++++++++++++++++--- 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index c1064431..c1a415d5 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -1,6 +1,6 @@ # Global and Local Configuration -Bender uses a flexible configuration system that combines files, environment variables, and command-line flags. +Bender uses a flexible configuration system that combines files, environment variables, and command-line flags. This page documents the configuration fields and their resolution order; for the role of [`Bender.local`](./local.md) within this system and its use as a per-workspace override file, see [Local Configuration](./local.md). ## Configuration Methods and Precedence diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 365cfb5d..8cd0246e 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -9,16 +9,23 @@ Dependencies are defined in the `dependencies` section of your [`Bender.yml`](./ ### Git Dependencies Git is the primary way to distribute Bender packages. You can specify them in two ways: -> **Important:** The shorthand notation (e.g., `common_cells: "1.21.0"`) is only available if you have defined at least one [remote](#remotes) in your manifest. If no remote is specified, you must use the full `git` URL (see [revision](#revision-based)) - #### Version-based (Recommended) Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges: +```yaml +dependencies: + common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: "1.21.0" } + axi: { git: "https://github.com/pulp-platform/axi.git", version: ">=0.23.0, <0.26.0" } +``` + +If you have defined a [remote](#remotes) in your manifest, you can use the shorthand notation instead: + ```yaml dependencies: common_cells: "1.21.0" axi: { version: ">=0.23.0, <0.26.0" } ``` + > **Note:** Bender only recognizes Git tags that follow the `vX.Y.Z` format (e.g., `v1.2.1`). #### Revision-based @@ -65,6 +72,26 @@ dependencies: cva6: { version: "4.0.0", remote: openhw } # Explicitly uses 'openhw' ``` +### Differing Repository Name + +By default, Bender appends the dependency's local name to the remote URL when resolving the Git URL. If the upstream repository is named differently from how you want to refer to the dependency locally, use `upstream_name`: + +```yaml +remotes: + pulp: "https://github.com/pulp-platform" + +dependencies: + cells: { version: "1.21.0", upstream_name: "common_cells" } + # Resolves to https://github.com/pulp-platform/common_cells.git +``` + +You can also embed the dependency name explicitly in the remote URL using the `{}` placeholder, which is useful for non-trivial URL patterns: + +```yaml +remotes: + pulp: "https://gitlab.example.com/scm/{}.git" +``` + ## Targets Dependencies can be conditionally included or configured using targets. For details on how to use target expressions or pass targets to dependencies, see the [Targets](./targets.md) documentation. @@ -75,7 +102,7 @@ Bender automatically detects if a dependency uses **Git Large File Storage (LFS) ## Submodules -TODO +If a dependency contains a `.gitmodules` file, Bender will automatically initialize and update its Git submodules recursively after checkout. No additional configuration is required. ## Version Resolution and the Lockfile diff --git a/book/src/local.md b/book/src/local.md index c1fba492..df291da0 100644 --- a/book/src/local.md +++ b/book/src/local.md @@ -2,10 +2,14 @@ `Bender.local` is an optional, user-specific configuration file used to override the project's default settings. Its primary purpose is to allow local development of dependencies without modifying the shared [`Bender.yml`](./manifest.md) or [`Bender.lock`](./lockfile.md). +`Bender.local` is one entry in Bender's configuration file chain. See [Configuration](./configuration.md) for the full precedence order, the list of available fields, and the equivalent environment variables and CLI flags. + ## Overriding Dependencies The most common use for `Bender.local` is the `overrides` section. This forces Bender to use a specific version or a local path for a dependency, regardless of what the manifest requires. +Entries in `overrides` use the same syntax as entries in the `dependencies` section of [`Bender.yml`](./manifest.md) (see [Dependencies](./dependencies.md)), with the exception that target expressions are not supported. + ```yaml overrides: # Force a local path for 'common_cells' @@ -17,6 +21,8 @@ overrides: When an override is present, Bender will prioritize it over any other version resolution. +> **Note:** `overrides` only replace dependencies that already exist somewhere in the resolved dependency tree. They cannot be used to introduce new dependencies that are not pulled in by any package's [`Bender.yml`](./manifest.md). + ## Management `Bender.local` can be managed both manually and automatically. Several Bender commands manage it for you during the development process: diff --git a/book/src/workflow/ci.md b/book/src/workflow/ci.md index 0dbc5531..9c55307e 100644 --- a/book/src/workflow/ci.md +++ b/book/src/workflow/ci.md @@ -81,3 +81,19 @@ cache: ``` > **Note on Cache Keys:** We use the hash of [`Bender.lock`](../lockfile.md) as the cache key. This ensures the cache is only reused when the dependencies haven't changed. + +## Sharing the Database Across Runs and Projects + +When jobs run on a persistent runner, the `database` directory (where Bender stores cloned repositories) can be shared across CI runs and even across projects to drastically reduce fetch times and disk usage. + +To enable this, point Bender at a shared location via a [`Bender.local`](../local.md) file (for example placed in a parent directory of the project so it is picked up automatically): + +```yaml +database: /var/cache/bender_shared +``` + +This way, every job that runs in the runner reuses the already-fetched Git data instead of re-cloning from scratch. See [Configuration](../configuration.md) for more on the `database` setting. + +> **Caveats:** +> - **Checkout collisions:** When sharing the database, checkouts from different projects can collide if the top-level [`Bender.yml`](../manifest.md) does not specify a project-specific `workspace.checkout_dir`. Make sure each top-level project sets its own `checkout_dir` so that checkouts remain isolated even when the database is shared. +> - **Concurrent runs:** Bender does not currently take a lock before performing Git operations on the shared database. Concurrent jobs that touch the same database may occasionally fail with Git errors. This is unlikely, but worth keeping in mind when sizing parallelism. diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md index 4da83615..0bda6135 100644 --- a/book/src/workflow/dependencies.md +++ b/book/src/workflow/dependencies.md @@ -1,9 +1,9 @@ # Adding and Updating Dependencies -As working with dependencies is one of bender's main features, there are a few commands to ensure functionality and assist with understanding the dependency structure. +As working with dependencies is one of bender's main features, there are a few commands to ensure functionality and assist with understanding the dependency structure. For background on how dependencies are declared in the [`Bender.yml`](../manifest.md) manifest, see [Dependencies](../dependencies.md). ## New dependencies -Once new dependencies are added to the manifest, bender needs to first be made aware of their existence. Otherwise, the internally used dependency tree will be incorrect or mismatched, and some commands will not work correctly, returning an error. To update dependencies, run the following command: +Once new dependencies are added to the [manifest](../manifest.md), bender needs to first be made aware of their existence. Otherwise, the internally used dependency tree will be incorrect or mismatched, and some commands will not work correctly, returning an error. To update dependencies, run the following command: ```sh bender update @@ -18,6 +18,8 @@ In case other dependencies already exist and you do not want to re-resolve these ## Updating dependencies Similar to when adding new dependencies, updating existing dependencies to more recent versions is also done with the `update` command. +During an update, Bender picks the highest SemVer-compatible version and a unique revision that simultaneously satisfies the constraints of every package in the dependency tree. If the requirements conflict and no single revision satisfies them, Bender will prompt you to choose how to resolve the conflict. See [Dependencies](../dependencies.md) for more on version resolution. + ### Single Dependency Update You don't always have to update your entire dependency tree. To update only a specific package, provide its name: @@ -62,7 +64,7 @@ If you need to know where a specific dependency is stored (e.g., to point an ext bender path ``` -This will output the absolute path to the package's root directory. +This will output the absolute path to the dependency's checkout directory. If the package has not yet been checked out, `bender path` will check it out first. ## Checking Usage (`parents`) @@ -73,3 +75,21 @@ bender parents ``` This will show you all packages in your tree that depend on `` and what version constraints they have placed on it. + +## Auditing the Dependency Tree (`audit`) + +To get a quick overview of the state of your dependencies, including outdated packages, version conflicts, and dependencies pinned to a Git hash rather than a SemVer version, use: + +```sh +bender audit +``` + +The output classifies each package as one of: +- **Up-to-date:** the resolved version is the highest available. +- **Auto-update:** a newer version exists that still satisfies all constraints; can be picked up by running `bender update`. +- **Update:** a newer version exists but is outside the current SemVer constraints; requires manual updating of constraints in [`Bender.yml`](../manifest.md). +- **Hash:** the dependency is pinned to a specific Git revision rather than a SemVer version. +- **Path:** the dependency points to a local directory. +- **Conflict:** the dependency tree has incompatible version requirements or remote URLs — use `bender parents ` to investigate. + +Pass `--only-update` to show only packages that have a possible update, or `-f/--fetch` to force a re-fetch of all Git remotes before auditing. From 53e41d02451b74110266bdfaf9ccbccbf919e109 Mon Sep 17 00:00:00 2001 From: Tim Fischer Date: Mon, 18 May 2026 18:22:37 +0200 Subject: [PATCH 42/47] ci(docs): fix mdbook installation --- .github/workflows/docs.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 98953e3c..0d0886d9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,10 +22,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install mdBook - uses: cargo-bins/cargo-binstall@v1 - with: - packages: mdbook + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v2 - name: Build book run: mdbook build book/ From 2a791830b087f5e882c787ba2532e8835f13092a Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 18 May 2026 18:51:39 +0200 Subject: [PATCH 43/47] book: document Homebrew, Nix, and AUR install paths Replace the Linux-only "Linux Distributions" subsection with a broader "Package Managers" section covering the existing Homebrew formula, the nixpkgs package and the repo's own flake, and the AUR package. Co-Authored-By: Claude Opus 4.7 (1M context) --- book/src/installation.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/book/src/installation.md b/book/src/installation.md index e24a5f15..f5e3bd9d 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -39,11 +39,35 @@ If you have cloned the repository, you can install the local version by running cargo install --path . ``` -## Linux Distributions +## Package Managers -Some Linux distributions provide Bender through their package managers: +Bender is also available through several third-party package managers: -- **ArchLinux:** [Bender on the AUR](https://aur.archlinux.org/packages/bender) +### Homebrew (macOS / Linux) +```sh +brew install bender +``` +See the [Homebrew formula](https://formulae.brew.sh/formula/bender) for more details. + +### Nix +Bender is packaged in [nixpkgs](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/be/bender/package.nix): +```sh +nix-env -iA nixpkgs.bender +# or, on a flake-enabled system: +nix profile install nixpkgs#bender +``` +The repository also ships its own [`flake.nix`](https://github.com/pulp-platform/bender/blob/master/flake.nix), so you can run Bender directly from the latest source without installing: +```sh +nix run github:pulp-platform/bender +``` + +### Arch Linux (AUR) +```sh +yay -S bender # or any other AUR helper +``` +See [Bender on the AUR](https://aur.archlinux.org/packages/bender) for the package page. + +> **Note:** Third-party packages may lag behind the latest [GitHub release](https://github.com/pulp-platform/bender/releases). For the most recent version, prefer the shell installer or `cargo install`. ## Verifying Installation From 7715e36a59603dabd01aee0f8038b2db2a4922a0 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Mon, 18 May 2026 19:23:23 +0200 Subject: [PATCH 44/47] book: address further PR review comments Tweak principles to avoid enumerating EDA tools, note that Bender.yml should sit at the Git repo root, clarify group-level include_dirs scope, document `bender script template_json`, link directly to the lowRISC `vendor.py`, and call out that vendored files still need to be listed under `sources`. Co-Authored-By: Claude Opus 4.7 (1M context) --- book/src/manifest.md | 2 ++ book/src/principles.md | 2 +- book/src/sources.md | 2 +- book/src/workflow/scripts.md | 8 ++++++++ book/src/workflow/vendor.md | 4 +++- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/book/src/manifest.md b/book/src/manifest.md index 69b69925..1347c933 100644 --- a/book/src/manifest.md +++ b/book/src/manifest.md @@ -2,6 +2,8 @@ The package manifest describes the package, its metadata, its dependencies, and its source files. All paths in the manifest may be relative, in which case they are understood to be relative to the directory that contains the manifest. A manifest is required for each bender package. +> **Note:** The [`Bender.yml`](./manifest.md) should be located at the root of the Git repository. Git-based dependency resolution currently relies on this assumption, and placing the manifest in a subdirectory of the repository may cause dependencies to not resolve correctly. + It is strongly recommended to start the Manifest file with a license header (open-source or proprietary) as a comment. This provides clarity on the project's usage. ```yaml diff --git a/book/src/principles.md b/book/src/principles.md index 4567699f..5fcebd17 100644 --- a/book/src/principles.md +++ b/book/src/principles.md @@ -4,7 +4,7 @@ Bender was created to solve the challenges of managing large-scale hardware desi ## 1. Modular and Opt-in Bender is designed to be a "pre-build" tool. It does not replace your EDA tools (synthesis, simulation, formal); it helps orchestrate them. -- **Tool Agnostic:** Whether you use Vivado, Questa, VCS, or Verilator, Bender provides the necessary file lists and configurations. +- **Tool Agnostic:** Bender provides file lists and tool-specific scripts for a wide range of simulation, synthesis, and implementation tools (see [Generating Tool Scripts](./workflow/scripts.md)). - **Flexible Layout:** We do not enforce a strict directory structure. As long as a [`Bender.yml`](./manifest.md) is present, Bender can manage it. ## 2. Reproducibility as Ground Truth diff --git a/book/src/sources.md b/book/src/sources.md index ebcdc702..a564e094 100644 --- a/book/src/sources.md +++ b/book/src/sources.md @@ -31,7 +31,7 @@ sources: - src/rtl/top.sv ``` -- **include_dirs**: Paths added to the `+incdir+` flag during compilation. +- **include_dirs**: Paths added to the `+incdir+` flag during compilation. These directories apply only to the files in this source group and any nested child groups; they are generally *not* visible to sibling groups or to dependents of the package. To expose headers to other packages, use [`export_include_dirs`](#exported-include-directories) instead. - **defines**: Preprocessor macros added via `+define+`. - **target**: A [target expression](./targets.md) that determines if this entire group is included in the current flow. diff --git a/book/src/workflow/scripts.md b/book/src/workflow/scripts.md index f93d4b53..d06a359e 100644 --- a/book/src/workflow/scripts.md +++ b/book/src/workflow/scripts.md @@ -84,3 +84,11 @@ Bender uses the [Tera](https://keats.github.io/tera/) templating engine for its ```sh bender script template --template my_custom_format.tera > output.txt ``` + +To help develop a custom template, you can inspect the JSON structure that Bender passes to the template engine using: + +```sh +bender script template_json +``` + +This prints the same data that would be exposed to your `.tera` template, making it easy to discover available fields. diff --git a/book/src/workflow/vendor.md b/book/src/workflow/vendor.md index c52e681b..99e67ba2 100644 --- a/book/src/workflow/vendor.md +++ b/book/src/workflow/vendor.md @@ -2,7 +2,7 @@ Bender's `vendor` command allows you to manage external dependencies that aren't natively packaged for Bender. It works by copying a subset of files from an upstream Git repository into a local directory within your project, allowing you to track changes and maintain local patches. -This flow is heavily inspired by the `vendor.py` script used in the [OpenTitan](https://opentitan.org/) project. +This flow is heavily inspired by the [`vendor.py`](https://github.com/lowRISC/opentitan/blob/master/util/vendor.py) script used in the [OpenTitan](https://opentitan.org/) project. ## Configuration @@ -45,6 +45,8 @@ bender vendor init Bender clones the upstream repository, filters the files based on your rules, and copies them to your project. If a `patch_dir` is specified, any existing patches are applied automatically. +> **Important:** Vendored files are not automatically picked up as compilation sources. After `bender vendor init`, you still need to list the relevant files (or globs matching them) in the [`sources`](../sources.md) section of your [`Bender.yml`](../manifest.md) for them to participate in script generation and source collection. + ### 2. Make Local Changes and Diff Assume you need to fix a bug in `deps/my_ip/src/top.sv`. You edit the file directly in your workspace. You can see how your local code differs from the upstream source (plus existing patches) by running: From e4ece9e02d0bfcc1d74902aef77003650f10de7d Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 19 May 2026 08:43:41 +0200 Subject: [PATCH 45/47] book: backfill content carried over from the old README Restore details that were present in the pre-book README but not yet in the rendered book: full `bender pickle` subcommand reference, concrete Git LFS warning codes (W26/W27), the rule that dependency target filters do not affect lockfile resolution, target-conditional `include_dirs` and `defines` syntax, recommended `test`/`rtl`/`gate` target conventions, the deprecation status of `plugins` in the configuration file, and a link to the Cargo dependency-spec reference alongside the existing semver crate link. Co-Authored-By: Claude Opus 4.7 (1M context) --- book/src/commands.md | 28 ++++++++++++++++++++++++++++ book/src/configuration.md | 4 +++- book/src/dependencies.md | 11 +++++++++-- book/src/sources.md | 21 +++++++++++++++++++++ book/src/targets.md | 10 ++++++++++ 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/book/src/commands.md b/book/src/commands.md index d4c176b9..875748c6 100644 --- a/book/src/commands.md +++ b/book/src/commands.md @@ -67,6 +67,34 @@ Supported formats: Furthermore, similar flags to the `sources` command exist. +## `pickle` --- Parse and rewrite SystemVerilog sources with Slang + +The `bender pickle` command parses SystemVerilog sources with [Slang](https://github.com/MikePopoloski/slang) and prints the resulting source again. It supports optional renaming and trimming of unreachable files for specified top modules. + +This command is only available when Bender is built with Slang support (the default; pass `--all-features` if building without defaults). + +Useful options: +- `--top `: Trim output to files reachable from one or more top modules. +- `--prefix ` / `--suffix `: Add a prefix and/or suffix to renamed symbols. Both require `--expand-macros`. +- `--exclude-rename `: Exclude specific symbols from renaming. +- `--ast-json`: Emit AST JSON instead of source code. +- `--expand-macros`, `--strip-comments`, `--squash-newlines`: Control output formatting. +- `-I `, `-D `: Add extra include directories and preprocessor defines beyond those declared in the manifest. +- `-o/--output `: Write to a file instead of standard output. + +The `-t/--target`, `-p/--package`, `--exclude`, and `--no-deps` flags work like for [`sources`](#sources-list-source-files). + +Examples: + +```sh +# Keep only files reachable from top module `my_top`. +bender pickle --top my_top + +# Rename symbols, but keep selected names unchanged. +bender pickle --top my_top --expand-macros --prefix p_ --suffix _s --exclude-rename my_top +``` + + ## `update` --- Re-resolve dependencies Whenever you update the list of dependencies, you likely have to run `bender update` to re-resolve the dependency versions, and recreate the [`Bender.lock`](./lockfile.md) file. diff --git a/book/src/configuration.md b/book/src/configuration.md index c1a415d5..5f0cc4ca 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -57,9 +57,11 @@ Forces specific dependencies to use a particular version or local path. This is ``` ### `plugins` -Auxiliary plugin dependencies that are loaded for every package. These allow you to provide additional Bender subcommands across your entire environment. +Auxiliary plugin dependencies that are loaded for every package. These allow you to provide additional Bender subcommands across your entire environment. The entry uses the same format as the `dependencies` section of a manifest. - **Config Key:** `plugins` +> **Deprecated:** Configuring `plugins` from the configuration file is deprecated and may be removed in a future release. Prefer declaring `plugins` in the package manifest ([`Bender.yml`](./manifest.md)). + --- ## Global CLI Options diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 8cd0246e..413e417b 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -10,7 +10,7 @@ Dependencies are defined in the `dependencies` section of your [`Bender.yml`](./ Git is the primary way to distribute Bender packages. You can specify them in two ways: #### Version-based (Recommended) -Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges: +Bender uses [Semantic Versioning (SemVer)](https://semver.org/) to find the best compatible version. You can use [SemVer operators](https://docs.rs/semver/latest/semver/enum.Op.html) to specify version ranges — the syntax matches Cargo's, see the [Cargo dependency reference](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html) for a more accessible overview: ```yaml dependencies: @@ -96,9 +96,16 @@ remotes: Dependencies can be conditionally included or configured using targets. For details on how to use target expressions or pass targets to dependencies, see the [Targets](./targets.md) documentation. +> **Note:** A `target` on a dependency only filters that dependency out of *source listings and generated scripts*. It does **not** affect dependency resolution: every dependency declared in [`Bender.yml`](./manifest.md) is still resolved and recorded in [`Bender.lock`](./lockfile.md) regardless of which targets are active. + ## Git LFS Support -Bender automatically detects if a dependency uses **Git Large File Storage (LFS)**. If `git-lfs` is installed on your system, Bender will automatically pull the required large files during the checkout process. +Bender detects whether a dependency uses **Git Large File Storage (LFS)** via its `.gitattributes` and reacts as follows: + +- If LFS is detected and `git-lfs` is installed, Bender configures LFS and pulls the required files automatically. +- If LFS is detected but `git-lfs` is **not** installed, Bender emits warning `W26` and continues the checkout. You may end up with pointer files instead of the actual large files, which can cause downstream build failures — install `git-lfs` to resolve this. +- If LFS is disabled in your configuration (`git_lfs: false`) but the dependency appears to use LFS, Bender emits warning `W27`. +- If the repository does not use LFS, Bender skips LFS operations entirely. ## Submodules diff --git a/book/src/sources.md b/book/src/sources.md index a564e094..da7c7c22 100644 --- a/book/src/sources.md +++ b/book/src/sources.md @@ -35,6 +35,27 @@ sources: - **defines**: Preprocessor macros added via `+define+`. - **target**: A [target expression](./targets.md) that determines if this entire group is included in the current flow. +### Target-Conditional Include Dirs and Defines + +Individual entries in `include_dirs` and `defines` can also be filtered by target. Use the `{ target: , dir: }` form for include directories, and `{ target: , value: }` for define values: + +```yaml +sources: + - include_dirs: + - include + # Only added when the `fpga` target is active + - { target: fpga, dir: include/fpga } + defines: + # Static define + BIT_WIDTH: 64 + # Only set when the `test` target is active + TEST_COMPONENTS: { target: any(test, regression_test), value: "all" } + files: + - src/rtl/top.sv +``` + +The same `{ target: , dir: }` form is accepted in [`export_include_dirs`](#exported-include-directories). + ## Glob Patterns Bender supports glob patterns for automatically including multiple files without listing them individually: diff --git a/book/src/targets.md b/book/src/targets.md index c5a86bf8..7b11cb37 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -127,6 +127,16 @@ The `bender script` command activates the following targets based on the chosen - **RTL:** If you use the `--assume-rtl` flag, Bender will automatically assign the `rtl` target to any source group that does not have an explicit target specification. - **ASIC:** While `asic` is a common convention, it is **not** set automatically by Bender. It should be manually activated via `-t asic` when needed. +### Recommended Conventions + +Bender does not enforce these, but the following user-defined targets are widely used across PULP projects and are a good default for new packages: + +- **`test`** — testbench code and verification IP, kept out of synthesis flows. +- **`rtl`** — synthesizable RTL code. +- **`gate`** — gate-level netlists, used in post-synthesis simulation and timing flows. + +Similarly, `asic` vs. `fpga` is the conventional way to swap between technology-specific implementations. + ## Activating Targets via CLI Use the `-t` or `--target` flag with Bender commands: From ad96cac8adae619b9eb74cf1346df4afad9756fb Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 19 May 2026 09:23:37 +0200 Subject: [PATCH 46/47] book: rewrite principles page to track the original README Drop the marketing-style "Decentralized and Secure" / "Local-First Development" framings and the four-principle expansion. Restore the original README structure of two core principles ("be as opt-in as possible", "allow for reproducible builds") followed by the three feature tiers, with the NDA / private-repo motivation folded back into the dependency-management tier where it originally lived. Co-Authored-By: Claude Opus 4.7 (1M context) --- book/src/principles.md | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/book/src/principles.md b/book/src/principles.md index 5fcebd17..0c56481b 100644 --- a/book/src/principles.md +++ b/book/src/principles.md @@ -1,44 +1,44 @@ # Principles -Bender was created to solve the challenges of managing large-scale hardware designs with complex, nested dependencies. It is built around four core principles that guide its development and usage. +Bender is built around two core principles, supported by three feature tiers that build on each other. -## 1. Modular and Opt-in -Bender is designed to be a "pre-build" tool. It does not replace your EDA tools (synthesis, simulation, formal); it helps orchestrate them. -- **Tool Agnostic:** Bender provides file lists and tool-specific scripts for a wide range of simulation, synthesis, and implementation tools (see [Generating Tool Scripts](./workflow/scripts.md)). -- **Flexible Layout:** We do not enforce a strict directory structure. As long as a [`Bender.yml`](./manifest.md) is present, Bender can manage it. +## Be as opt-in as possible -## 2. Reproducibility as Ground Truth -In hardware design, knowing exactly what was taped out or simulated is critical. -- **Precise Locking:** The [`Bender.lock`](./lockfile.md) file tracks every dependency down to its specific Git commit hash. -- **Immutable States:** By committing the lockfile, you ensure that everyone on the team—and every CI runner—is using identical source code. +Bender does not assume a specific EDA tool, workflow, or directory layout beyond a few key files. All features are designed to be modular, so they can be picked up individually and integrated into an existing flow. As long as a [`Bender.yml`](./manifest.md) is present, Bender can manage the package. -## 3. Decentralized and Secure -Unlike many software package managers (like npm or cargo), Bender does not rely on a central, public registry. -- **Git-Centric:** Dependencies are resolved directly from Git repositories. -- **NDA Friendly:** This allows projects to use internal, private repositories or even local paths, ensuring sensitive IP remains protected and within your infrastructure. +## Allow for reproducible builds -## 4. Local-First Development -Hardware development often requires modifying an IP and its dependencies simultaneously. -- **Zero-Friction Overrides:** The [`Bender.local`](./local.md) mechanism allows you to temporarily swap a remote dependency for a local working copy without changing the project's official manifest. -- **Seamless Snapshots:** Captured states can be shared or moved to CI easily, bridging the gap between local development and official releases. +Bender maintains a precise [lockfile](./lockfile.md) which records the exact Git revision each dependency was resolved to. Committing this file alongside the manifest lets the exact source state of a package — for example at a tape-out or a release — be reconstructed after the fact. --- -## The Three Tiers of Bender +## Feature Tiers -Bender's functionality can be categorized into three distinct tiers, each building upon the other: +Bender's functionality is organized into three tiers, each building on the previous one. A package only needs to opt into the tiers it uses. ### Tier 1: Source Collection -At its simplest level, Bender is a tool for collecting and organizing HDL source files. -- **Ordering:** Maintains the required order across source files (e.g., packages before modules). -- **Organization:** Allows files to be organized into recursive groups with specific targets, defines, and include directories. + +Collect and organize the HDL source files of a hardware IP: + +- Maintain the required order across files, e.g. for package declarations before their use. +- Stay language-agnostic across SystemVerilog and VHDL. +- Allow files to be organized into recursive groups. +- Track defines and include directories individually for each group. + +See [Sources](./sources.md) for the manifest format. ### Tier 2: Dependency Management -Bender resolves and manages transitive dependencies between different hardware IPs. -- **Version Resolution:** Enforces Semantic Versioning (SemVer) to ensure compatibility. -- **Lifecycle Management:** Automates the fetching, checking out, and updating of external packages. + +Manage other packages an IP depends on and provide a local checkout of their sources: + +- Support transitive dependencies. +- Resolve dependencies directly from Git rather than a central package registry. Projects containing IP under NDA can therefore use private repositories or local paths without exposing them. +- Use [Semantic Versioning](https://semver.org/) to constrain compatible revisions. + +See [Dependencies](./dependencies.md) for details. ### Tier 3: Tool Script Generation -The final tier provides the ability to generate the actual scripts and file lists used by vendor tools. -- **Automation:** Eliminates the need to manually maintain tool-specific file lists (like `.f` files or TCL scripts). -- **Consistency:** Ensures that the exact same set of sources is used across all stages of the design flow. + +Generate source file listings and compilation scripts for various EDA tools, so the same set of resolved sources can be fed into simulation, synthesis, and downstream flows without manually maintaining tool-specific file lists. + +See [Generating Tool Scripts](./workflow/scripts.md) for the supported formats and options. From 88bf786cb1e006d1a8c7de0e4058376dc76ff347 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Tue, 19 May 2026 09:44:40 +0200 Subject: [PATCH 47/47] book: comprehensive review pass Fix factual errors, fill in missing flag documentation, inline warning code references where the relevant feature is documented, and tighten prose: - lockfile.md: move `frozen: true` out of the `package` block in the example; it's a top-level manifest field. - commands.md: rewrite `pickle` Slang-availability note to use the correct feature flag (`--features slang`, not `--all-features`), and reword the colloquial `bender update` note. - concepts.md: rename `local.md` TOC entry from "Workspace" to "Local Configuration" to match the page title. - commands.md: document `path --checkout`, `packages --version` / `--targets`, `sources --raw` / `--ignore-passed-targets`, and `parents --targets`; add cross-links from `sources` to dependencies.md / sources.md and from manifest plugins to commands.md. - workflow/dependencies.md: document `audit --ignore-url-conflict`. - workflow/package_dev.md: document snapshot `--working-dir`, `--checkout`, `--force`, including the W25 interaction with `--no-skip`. - Inline warning codes where the related feature is documented: W01/W06 under workspace fields, W11 under `upstream_name`, W14 under `--local`, W18 under overrides, W25 under snapshot. - Drop "powerful" filler from index.md, targets.md, sources.md. - Add missing cross-links from getting_started.md and index.md. - Standardize "tapeout" -> "tape-out". Co-Authored-By: Claude Opus 4.7 (1M context) --- book/src/commands.md | 26 ++++++++++++++++++-------- book/src/concepts.md | 2 +- book/src/configuration.md | 2 +- book/src/dependencies.md | 2 +- book/src/getting_started.md | 2 +- book/src/index.md | 2 +- book/src/local.md | 2 +- book/src/lockfile.md | 7 +++++-- book/src/manifest.md | 6 ++++-- book/src/sources.md | 2 +- book/src/targets.md | 2 +- book/src/workflow/dependencies.md | 5 ++++- book/src/workflow/package_dev.md | 5 +++++ 13 files changed, 44 insertions(+), 21 deletions(-) diff --git a/book/src/commands.md b/book/src/commands.md index 875748c6..bf8a7a91 100644 --- a/book/src/commands.md +++ b/book/src/commands.md @@ -5,25 +5,29 @@ ## `path` --- Get the path of a checked-out package -The `bender path ` prints the path of the checked-out version of package `PKG`. +The `bender path ` prints the path of the checked-out version of package `PKG`. One or more package names may be passed. Useful in scripts: #!/bin/bash cat `bender path mydep`/src/hello.txt +If a package has not been checked out yet, `bender path` checks it out before printing. Pass `--checkout` to force a re-checkout even when the directory already exists. + ## `packages` --- Display the dependency graph -- `bender packages`: List the package dependencies. The list is sorted and grouped according to a topological sorting of the dependencies. That is, leaf dependencies are compiled first, then dependent ones. -- `bender packages -f`: Produces the same list, but flattened. -- `bender packages -g`: Produces a graph description of the dependencies of the form `TAB`. +- `bender packages`: List the package [dependencies](./dependencies.md). The list is sorted and grouped according to a topological sorting of the dependencies. That is, leaf dependencies are compiled first, then dependent ones. +- `bender packages -f/--flat`: Produces the same list, but flattened. +- `bender packages -g/--graph`: Produces a graph description of the dependencies of the form `TAB`. +- `bender packages --version` (alias `--versions`): Print the resolved version of each package. Implies `--flat`. +- `bender packages --targets` (alias `--target`): Print the available [targets](./targets.md) for each package. ## `sources` --- List source files [Code](https://github.com/pulp-platform/bender/blob/master/src/cmd/sources.rs) -Produces a *sources manifest*, a JSON description of all files needed to build the project. +Produces a *sources manifest*, a JSON description of all files needed to build the project. See [Sources](./sources.md) for the manifest format and [Dependencies](./dependencies.md) for how dependencies contribute their sources. The manifest is recursive by default; meaning that dependencies and groups are nested. Use the `-f`/`--flatten` switch to produce a simple flat listing. @@ -37,6 +41,10 @@ To get the sources for a subset of packages, exclude specific packages and their For multiple packages (or excludes), multiple `-p` (or `-e`) arguments can be added to the command. +Additional flags: +- `--raw`: Output the raw internal source tree as JSON, useful for debugging Bender itself. +- `--ignore-passed-targets`: Ignore any targets that would otherwise be inherited via `pass_targets` from a parent package. + ## `config` --- Emit the current configuration @@ -71,7 +79,7 @@ Furthermore, similar flags to the `sources` command exist. The `bender pickle` command parses SystemVerilog sources with [Slang](https://github.com/MikePopoloski/slang) and prints the resulting source again. It supports optional renaming and trimming of unreachable files for specified top modules. -This command is only available when Bender is built with Slang support (the default; pass `--all-features` if building without defaults). +This command is only available when Bender is built with the `slang` feature, which is part of the default feature set. If you previously installed Bender with `--no-default-features`, rebuild with `--features slang` (or the default feature set) to enable `pickle`. Useful options: - `--top `: Trim output to files reachable from one or more top modules. @@ -101,7 +109,7 @@ Whenever you update the list of dependencies, you likely have to run `bender upd Calling update with the `--fetch/-f` flag will force all git dependencies to be re-fetched from their corresponding urls. -> Note: Actually this should be done automatically if you add a new dependency. But due to the lack of coding time, this has to be done manually as of now. +> **Note:** `bender update` should ideally be run automatically when dependencies are added; for now this has to be done manually. ## `clone` --- Clone dependency to make modifications @@ -125,7 +133,9 @@ With `bender snapshot`, all dependencies previously cloned to a working director ## `parents` --- Lists packages calling the specified package -The `bender parents ` command lists all packages calling the `PKG` package. +The `bender parents ` command lists all packages calling the `PKG` package, along with the version requirement each parent imposes. + +Pass `--targets` to additionally print the [targets](./targets.md) each parent passes down to `PKG` via `pass_targets`. ## `checkout` --- Checkout all dependencies referenced in the Lock file diff --git a/book/src/concepts.md b/book/src/concepts.md index 15662f18..1df24a8f 100644 --- a/book/src/concepts.md +++ b/book/src/concepts.md @@ -5,7 +5,7 @@ This section explains the core ideas and files that make Bender work. Understand - **[Principles](./principles.md):** The high-level goals and design philosophy behind Bender. - **[Manifest](./manifest.md):** How to define your package's metadata, dependencies, and sources. - **[Lockfile](./lockfile.md):** How Bender ensures reproducible builds across different environments. -- **[Workspace](./local.md):** Overriding settings for your local development workspace. +- **[Local Configuration](./local.md):** Overriding settings for your local development workspace via `Bender.local`. - **[Comparing the Files](./bender_files.md):** A quick comparison of the three core files (`.yml`, `.lock`, `.local`). - **[Dependencies](./dependencies.md):** How Bender handles hierarchical and transitive dependencies. - **[Sources](./sources.md):** Managing HDL source files, include directories, and defines. diff --git a/book/src/configuration.md b/book/src/configuration.md index 5f0cc4ca..ffac90c9 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -75,7 +75,7 @@ Sets a custom root working directory. This directory is used as the starting poi - **Default:** Current working directory. ### `local` -Disables fetching of remotes. Useful for working on air-gapped computers or when you want to ensure no network operations occur. +Disables fetching of remotes. Useful for working on air-gapped computers or when you want to ensure no network operations occur. When set, Bender emits warning `W14` to remind you that resolution may not pick up newly available versions. - **CLI Flag:** `--local` - **Env Var:** `BENDER_LOCAL` diff --git a/book/src/dependencies.md b/book/src/dependencies.md index 413e417b..90a7a768 100644 --- a/book/src/dependencies.md +++ b/book/src/dependencies.md @@ -74,7 +74,7 @@ dependencies: ### Differing Repository Name -By default, Bender appends the dependency's local name to the remote URL when resolving the Git URL. If the upstream repository is named differently from how you want to refer to the dependency locally, use `upstream_name`: +By default, Bender appends the dependency's local name to the remote URL when resolving the Git URL. If the upstream repository is named differently from how you want to refer to the dependency locally, use `upstream_name`. Without this field, a mismatch between a dependency's local name and the `package.name` declared inside the dependency's own [`Bender.yml`](./manifest.md) triggers warning `W11`. ```yaml remotes: diff --git a/book/src/getting_started.md b/book/src/getting_started.md index 37e1daf9..28d6c7e4 100644 --- a/book/src/getting_started.md +++ b/book/src/getting_started.md @@ -62,4 +62,4 @@ Finally, generate a compilation script for your EDA tool (e.g., QuestaSim/ModelS bender script vsim > compile.tcl ``` -You can now run `vsim -do compile.tcl` in your terminal to compile the entire project. +You can now run `vsim -do compile.tcl` in your terminal to compile the entire project. See [Generating Tool Scripts](./workflow/scripts.md) for the full set of output formats and flags. diff --git a/book/src/index.md b/book/src/index.md index 94c39044..dcd9a299 100644 --- a/book/src/index.md +++ b/book/src/index.md @@ -9,7 +9,7 @@ Bender helps you manage complex hardware IP hierarchies, ensuring that every mem - **Hierarchical Dependency Management:** Resolve and manage transitive dependencies across multiple Git repositories or local paths, allowing for IPs to be used across projects. - **Reproducible Builds:** A precise lockfile mechanism ([`Bender.lock`](./lockfile.md)) ensures identical design states across environments. - **HDL-Aware Source Collection:** Automatically manages file ordering, include directories, and preprocessor defines for SystemVerilog and VHDL. -- **Target-Based Filtering:** Use powerful boolean expressions to include or exclude files based on your flow (simulation, synthesis, etc.) or design configuration. +- **Target-Based Filtering:** Use [target expressions](./targets.md) to include or exclude files based on your flow (simulation, synthesis, etc.) or design configuration. - **Local Development Workflow:** Easily modify dependencies in-place using the `clone` and `snapshot` flow without breaking official manifests. - **Tool Script Generation:** Generate compilation and simulation scripts for major EDA tools like QuestaSim, VCS, Vivado, Verilator, and more. diff --git a/book/src/local.md b/book/src/local.md index df291da0..edab51b0 100644 --- a/book/src/local.md +++ b/book/src/local.md @@ -19,7 +19,7 @@ overrides: axi: { git: "https://github.com/my_fork/axi.git", rev: "experimental_branch" } ``` -When an override is present, Bender will prioritize it over any other version resolution. +When an override is present, Bender will prioritize it over any other version resolution and emit warning `W18` listing the package and the override target, so you can spot accidental overrides in `Bender.local`. > **Note:** `overrides` only replace dependencies that already exist somewhere in the resolved dependency tree. They cannot be used to introduce new dependencies that are not pulled in by any package's [`Bender.yml`](./manifest.md). diff --git a/book/src/lockfile.md b/book/src/lockfile.md index bfaf404c..85544c5d 100644 --- a/book/src/lockfile.md +++ b/book/src/lockfile.md @@ -51,7 +51,10 @@ If you want to prevent accidental updates to your project's dependency tree, you ```yaml package: name: my_chip - frozen: true # Prevents 'bender update' from running + +frozen: true # Prevents 'bender update' from running ``` -When `frozen: true` is set, `bender update` will fail, ensuring that your `Bender.lock` remains unchanged until you explicitly unfreeze the manifest. This is mostly recommended for late-stage tapeouts. +`frozen` is a top-level manifest field, not a member of the `package` block. + +When `frozen: true` is set, `bender update` will fail, ensuring that your `Bender.lock` remains unchanged until you explicitly unfreeze the manifest. This is mostly recommended for late-stage tape-outs. diff --git a/book/src/manifest.md b/book/src/manifest.md index 1347c933..c42b7ab5 100644 --- a/book/src/manifest.md +++ b/book/src/manifest.md @@ -67,7 +67,7 @@ export_include_dirs: - include ``` -Setting `frozen` to `true` prevents Bender from updating dependencies beyond what is recorded in the lockfile. This is useful for chip packages in tapeout mode where dependency changes would require disastrous amounts of re-verification. +Setting `frozen` to `true` prevents Bender from updating dependencies beyond what is recorded in the lockfile. This is useful for chip packages in tape-out mode where dependency changes would require disastrous amounts of re-verification. ```yaml # Freeze dependency updates. Optional. Defaults to false. @@ -91,7 +91,9 @@ workspace: checkout_dir: deps ``` -Packages can expose shell scripts as bender subcommands using the `plugins` section. These commands are available to packages that depend on this one and can be invoked as `bender `. +> **Note:** If a `package_links` target already exists and is not a symlink to the expected destination, Bender skips it and emits warning `W01` rather than overwriting it. If a dependency under a custom `checkout_dir` is not a Git working tree or has uncommitted changes, Bender emits warning `W06` and leaves it alone — use `bender snapshot --checkout --force` to refresh it (see [Package Development](./workflow/package_dev.md)). + +Packages can expose shell scripts as [`bender` subcommands](./commands.md) using the `plugins` section. These commands are available to packages that depend on this one and can be invoked as `bender `. ```yaml # Package-provided commands callable as `bender `. Optional. diff --git a/book/src/sources.md b/book/src/sources.md index da7c7c22..533d0715 100644 --- a/book/src/sources.md +++ b/book/src/sources.md @@ -90,7 +90,7 @@ sources: ## File Overrides -The `override_files: true` flag allows a source group to replace files with the same basename from other parts of the dependency tree. This is a powerful mechanism for "patching" dependencies or swapping implementations at the top level. +The `override_files: true` flag allows a source group to replace files with the same basename from other parts of the dependency tree. Use it to "patch" dependencies or swap implementations at the top level. ```yaml sources: diff --git a/book/src/targets.md b/book/src/targets.md index 7b11cb37..1d0fc04a 100644 --- a/book/src/targets.md +++ b/book/src/targets.md @@ -155,7 +155,7 @@ bender script vivado -t synthesis -t fpga ## Passing Targets Hierarchically -Bender allows you to "configure" your dependencies by passing specific targets down to them using the `pass_targets` field. This is a powerful way to propagate global settings or select implementations in sub-modules. +Bender allows you to configure your dependencies by passing specific targets down to them using the `pass_targets` field. This lets you propagate global settings or select alternative implementations within sub-modules. ### Simple Passing You can pass a target name as a string, which will then always be active for that specific dependency: diff --git a/book/src/workflow/dependencies.md b/book/src/workflow/dependencies.md index 0bda6135..e2009ef6 100644 --- a/book/src/workflow/dependencies.md +++ b/book/src/workflow/dependencies.md @@ -92,4 +92,7 @@ The output classifies each package as one of: - **Path:** the dependency points to a local directory. - **Conflict:** the dependency tree has incompatible version requirements or remote URLs — use `bender parents ` to investigate. -Pass `--only-update` to show only packages that have a possible update, or `-f/--fetch` to force a re-fetch of all Git remotes before auditing. +Useful flags: +- `--only-update`: show only packages that have a possible update. +- `-f/--fetch`: force a re-fetch of all Git remotes before auditing. +- `--ignore-url-conflict`: suppress conflict reporting when the same dependency is reached via different remote URLs (e.g. an HTTPS and an SSH URL for the same repository). diff --git a/book/src/workflow/package_dev.md b/book/src/workflow/package_dev.md index 94e3bd22..2e8a52be 100644 --- a/book/src/workflow/package_dev.md +++ b/book/src/workflow/package_dev.md @@ -36,6 +36,11 @@ Bender will: **Why use Snapshot?** The main benefit of a snapshot is portability. Because the lockfile is updated with the specific commit hashes, you can commit [`Bender.lock`](../lockfile.md) and share it with colleagues or run it in CI. The other environments will download the exact revisions you were working on from the Git remotes, without needing access to your local development paths. +Useful flags: +- `--working-dir `: scan a different directory for local checkouts (defaults to `working_dir`, matching `bender clone`'s default). +- `--checkout`: after writing the lockfile, also check out the resolved revisions into the configured `checkout_dir` (if any). Dependencies with uncommitted changes are skipped by default; warning [`W25`](#) is emitted for each one. Pass `--no-skip` to snapshot them anyway. +- `--force`: combined with `--checkout`, overwrite an existing custom `checkout_dir`. Use with care, as this can discard local work. + ## Finalizing Changes Once your changes are stable and you are ready to "release" them: