34 个版本 (18 个破坏性)

0.28.1 2024年2月23日
0.27.4 2023年12月29日
0.27.3 2023年9月12日
0.27.2 2023年7月13日
0.1.0 2018年2月28日

#1 in 模拟

Download history 10/week @ 2024-04-28 23/week @ 2024-05-05 23/week @ 2024-05-12 42/week @ 2024-05-19 13/week @ 2024-05-26 19/week @ 2024-06-02 6/week @ 2024-06-09 5/week @ 2024-06-16 7/week @ 2024-06-30 15/week @ 2024-07-07 15/week @ 2024-07-14 8/week @ 2024-07-21 250/week @ 2024-07-28 28/week @ 2024-08-04 16/week @ 2024-08-11

303 每月下载量

Apache-2.0 OR MIT

360KB
7.5K SLoC

bender

贝纳德是硬件设计项目的依赖管理工具。它提供了一种定义 IP 之间依赖关系、执行单元测试以及验证源文件是否为各种仿真和综合工具的有效输入的方法。

Build Status Crates.io dependency status Crates.io

目录

原则

贝纳德围绕以下核心原则构建

  • 尽可能地进行选择。 我们不假设任何特定的 EDA 工具、工作流程或目录布局(除了几个关键文件)。所有功能都设计得尽可能模块化,以便用户可以将它们集成到他们各自的工作流程中。

  • 允许进行可重复构建。 贝纳德维护一个精确的 锁定文件,该文件跟踪依赖项解决的确切 git 哈希值。这允许在事后可靠地重新构建软件包的源代码。

  • 收集源文件。 贝纳德的第一功能层是收集硬件 IP 中的源文件。在这样做的时候,它应该做以下事情

    • 维护源文件之间的所需顺序,例如在它们使用之前声明包。
    • 尽可能无语言限制,支持 SystemVerilog 和 VHDL。
    • 允许将源文件组织成递归组。
    • 为每个组单独跟踪定义和包含目录。
  • 管理依赖项。 贝纳德的第二功能层是维护 IP 可能依赖的其他包,并提供必要的源文件的本地签出。具体来说,它应该

    • 支持传递依赖
    • 不依赖于中央软件包注册表,例如 npm、cargo 或 brew(由于项目的部分通常处于 NDA 之下,这是必要的)
    • 强制执行严格的语义版本控制语义版本控制
  • 生成工具脚本。 Bender 的第三个功能层级是生成各种工具的源文件列表和编译脚本。

安装

要使用 Bender 进行单个项目的开发,最简单的方法是下载并使用预编译的二进制文件。我们为每个发布版本提供了适用于所有当前版本的 Ubuntu 和 CentOS 以及通用 Linux 的二进制文件。打开终端并输入以下命令

curl --proto '=https' --tlsv1.2 https://pulp-platform.github.io/bender/init -sSf | sh

该命令将下载并执行一个脚本,该脚本检测您的发行版并从最新发布版下载适合您当前目录的适当 bender 二进制文件。如果您需要特定版本的 Bender(例如,0.21.0),请将 -s -- 0.21.0 添加到该命令中。或者,您可以从 我们的 GitHub 发布版手动下载预编译的二进制文件。

如果您更喜欢构建自己的二进制文件,您需要安装 Rust。然后,您可以使用以下命令为当前用户构建和安装 Bender

cargo install bender

如果您需要特定版本的 Bender(例如,0.21.0),请将 --version 0.21.0 添加到该命令中。

要全局安装 Bender,您可以将从上述方法之一获得的二进制文件复制到系统目录之一,该目录位于 PATH 中。更好的是,一些 Linux 发行版已将 Bender 放入其仓库中。我们目前知道

ArchLinux aur-shield

如果您知道其他发行版,请通过 PR 扩展此列表。

工作流程

Bender 的工作流程基于配置文件和锁定文件。配置文件列出当前包的源、依赖项和测试。锁定文件用于跟踪正在使用的包的确切版本。将该文件添加到版本控制中,例如,对于将要封装的芯片,可以轻松重建仿真、综合或封装期间使用的确切 IP。

在执行任何命令时,Bender 会检查配置文件中是否有添加到配置文件中但不在锁定文件中的依赖项。然后,它会尝试为每个添加的依赖项找到一个与其他依赖项兼容的修订版,并将其添加到锁定文件中。在第二步中,Bender 尝试确保检出的修订版与锁定文件中的修订版匹配。如果不可能,将生成适当的错误。

更新命令重新评估配置文件中的所有依赖项,并尝试为每个找到满足所有递归约束的修订版。如果使用语义版本控制,这将更新依赖项到配置文件中提供的版本要求范围内的较新版本。

包结构

Bender 在一个包中寻找以下三个文件

  • Bender.yml:这是主要的 包清单,也是将目录识别为 Bender 包的唯一必要文件。它包含元数据、依赖项和源文件列表。

  • Bender.lock:在所有依赖项成功解析后,将生成一次性的锁文件。它包含每个依赖项的确切修订版本。该文件可以存放在版本控制系统中,以便进行可重复构建。这在录制设计时非常有用。如果锁文件丢失或添加了新的依赖项,则将其重新生成。

  • Bender.local:此可选文件包含本地配置覆盖。在版本控制中应忽略此文件,即将其添加到.gitignore。此文件可用于覆盖依赖项的本地变体。当用户请求依赖项的本地副本时也会使用此文件。

相关代码

清单格式 (Bender.yml)

包清单描述了包、其元数据、其依赖项及其源文件。清单中的所有路径都是相对的,在这种情况下,它们被认为是相对于包含清单的目录的相对路径。

# 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 <[email protected]>"]

# Other packages this package depends on. Optional.
dependencies:
  # Path dependency.
  axi: { path: "../axi" }

  # Registry dependency. Not supported at the moment.
  # common_verification: "0.2"

  # Git version dependency.
  common_verification: { git: "[email protected]:pulp-platform/common_verification.git", version: "0.1" }

  # Git revision dependency.
  common_cells: { git: "[email protected]:pulp-platform/common_cells.git", rev: master }

# 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

# 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 <cmd>`.
# 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' }

相关代码

依赖

依赖项在包清单的dependencies部分或配置文件中的overrides部分中指定。以下将描述不同类型的依赖项。

路径

mydep: { path: "../path/to/mydep" }

路径依赖项不被视为版本化的。要么所有版本的依赖项mydep都指向同一路径,否则解析将失败。

Git

mydep: { git: "[email protected]:pulp-platform/common_verification.git", rev: "<commit-ish>" }
mydep: { git: "[email protected]:pulp-platform/common_verification.git", version: "1.1" }

Git依赖项将自动检出和克隆,并考虑进行版本解析。rev字段可以是git的“提交-可识别”,本质上是一个提交哈希、标签名称或分支名称,选择与指定修订标识符以指示的名称最新名称。字段version可以是semver谓词的任何一种,例如简单的版本X.Y.Z(或X.Y),使用前缀^仅允许该特定版本,使用~将更新限制为补丁,或使用>=U.V.W, <X.Y.Z定义自定义范围。有关如何解析字段version的更多详细信息,请参阅cargo文档。选择最高兼容版本。

所有形式为vX.Y.Z的Git标签都被认为是包的版本。

相关依赖解析代码

包清单中sources部分的源文件是一个递归结构。列表中的每个条目可以是单个源文件,也可以是一组源文件

# Format of the `sources` section in the manifest:
sources:
  - <file or group 1>
  - <file or group 2>
  - ...

  # 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:
      - <include dir 1>
      - <include dir 2>
      - ...
    # List of defines. Optional.
    defines:
      # Defines without value:
      <define name 1>: ~
      <define name 2>: ~
      # Defines with value:
      <define name 3>: <define value 3>
      <define name 4>: <define value 4>
      ...
    # Target specifier. Optional.
    target: <target specifier>
    # Recursive list of source files and groups:
    files:
      - <file or group 1>
      - <file or group 2>
      - ...

target规范配置了在某些情况下应包含或排除的源组。以下将详细介绍。字段include_dirs指定了要添加到该组的任何编译命令的+incdir+...语句。字段defines指定了要添加到该组的任何编译命令的+define+...语句。

目标

目标是用于过滤源文件和依赖项的标志。它们用于区分ASIC/FPGA设计流程中的步骤、EDA工具、技术目标等。它们还可以用于具有针对不同芯片或技术的不同版本的IP。

目标指定了一种简单的表达式语言,如下所示

  • * 匹配任何目标
  • name 匹配目标 "name"
  • all(T1, ..., TN) 如果所有目标T1到TN匹配(布尔AND
  • any(T1, ..., TN) 如果目标T1到TN中的任何一个匹配(布尔OR
  • not(T) 如果目标T不匹配(布尔NOT

以下目标由各种bender子命令自动设置

  • synthesis 用于合成工具脚本生成
  • simulation 用于仿真工具脚本生成

个别命令也可以设置特定工具的目标

  • vsim
  • vcs
  • verilator
  • synopsys
  • riviera
  • genus
  • vivado

个别命令也可以设置特定供应商的目标

  • xilinx
  • synopsys

个别命令也可以设置特定技术目标

  • asic
  • fpga

此外,我们建议使用以下目标来识别设计过程中的不同阶段源代码和网表

  • test 用于测试平台代码
  • rtl 用于可综合的RTL代码
  • gate 用于门级网表

相关代码

供应商

部分,列出从不支持bender的外部存储库复制和修补到此存储库的文件和目录。要更新,请参阅下面的 vendor 命令。

配置格式 (bender.yml, Bender.local)

Bender会在以下位置查找配置文件

  • /etc/bender.yml
  • $HOME/.config/bender.yml

它还会从当前工作目录递归向上查找以下内容

  • .bender.yml
  • Bender.local

这些文件的合并顺序是它们被找到的顺序,因此foo/.bender.yml中的配置将覆盖foo/bar/.bender.yml中的配置。

配置文件通常如下所示

# 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: "[email protected]: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" }

相关代码

命令

bender 是依赖关系管理系统的人口。Bender始终在包内操作;从当前工作目录开始,向上搜索文件层次结构,直到找到一个Bender.yml,这标志着包。

path --- 获取已签出的包的路径

bender path <PKG> 打印包 PKG 签出版本的路径。

在脚本中很有用

#!/bin/bash
cat `bender path mydep`/src/hello.txt

packages --- 显示依赖图

  • bender packages:列出包依赖项。列表按依赖项的拓扑排序排序和分组。也就是说,叶依赖项首先编译,然后是依赖项。
  • bender packages -f:生成相同的列表,但进行了扁平化。
  • bender packages -g:生成依赖关系的图描述,格式为<pkg>TAB<dependencies...>

sources —— 列出源文件

代码

生成一个源清单,这是构建项目所需所有文件的JSON描述。

清单默认是递归的;这意味着依赖和组是嵌套的。使用-f/--flatten选项来生成简单的平面列表。

要启用特定目标,请使用-t/--target选项。

要获取部分包的源代码,排除特定包及其依赖项,或排除所有依赖项,存在以下标志

  • -p/--package:指定要显示源代码的包。
  • -e/--exclude:指定要排除在源代码之外的包。
  • -n/--no-deps:排除所有依赖项,即只包括顶级或指定的包。

对于多个包(或排除项),可以在命令中添加多个-p(或-e)参数。

config —— 输出当前配置

bender config命令将当前活动配置作为JSON打印到标准输出。

script —— 生成特定工具的脚本

bender script <format>命令可以生成脚本,将包及其依赖项的源代码输入到供应商工具中。这些脚本使用内部存储的模板,通过tera crate渲染,但也可以使用自定义模板。

支持的格式

  • flist:一个平面文件列表,可以直接嵌入到工具的调用命令中,例如verilate $(bender script flist)
  • vsim:Mentor ModelSim/QuestaSim的Tcl编译脚本。
  • vcs:VCS的Tcl编译脚本。
  • verilator:Verilator的命令行参数。
  • synopsys:Synopsys DC和DE的Tcl编译脚本。
  • formality:Formality(作为参考设计)的Tcl编译脚本。
  • riviera:Aldec Riviera-PRO的Tcl编译脚本。
  • genus:Cadence Genus的Tcl编译脚本。
  • vivado:Xilinx Vivado的Tcl文件添加脚本。
  • vivado-sim:与vivado相同,但专门用于仿真目标。
  • precision:Mentor Precision的Tcl编译脚本。
  • template:使用--template标志提供的自定义tera模板。
  • template_json:用于渲染tera模板的json结构。

此外,与sources命令类似的标志也存在。

update —— 重新解析依赖项

每次更新依赖列表时,您可能需要运行 bender update 来重新解析依赖版本,并重新创建 Bender.lock 文件。

使用带有 --fetch/-f 标志的 update 命令将强制所有 git 依赖从相应的 URL 重新获取。

注意:实际上,如果添加了新的依赖,这应该自动完成。但由于缺乏编码时间,目前必须手动完成。

clone —— 复制依赖以进行修改

bender clone <PKG> 命令将包 PKG 检出到目录中(默认 working_dir,可以用 -/ --path <DIR> 覆盖)。为确保包在 bender 中正确链接,Bender.local 文件被修改以包含一个 path 依赖覆盖,链接到相应的包。

这可以用于在父存储库内部开发依赖包,允许测试未提交和已提交的更改,无需担心 bender 会更新依赖。

一旦添加了更改,请确保调用包引用正确的版本,并在 Bender.local 中移除路径依赖。

注意:将来可能更新覆盖位置,以通过向 Bender.lock 添加持久部分来防止修改可由人工编辑的 Bender.local 文件。

注意:新创建的目录将是一个 git 仓库,远程原点指向解析的依赖项的 git 标签(通常从清单(Bender.yml)中评估)。您可能需要调整 git 远程 URL 以正确与您的远程存储库一起工作。

parents —— 列出调用指定包的包

bender parents <PKG> 命令列出调用 PKG 包的所有包。

checkout —— 检出 Lock 文件中引用的所有依赖

此命令将确保所有依赖都从远程存储库下载。这通常由其他命令自动执行,例如 sourcesscript

fusesoc —— 创建 FuseSoC .core 文件

此命令将从 bender 表示形式生成 FuseSoC .core 文件,以实现与 FuseSoC 工具的开源兼容性。它旨在提供基本清单文件,以便任何希望包含 bender 包的项目都可以这样做而无需过多开销。

如果提供了 --single 参数,则仅解析顶层 Bender.yml 文件并生成一个 .core 文件。

如果没有提供--single参数,bender将遍历所有依赖项并生成一个 FuseSoC .core文件,即使没有这样的文件。如果对应依赖项的同一目录中已存在.core文件,则会使用该文件来链接依赖项(如果存在多个,则用户将被提示选择一个)。根据.core文件中的Created by bender from the available manifest file.注释,将覆盖先前生成的.core文件。

--license参数将允许您在生成的.core文件顶部添加多个注释行,例如许可证头字符串。

--fuse_vendor参数将为VLNV名称的所有生成的.core依赖项分配供应商字符串。

--fuse_version参数将为VLNV名称的处理顶级包分配版本。

vendor --- 从不支持bender的依赖项复制文件

用于管理单一代码库的命令集合。需要子命令。

请确保您分别管理这些文件所需的包含文件和源文件,因为此命令仅获取文件并对它们进行修补。这在一定程度上基于lowRISC's vendor.py脚本。

vendor init --- (重新)初始化供应商依赖项

此命令将(重新)初始化Bender.yml文件中vendor_package部分的依赖项,从远程仓库获取文件,应用必要的补丁文件,并将它们写入相应的target_dir

如果传递了-n/--no_patch参数,则将初始化依赖项而不会应用任何补丁。

vendor diff --- 打印本地未修补更改的diff

此命令将打印一个diff,显示应用了patch_dir中补丁的远程仓库。

vendor patch --- 从本地更改生成补丁文件

如果供应商依赖项中存在本地、暂存的更改,则此命令将提示输入提交信息并为此依赖项生成补丁。补丁将写入patch_dir

如果传递了--plain参数,则此命令将不会提示输入提交信息并为供应商依赖项的所有(暂存和未暂存)本地更改生成补丁。

示例工作流程

假设我们希望将依赖项my_ip供应商到项目monorepo中。一个简单的配置在Bender.yml中可能如下所示(有关此配置的更多信息,请参阅上面的Bender.yml描述)

vendor_package:
  - name: my_ip
    target_dir: deps/my_ip
    upstream: { git: "<url>", rev: "<commit-hash>" }
    patch_dir: "deps/patches/my_ip"

现在执行bender vendor init将从upstream克隆此依赖项并将其放置在target_dir中。

接下来,假设我们在依赖项内部编辑了两个文件,分别是deps/my_ip/adeps/my_ip/b。我们可以使用bender vendor diff命令打印这些更改。

现在,我们想生成一个包含在deps/my_ip/a中更改(但不包括在deps/my_ip/b中)的补丁。我们使用以下命令git add deps/my_ip/a(当然,您也可以使用以下命令只暂存文件的某个部分:git add --patch)。命令bender vendor patch将现在请求一个与该补丁关联的提交消息。然后,它将包含我们更改的deps/my_ip/a补丁放入deps/patches/my_ip/0001-commit-message.patch(如果已经存在编号补丁,则编号将递增)。

在monorepo中创建相应的提交也很容易。deps/my_ip/a仍然从上一步骤中暂存。我们只需要执行以下命令:git add deps/patches/my_ip/0001-commit-message.patchgit commit,在monorepo中创建一个原子提交,包含我们对deps/my_ip/a的更改以及相应的补丁。

将补丁上传到依赖项也很容易。我们克隆依赖项的存储库,检出<commit-hash>并创建一个新分支。现在,执行以下命令git am /path/to/monorepo/deps/patches/my_ip/0001-commit-message.patch将从该补丁创建一个提交,包括所有元数据,如提交消息、作者和时间戳。然后,可以对这个分支进行变基,并从该分支创建常规的pull request。

注意:当在vendor_package中使用映射时,补丁将与映射的目录相关。因此,在上传时,您可能需要使用以下命令而不是简单的git amgit am --directory=<mapping.from>

依赖

~15–28MB
~428K SLoC