From 89a9fdcc657bc4ef07ebb57318b876808daab204 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Fri, 23 Oct 2026 10:44:24 +0800 Subject: [PATCH 1/8] docs: rebuild bilingual guides and add documentation previews Organize the Chinese and English documentation into tutorials, task instructions, API references and explanations. Add a complete Adder walkthrough and practical guidance for RTL export, simulation, internal signals, language bindings and UVM transactions. Keep README and legacy pages as entry points to the canonical documentation. Add a searchable MkDocs site with language switching and a Wiki exporter that uses the same Markdown sources. Provide checks for page and navigation parity, local links and anchors, Python example syntax and matching runnable examples across translations. Run documentation checks, strict site builds and Wiki exports for relevant master PRs, master/docs branch pushes and manual runs. Upload the site and Wiki as review artifacts, and document the authoring workflow. Validation: bilingual/link/syntax checks, strict site build and Wiki export passed. Four Python documentation examples passed against generated models; site navigation, search, language switching and mobile layout were checked. --- .github/workflows/docs.yml | 61 ++++++ CONTRIBUTING.md | 70 +------ README.md | 253 ++----------------------- README.zh.md | 280 ++-------------------------- doc/API.zh.md | 168 +---------------- doc/en/development/contributing.md | 47 +++++ doc/en/development/documentation.md | 56 ++++++ doc/en/development/releases.md | 44 +++++ doc/en/explanation/architecture.md | 38 ++++ doc/en/guides/export.md | 73 ++++++++ doc/en/guides/installation.md | 92 +++++++++ doc/en/guides/internal-signals.md | 75 ++++++++ doc/en/guides/languages.md | 49 +++++ doc/en/guides/simulation.md | 114 +++++++++++ doc/en/guides/uvm-tlm.md | 59 ++++++ doc/en/index.md | 24 +++ doc/en/reference/cli.md | 70 +++++++ doc/en/reference/compatibility.md | 42 +++++ doc/en/reference/dut-api.md | 86 +++++++++ doc/en/reference/troubleshooting.md | 36 ++++ doc/en/tutorials/first-dut.md | 110 +++++++++++ doc/index.md | 0 doc/install-macos.en.md | 61 +----- doc/install-macos.zh.md | 61 +----- doc/maintainer-guidance.md | 83 +-------- doc/zh/development/contributing.md | 47 +++++ doc/zh/development/documentation.md | 56 ++++++ doc/zh/development/releases.md | 44 +++++ doc/zh/explanation/architecture.md | 38 ++++ doc/zh/guides/export.md | 73 ++++++++ doc/zh/guides/installation.md | 92 +++++++++ doc/zh/guides/internal-signals.md | 75 ++++++++ doc/zh/guides/languages.md | 49 +++++ doc/zh/guides/simulation.md | 114 +++++++++++ doc/zh/guides/uvm-tlm.md | 59 ++++++ doc/zh/index.md | 24 +++ doc/zh/reference/cli.md | 70 +++++++ doc/zh/reference/compatibility.md | 42 +++++ doc/zh/reference/dut-api.md | 86 +++++++++ doc/zh/reference/troubleshooting.md | 36 ++++ doc/zh/tutorials/first-dut.md | 110 +++++++++++ mkdocs.yml | 99 ++++++++++ requirements-docs.txt | 4 + scripts/docs.py | 217 +++++++++++++++++++++ test/README.md | 44 +++-- 45 files changed, 2488 insertions(+), 943 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 doc/en/development/contributing.md create mode 100644 doc/en/development/documentation.md create mode 100644 doc/en/development/releases.md create mode 100644 doc/en/explanation/architecture.md create mode 100644 doc/en/guides/export.md create mode 100644 doc/en/guides/installation.md create mode 100644 doc/en/guides/internal-signals.md create mode 100644 doc/en/guides/languages.md create mode 100644 doc/en/guides/simulation.md create mode 100644 doc/en/guides/uvm-tlm.md create mode 100644 doc/en/index.md create mode 100644 doc/en/reference/cli.md create mode 100644 doc/en/reference/compatibility.md create mode 100644 doc/en/reference/dut-api.md create mode 100644 doc/en/reference/troubleshooting.md create mode 100644 doc/en/tutorials/first-dut.md delete mode 100644 doc/index.md create mode 100644 doc/zh/development/contributing.md create mode 100644 doc/zh/development/documentation.md create mode 100644 doc/zh/development/releases.md create mode 100644 doc/zh/explanation/architecture.md create mode 100644 doc/zh/guides/export.md create mode 100644 doc/zh/guides/installation.md create mode 100644 doc/zh/guides/internal-signals.md create mode 100644 doc/zh/guides/languages.md create mode 100644 doc/zh/guides/simulation.md create mode 100644 doc/zh/guides/uvm-tlm.md create mode 100644 doc/zh/index.md create mode 100644 doc/zh/reference/cli.md create mode 100644 doc/zh/reference/compatibility.md create mode 100644 doc/zh/reference/dut-api.md create mode 100644 doc/zh/reference/troubleshooting.md create mode 100644 doc/zh/tutorials/first-dut.md create mode 100644 mkdocs.yml create mode 100644 requirements-docs.txt create mode 100644 scripts/docs.py diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..948133a1 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,61 @@ +name: Documentation + +on: + pull_request: + branches: [master] + paths: + - "doc/**" + - "README*" + - "CONTRIBUTING.md" + - "test/README.md" + - "mkdocs.yml" + - "requirements-docs.txt" + - "scripts/docs.py" + - ".github/workflows/docs.yml" + push: + branches: [master, "docs/**"] + paths: + - "doc/**" + - "README*" + - "CONTRIBUTING.md" + - "test/README.md" + - "mkdocs.yml" + - "requirements-docs.txt" + - "scripts/docs.py" + - ".github/workflows/docs.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: documentation-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + documentation: + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + cache-dependency-path: requirements-docs.txt + - name: Install documentation tools + run: python -m pip install -r requirements-docs.txt + - name: Check translations, links and example syntax + run: python scripts/docs.py check + - name: Build documentation site + run: python -m mkdocs build --strict + - name: Export Wiki pages + run: python scripts/docs.py wiki --output build/wiki-export + - name: Upload documentation preview + uses: actions/upload-artifact@v4 + with: + name: picker-documentation + if-no-files-found: error + path: | + build/docs-site + build/wiki-export diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5596595c..7b8eddff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,69 +1,11 @@ -# Contributing to the picker project +# Contributing / 参与贡献 -First off, thank you for considering contributing to our project! We appreciate your time and effort, and we value every contribution. +[English development guide](doc/en/development/contributing.md) | [中文开发指南](doc/zh/development/contributing.md) -## How to Contribute +Use a topic branch and submit a PR targeting master. Explain the problem, resulting behavior and tests run; choose exactly one release:patch/minor/major label. Update both language references when changing an interface. Start with the [architecture](doc/en/explanation/architecture.md) and [documentation workflow](doc/en/development/documentation.md). -### Reporting Issues +在独立分支修改并提交到 master 的 PR,说明问题、改后行为与实际测试,选择且仅选择一个 release:patch/minor/major 标签。接口改动同步中英文文档。先看[架构](doc/zh/explanation/architecture.md)与[文档工作流](doc/zh/development/documentation.md)。 -If you find a bug or have a feature request, please create an issue on GitHub. Before creating a new issue, please check if the issue already exists. +Before reporting an issue, search [existing issues](https://github.com/XS-MLVP/picker/issues) and include a minimal reproducer with tool versions. 提交问题前先搜索已有记录,附最小复现和工具版本。Community QQ / 社区 QQ:600480230。 -1. Go to the [Issues](https://github.com/XS-MLVP/picker/issues) page. -2. Search for existing issues to avoid duplicates. -3. If no similar issue exists, click on "New Issue" and fill out the template with as much detail as possible. -4. Add appropriate tags to your issue for better categorization, such as bug, DUT name, etc. - -### Submitting Code Changes - -We follow the GitHub Flow for our development process. Here are the steps to submit your code changes: - -1. **Fork the repository**: Click the "Fork" button at the top right of the repository page. -2. **Clone your fork**: Clone your forked repository to your local machine. - ```bash - git clone - cd picker - ``` -3. **Create a new branch**: Create a new branch for your changes. - ```bash - git checkout -b my-feature-branch - ``` -4. **Make your changes**: Make your changes to the codebase. -5. **Commit your changes**: Commit your changes with a descriptive commit message. - ```bash - git add . - git commit -m "Description of my changes" - ``` -6. **Push to your fork**: Push your changes to your forked repository. - ```bash - git push origin my-feature-branch - ``` -7. **Create a Pull Request**: Go to the original repository and create a pull request from your fork. Fill out the pull request template with as much detail as possible. - -### Code Style - -Please ensure your code adheres to the following style guidelines: - -- Use meaningful variable and function names. -- Write comments and docstrings to explain your code. -- Ensure your code is well-formatted and linted. - -### Writing Tests - -If you add new functionality, please write tests to ensure it works correctly. - - -### Documentation - -If your changes affect the documentation, please update the relevant sections. - -### Code of Conduct - -Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project, you agree to abide by its terms. - -### Getting Help - -If you need help or have any questions, feel free to reach out by creating an issue or joining our community QQ group: 600480230. - -### Acknowledgments - -Thank you for your contributions! Your support and involvement help make this project better. +[Code of Conduct / 行为准则](CODE_OF_CONDUCT.md) · [Security reporting / 安全报告](SECURITY.md) diff --git a/README.md b/README.md index 71270185..84029078 100644 --- a/README.md +++ b/README.md @@ -1,250 +1,31 @@ -# Picker: Pick your favorite language to verify your chip. - -> A codegen tool for chip verification, which can provide C++/Python interfaces for the RTL designs. +# Picker English | [中文](README.zh.md) -## Introduction - -**picker** is a chip verification auxiliary tool with two main functions: - -1. **Export RTL designs into verification modules:** Picker can convert RTL design verification modules (.v/.scala/.sv) into dynamic libraries and provide programming interfaces in multiple high-level languages (currently supporting C++, Python, Java, Scala, Golang, Lua) to drive the circuits. -1. **Pack UVM-TLM transaction with other languages:** Picker can automatically encapsulate TLM code based on user-provided UVM sequence_items, providing communication interfaces between UVM and other high-level languages (such as Python). - -This tool allows users to perform chip unit testing based on existing software testing frameworks, such as pytest, junit, TestNG, go test, etc. - -Advantages of verification based on picker: - -1. No RTL design leakage: After conversion by picker, the original design files (.v) are transformed into binary files (.so). Verification can still be performed without the original design files, and the verifier cannot access the RTL source code. -1. Reduced compilation time: When the DUT (Design Under Test) is stable, it only needs to be compiled once (packaged into a .so file). -1. Wide user range: Provides multiple programming interfaces, covering developers of different languages. -1. Utilizes rich software ecosystems: Supports ecosystems such as Python3, Java, Golang. -1. Automated UVM transaction encapsulation: Achieves communication between UVM and Python through automated UVM transaction encapsulation. - -Currently supported RTL simulators by picker: - -1. Verilator -1. Synopsys VCS -1. [GSIM](https://github.com/OpenXiangShan/gsim) -1. [UniVista Simulator (UVS)](https://www.univista-isg.com/site/product_detail/441) - -## How to Use - -### Dependency Installation - -1. [CMake](https://cmake.org/download/) (>=3.11) -2. [GCC](https://gcc.gnu.org/) (needs to support C++20, at least version 10, **recommended version 11 or above**) -3. [Python3](https://www.python.org/downloads/) (>=3.8) -4. [Verilator](https://verilator.org/guide/latest/install.html#git-quick-install) (>=5.020) -5. [SWIG](http://www.swig.org/) (>=**4.2.0**, multi-language support) - -### Source Code Download - -```bash -git clone https://github.com/XS-MLVP/picker.git --depth=1 -cd picker -make init -``` - -`make init` fetches the git-based dependencies under `dependence/`, including `xcomm`, `slang`, and `fmt`. - -### Build and Install +Picker exports Verilog/SystemVerilog designs as Python, C++, Java, Scala, Go, or Lua modules, so you can write hardware tests in a familiar language. Tests can read and write signals, advance clocks, check results, and save waveforms. Picker also generates transaction bridges between Python and UVM. -```bash -cd picker -make -# You can enable support for other languages by -# using `make BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua`. -# Each language requires its own development environment, -# which needs to be configured separately, such as `javac` for Java. -# Install to the default prefix (/usr/local) -sudo -E make install +## Get started -# Or install to a custom prefix, for example: -# make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/picker" -``` - -#### Install Prefix - -The default installation prefix is `/usr/local`. - -To install picker somewhere else, pass `ARGS` to the `install` target: - -```bash -make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/picker" -``` - -Installed files follow the selected prefix: - -- `/bin/picker` -- `/share/picker` -- `/lib/libxspcomm.so` +[Install Picker](doc/en/guides/installation.md), then follow the [adder tutorial](doc/en/tutorials/first-dut.md) to run your first test. From the repository root, export a Python module: -If you are installing on macOS and want a complete example that uses a user-owned prefix, see [doc/install-macos.en.md](doc/install-macos.en.md). - -Use `sudo -E make install` only when the target prefix requires elevated permissions. If you install under a user-owned directory such as `$HOME/picker`, `sudo` is usually unnecessary. - -The installation will also install the `xspcomm` base library (https://github.com/XS-MLVP/xcomm), which is used to encapsulate the basic types of `RTL` modules. If you compile against it manually, you may need to add the corresponding library search path, such as `-L/lib`. - -If support for languages such as Java is enabled, the corresponding `xspcomm` multi-language packages are installed under the same prefix. - -**picker can also be compiled into a wheel file and installed via pip** - -To package picker into a wheel installation package, use the following command: - -```bash -pip install pipx==1.10.0 # install dependency -make wheel # or BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua make wheel +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-adder/Adder --autobuild false +make -C build/docs-adder/Adder -j4 ``` -After compilation, the wheel file will be located in the dist directory. You can then install it via pip, for example: +Create a test in the generated package's parent directory to assign inputs by port name and check outputs. The tutorial includes a complete script and expected results. -```bash -# Manually install whl packages -pip install dist/xspcomm-0.0.1-cp311-cp311-linux_x86_64.whl -pip install dist/picker-0.0.1-cp311-cp311-linux_x86_64.whl -# Or install using the following make command -make wheel_install -``` +## Documentation -After installation, execute the `picker` command to expect the following output: +[English documentation](doc/en/index.md) · [完整中文文档](doc/zh/index.md) -``` -XDut Generate. -Convert DUT(*.v/*.sv) to C++ DUT libs. +- Use Picker: [export RTL](doc/en/guides/export.md), [clocks and waveforms](doc/en/guides/simulation.md), [internal signals](doc/en/guides/internal-signals.md), [languages](doc/en/guides/languages.md), [UVM](doc/en/guides/uvm-tlm.md). +- Look up an interface: [CLI](doc/en/reference/cli.md), [DUT API](doc/en/reference/dut-api.md), [troubleshooting](doc/en/reference/troubleshooting.md). +- Develop Picker: [how it works](doc/en/explanation/architecture.md), [contributing and tests](CONTRIBUTING.md), [documentation and Wiki](doc/en/development/documentation.md). -Usage: ./build/bin/picker [OPTIONS] [SUBCOMMAND] - -Options: - -h,--help Print this help message and exit - -v,--version Print version - --show_default_template_path - Print default template path - --show_xcom_lib_location_cpp - Print xspcomm lib and include location - --show_xcom_lib_location_java - Print xspcomm-java.jar location - --show_xcom_lib_location_scala - Print xspcomm-scala.jar location - --show_xcom_lib_location_python - Print python module xspcomm location - --show_xcom_lib_location_golang - Print golang module xspcomm location - --show_xcom_lib_location_lua - Print lua module xspcomm location - --check check install location and supported languages - -Subcommands: - export Export RTL Projects Sources as Software libraries such as C++/Python - pack Pack UVM transaction as a UVM agent and Python class -``` - -### Installation Test - -picker currently has two subcommands: `export` and `pack`. - -The `export` subcommand is used to convert RTL designs into "libraries" corresponding to other high-level programming languages, which can be driven through software. - -> $picker export --help - -```bash -Export RTL Projects Sources as Software libraries such as C++/Python -Usage: picker export [OPTIONS] file... - -Positionals: - file TEXT ... REQUIRED DUT .v/.sv source file, contain the top module - -Options: - -h,--help Print this help message and exit - --fs,--filelist TEXT ... DUT .v/.sv source files, contain the top module, split by comma. - Or use '*.txt' file with one RTL file path per line to specify the file list - --sim TEXT [verilator] vcs, gsim or verilator as simulator, default is verilator - --lang,--language TEXT:{python,cpp,java,scala,golang,lua} [python] - Build target project with assigned language, default python - --sdir,--source_dir TEXT [/home/yaozhicheng/workspace/picker/template] - Template Files Dir, default is ${picker_install_path}/../picker/template - --sname,--source_module_name TEXT ... - Pick the module in DUT .v file, default is the last module in the -f marked file - --tname,--target_module_name TEXT - Set the module name and file name of target DUT, default is the same as source. - For example, -T top, will generate UTtop.cpp and UTtop.hpp with UTtop class - --tdir,--target_dir TEXT Target directory to store all the results. If it ends with '/' or is empty, - the directory name will be the same as the target module name - --internal TEXT Exported internal signal config file, default is empty, means no internal pin - --checkpoints Enable checkpoints, save/restore , default is OFF - --vpi Enable VPI, for flexible internal signal access default is OFF - -F,--frequency TEXT [100MHz] - Set the frequency of the **only VCS** DUT, default is 100MHz, use Hz, KHz, MHz, GHz as unit - -w,--wave_file_name TEXT Wave file name, empty means don't dump wave - -c,--coverage Enable coverage, default is not selected as OFF - --cp_lib,--copy_xspcomm_lib BOOLEAN [1] - Copy xspcomm lib to generated DUT dir, default is true - -V,--vflag TEXT User defined simulator compile args, passthrough. - Eg: Using vcs simulator for exporting line coverage, -V '"-cm line -cm_dir /abs_path_to_store_coverage_data"' - -S,--sflag TEXT ... User defined slang RTL parser args, passthrough. - Eg: '--cmd-ignore=-myflag,1' - -C,--cflag TEXT User defined gcc/clang compile command, passthrough. - Eg: -C '"-O3 -std=c++17 -I./include"' - --verbose Verbose mode - -e,--example Build example project, default is OFF - --autobuild BOOLEAN [1] Auto build the generated project, default is true - -j,--build-threads INT [0] Maximum parallel build threads; 0 uses all available CPU cores -``` - -Static Multi-Module Support: - -When generating the wrapper for `dut_top.sv/v`, picker allows specifying multiple module names and their corresponding quantities using the `--sname` parameter. For example, if there are modules A and B in the design files `a.v` and `b.v` respectively, and you need 2 instances of A and 3 instances of B in the generated DUT, and the combined module name is C (if not specified, the default name will be A_B). This can be achieved using the following command: - -```bash -picker export path/a.v,path/b.v --sname A,2,B,3 --tname C -``` - -Environment Variables: - -- `DUMPVARS_OPTION`: Sets the option parameter for `$dumpvars`. For example, `DUMPVARS_OPTION="+mda" picker ....` enables array waveform support in VCS. - -The `pack` subcommand is used to convert UVM `sequence_item` into other languages and then communicate through TLM (currently supports Python, other languages are under development). - -> $picker pack --help - -```bash -Pack uvm transaction as a uvm agent and python class -Usage: picker pack [OPTIONS] file... - -Positionals: - file TEXT ... REQUIRED Sv source file, contain the transaction define - -Options: - -h,--help Print this help message and exit - -e,--example Generate example project based on transaction, default is OFF - -c,--force Force delete folder when the code has already generated by picker - -r,--rename TEXT ... Rename transaction name in picker generate code - -d,--generate-dut Generate DUT abstraction class with pin-level interface - -f,--filelist TEXT ... File list containing transaction files - --from-rtl TEXT RTL source file (.v/.sv) to auto-generate transaction from module ports - -``` - -### Test Examples - -After picker compilation, execute the following commands in the picker directory to test the examples: - -``` -bash example/Adder/release-verilator.sh --lang cpp -bash example/Adder/release-verilator.sh --lang python - -# Default enable cpp and python -# for other languages support:make BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua -bash example/Adder/release-verilator.sh --lang java -bash example/Adder/release-verilator.sh --lang scala -bash example/Adder/release-verilator.sh --lang golang -bash example/Adder/release-verilator.sh --lang lua - -bash example/RandomGenerator/release-verilator.sh --lang cpp -bash example/RandomGenerator/release-verilator.sh --lang python -bash example/RandomGenerator/release-verilator.sh --lang java -``` +## Community -### More Documents +Report issues and suggestions through [GitHub Issues](https://github.com/XS-MLVP/picker/issues). The community QQ group is 600480230. More verification resources are available in the [MLVP documentation](https://open-verify.cc/mlvp/docs/). -For guidance on chip verification with picker, please refer to: [https://open-verify.cc/mlvp/en/docs/](https://open-verify.cc/mlvp/en/docs/) +[Code of conduct](CODE_OF_CONDUCT.md) · [Security reports](SECURITY.md) · [License](LICENSE) diff --git a/README.zh.md b/README.zh.md index 5624bc14..207db645 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,277 +1,31 @@ -# Picker: 用你擅长的编程语言进行芯片验证. - -> A codegen tool for chip verification, which can provide C++/Python/Java/Scala/Golang/Lua interfaces for the RTL designs. +# Picker 中文 | [English](README.md) -## 介绍 - -**picker** 是一个芯片验证辅助工具,具有两个主要功能: - -1. **打包 RTL 设计验证模块:** picker 可以将 RTL 设计验证模块(.v/.scala/.sv)打包成动态库,并提供多种高级语言(目前支持 C++、Python、Java、Scala、Golang、Lua)的编程接口来驱动电路。 -1. **UVM-TLM 代码自动生成:** picker 能够基于用户提供的 UVM sequence_item 进行自动化的 TLM 代码封装,提供 UVM 与其他高级语言(如 Python)的通信接口。 - -该工具允许用户基于现有的软件测试框架,例如 pytest、junit、TestNG、go test 等,进行芯片单元测试。 - -基于 Picker 进行验证的优点 - -1. 不泄露 RTL 设计:经过 Picker 转换后,原始的设计文件(.v)被转化成了二进制文件(.so),脱离原始设计文件后,依旧可进行验证,且验证者无法获取 RTL 源代码。 -1. 减少编译时间:当 DUT(设计待测)稳定时,只需要编译一次(打包成 .so 文件)。 -1. 用户范围广:提供的编程接口多,覆盖不同语言的开发者。 -1. 使用丰富的软件生态:支持 Python3、Java、Golang 等生态系统。 -1. 自动化的 UVM 事务封装:通过自动化封装 UVM 事务,实现 UVM 和 Python 的通信。 - -Picker 目前支持的 RTL 仿真器: - -1. Verilator -1. Synopsys VCS -1. [GSIM](https://github.com/OpenXiangShan/gsim) -1. [UniVista Simulator (UVS)](https://www.univista-isg.com/site/product_detail/441) - -# 使用方法 - -### 依赖安装 - -1. [cmake](https://cmake.org/download/) ( >=3.11 ) -2. [gcc](https://gcc.gnu.org/) ( 需要支持 c++20, 版本至少为 10, **建议 11 及以上版本** ) -3. [python3](https://www.python.org/downloads/) ( >=3.8 ) -4. [verilator](https://verilator.org/guide/latest/install.html#git-quick-install) ( >=5.020 ) -5. [swig](http://www.swig.org/) ( >=**4.2.0**, 多语言支持 ) - -### 下载源码 - -```bash -git clone https://github.com/XS-MLVP/picker.git --depth=1 -cd picker -make init -``` - -`make init` 会自动拉取 `dependence/` 下的 git 依赖,包括 `xcomm`、`slang` 和 `fmt`。 - -### 构建并安装 - -```bash -cd picker -make -# 可通过 make BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua 开启其他语言支持。 -# 各语言需要自己的开发环境,需要自行配置,例如javac等 -# 安装到默认前缀 (/usr/local) -sudo -E make install +Picker 将 Verilog/SystemVerilog 设计导出为 Python、C++、Java、Scala、Go 或 Lua 模块,方便你用熟悉的语言编写硬件测试。测试代码可以读写信号、推进时钟、检查结果和保存波形。Picker 也支持生成连接 Python 与 UVM 的事务桥。 -# 或安装到自定义前缀,例如: -# make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/picker" -``` - -#### 安装前缀 - -默认安装前缀是 `/usr/local`。 +## 开始使用 -如果你想安装到其他位置,请在执行 `install` 时传入 `ARGS`: +先[安装 Picker](doc/zh/guides/installation.md),再跟随[加法器教程](doc/zh/tutorials/first-dut.md)完成第一次验证。在仓库根目录导出 Python 模块: -```bash -make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/picker" +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-adder/Adder --autobuild false +make -C build/docs-adder/Adder -j4 ``` -安装产物会跟随你设置的前缀放到这些目录下: - -- `/bin/picker` -- `/share/picker` -- `/lib/libxspcomm.so` - -如果你是在 macOS 上安装,并希望参考安装到用户目录下的完整示例,可以查看 [doc/install-macos.zh.md](doc/install-macos.zh.md)。 - -只有目标目录需要管理员权限时,才需要使用 `sudo -E make install`。如果安装到 `$HOME/picker` 这类当前用户可写目录,通常不需要 `sudo`。 - -安装时还会自动安装 `xspcomm` 基础库([https://github.com/XS-MLVP/xcomm](https://github.com/XS-MLVP/xcomm)),该基础库用于封装 `RTL` 模块的基础类型。如果你需要手动链接它,可能还需要补充对应的库搜索路径,例如 `-L/lib`。 - -如果开启了 Java 等语言支持,还会在同一个前缀下安装 `xspcomm` 对应的多语言软件包。 - -**picker 也可以编译为 wheel 文件,通过 pip 安装** +在生成包的父目录中创建测试,就可以通过端口名给输入赋值并检查输出。教程包含完整脚本和预期结果。 -通过以下命令把 picker 打包成 wheel 安装包: - -```bash -pip install pipx==1.10.0 # 安装依赖 -make wheel # or BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua make wheel -``` - -编译完成后,wheel 文件位于 dist 目录,然后通过 pip 安装,例如: - -```bash -# 手动安装whl包 -pip install dist/xspcomm-0.0.1-cp311-cp311-linux_x86_64.whl -pip install dist/picker-0.0.1-cp311-cp311-linux_x86_64.whl -# 或者通过以下make命令安装 -make wheel_install -``` - -安装完成后,执行`picker`命令可以得到以下输出: - -``` -XDut Generate. -Convert DUT(*.v/*.sv) to C++ DUT libs. +## 文档 -Usage: ./build/bin/picker [OPTIONS] [SUBCOMMAND] +[完整中文文档](doc/zh/index.md) · [English documentation](doc/en/index.md) -Options: - -h,--help Print this help message and exit - -v,--version Print version - --show_default_template_path - Print default template path - --show_xcom_lib_location_cpp - Print xspcomm lib and include location - --show_xcom_lib_location_java - Print xspcomm-java.jar location - --show_xcom_lib_location_scala - Print xspcomm-scala.jar location - --show_xcom_lib_location_python - Print python module xspcomm location - --show_xcom_lib_location_golang - Print golang module xspcomm location - --show_xcom_lib_location_lua - Print lua module xspcomm location - --check check install location and supported languages +- 使用:[导出 RTL](doc/zh/guides/export.md)、[时钟与波形](doc/zh/guides/simulation.md)、[内部信号](doc/zh/guides/internal-signals.md)、[多语言](doc/zh/guides/languages.md)、[UVM](doc/zh/guides/uvm-tlm.md)。 +- 查询:[命令行](doc/zh/reference/cli.md)、[DUT API](doc/zh/reference/dut-api.md)、[故障排查](doc/zh/reference/troubleshooting.md)。 +- 开发:[工作原理](doc/zh/explanation/architecture.md)、[贡献与测试](CONTRIBUTING.md)、[文档与 Wiki](doc/zh/development/documentation.md)。 -Subcommands: - export Export RTL Projects Sources as Software libraries such as C++/Python - pack Pack UVM transaction as a UVM agent and Python class -``` - -### 安装测试 - -当前 picker 有 export 和 pack 两个子命令。 - -export 子命令用于将 RTL 设计转换成其他高级编程语言对应的“库”,可以通过软件的方式进行驱动。 - -> $picker export --help - -```bash -Export RTL Projects Sources as Software libraries such as C++/Python -Usage: picker export [OPTIONS] file... - -Positionals: - file TEXT ... REQUIRED DUT .v/.sv source file, contain the top module - -Options: - -h,--help Print this help message and exit - --fs,--filelist TEXT ... DUT .v/.sv source files, contain the top module, split by comma. - Or use '*.txt' file with one RTL file path per line to specify the file list - --sim TEXT [verilator] vcs, gsim or verilator as simulator, default is verilator - --lang,--language TEXT:{python,cpp,java,scala,golang,lua} [python] - Build target project with assigned language, default python - --sdir,--source_dir TEXT Template Files Dir, default is ${picker_install_path}/../picker/template - --sname,--source_module_name TEXT ... - Pick the module in DUT .v file, default is the last module in the -f marked file - --tname,--target_module_name TEXT - Set the module name and file name of target DUT, default is the same as source. - For example, -T top, will generate UTtop.cpp and UTtop.hpp with UTtop class - --tdir,--target_dir TEXT Target directory to store all the results. If it ends with '/' or is empty, - the directory name will be the same as the target module name - --internal TEXT Exported internal signal config file, default is empty, means no internal pin - -F,--frequency TEXT [100MHz] - Set the frequency of the **only VCS** DUT, default is 100MHz, use Hz, KHz, MHz, GHz as unit - -w,--wave_file_name TEXT Wave file name, empty means don't dump wave - -c,--coverage Enable coverage, default is not selected as OFF - --cp_lib,--copy_xspcomm_lib BOOLEAN [1] - Copy xspcomm lib to generated DUT dir, default is true - -V,--vflag TEXT User defined simulator compile args, passthrough. - Eg: Using vcs simulator for exporting line coverage, -V '"-cm line -cm_dir /abs_path_to_store_coverage_data"' - -S,--sflag TEXT ... User defined slang RTL parser args, passthrough. - Eg: '--cmd-ignore=-myflag,1' - -C,--cflag TEXT User defined gcc/clang compile command, passthrough. - Eg: -C '"-O3 -std=c++17 -I./include"' - --verbose Verbose mode - -e,--example Build example project, default is OFF - --autobuild BOOLEAN [1] Auto build the generated project, default is true - -j,--build-threads INT [0] 最大并行构建线程数;0 表示使用所有可用 CPU 核心 -``` - -pack 子命令用于将 UVM 中的 sequence_item 转换为其他语言,然后通过 TLM 进行通信(目前支持 Python,其他语言在开发中) - -> $picker pack --help - -```bash -Pack uvm transaction as a uvm agent and python class -Usage: picker pack [OPTIONS] file... - -Positionals: - file TEXT ... REQUIRED Sv source file, contain the transaction define - -Options: - -h,--help Print this help message and exit - -e,--example Generate example project based on transaction, default is OFF - -c,--force Force delete folder when the code has already generated by picker - -r,--rename TEXT ... Rename transaction name in picker generate code - -d,--generate-dut Generate DUT abstraction class with pin-level interface - -f,--filelist TEXT ... File list containing transaction files - --from-rtl TEXT RTL source file (.v/.sv) to auto-generate transaction from module ports -``` - -#### 参数解释 - -##### export: - -- `file TEXT ... REQUIRED`:必须。位置参数,DUT.v/.sv 源文件,包含顶层模块 -- `-h,--help`: 可选。打印此帮助信息并退出 -- `--fs,--filelist TEXT ...`: 可选。DUT .v/.sv 源文件,包含顶层模块,逗号分隔。或使用 '\*.txt' 文件,每行指定一个 RTL 文件路径来指定文件列表 -- `--sim TEXT [verilator]`: 可选。使用 vcs 或 verilator 作为模拟器,默认是 verilator -- `--lang,--language TEXT:{python,cpp,java,scala,golang,lua} [python]`: 可选。构建示例项目,默认是 python -- `--sdir,--source_dir TEXT`: 可选。模板文件目录,默认是 ${picker_install_path}/../picker/template -- `--sname,--source_module_name TEXT ...`: 可选。在 DUT .v 文件中选择模块,默认是 -f 标记的文件中的最后一个模块 -- `--tname,--target_module_name TEXT`: 可选。设置目标 DUT 的模块名和文件名,默认与源相同。例如,-T top 将生成 UTtop.cpp 和 UTtop.hpp,并包含 UTtop 类 -- `--tdir,--target_dir TEXT`: 可选。代码生成渲染文件的目标目录,默认为 DUT 的模块名。如果该参数以'/'结尾,则在该参数指定的目录中创建以 DUT 模块名的子目录。 -- `--internal TEXT`: 可选。导出的内部信号配置文件,默认为空,表示没有内部引脚 -- `-F,--frequency TEXT [100MHz]`: 可选。设置 **仅 VCS** DUT 的频率,默认是 100MHz,可以使用 Hz、KHz、MHz、GHz 作为单位 -- `-w,--wave_file_name TEXT`: 可选。波形文件名,空表示不导出波形 -- `-c,--coverage`: 可选。启用覆盖率,默认不选择为 OFF -- `--cp_lib,--copy_xspcomm_lib BOOLEAN [1]`: 可选。将 xspcomm 库复制到生成的 DUT 目录,默认是 true -- `-V,--vflag TEXT`: 可选。用户定义的模拟器编译参数,透传。例如: 模拟器使用 vcs 时,导出行覆盖率: '-V '"-cm line -cm_dir /abs_path_to_store_coverage_data"'' -- `-S,--sflag TEXT ...`: 可选。用户定义的 slang(RTL 解析前端)参数,透传。filelist 中 slang 无法识别的参数会被自动屏蔽,此选项用于显式传入 slang 选项,例如:`--cmd-ignore=-myflag,1` -- `-C,--cflag TEXT`: 可选。用户定义的 gcc/clang 编译命令,透传。例如: -C '"-O3 -std=c++17 -I./include"' -- `--verbose`: 可选。详细模式 -- `-e,--example`: 可选。构建示例项目,默认是 OFF -- `--autobuild BOOLEAN [1]`: 可选。自动构建生成的项目,默认是 true -- `-j,--build-threads INT [0]`: 可选。限制生成项目的最大并行构建线程数,0 表示使用所有可用 CPU 核心 - -静态多模块支持: - -picker 在生成 dut_top.sv/v 的封装时,可以通过`--sname`参数指定多个模块名称和对应的数量。例如在 a.v 和 b.v 设计文件中分别有模块 A 和 B,需要 DUT 中有 2 个 A,3 个 B,生成的模块名称为 C(若不指定,默认名称为 A_B),则可执行如下命令: - -```bash -picker export path/a.v,path/b.v --sname A,2,B,3 --tname C -``` - -环境变量: - -- `DUMPVARS_OPTION`: 设置`$dumpvars`的 option 参数。例如`DUMPVARS_OPTION="+mda" picker ....` 开启 vcs 中数组波形的支持。 - -##### pack: - -- `file`: 必需。待解析的 UVM transaction 文件 -- `--example, -e`: 可选。根据 UVM 的 transaction 生成示例项目。 -- `--force, -c`: 可选。若已存在 picker 根据当前 transaction 解析出的文件,通过该命令可强制删除该文件,并重新生成 -- `--rename, -r`: 可选。配置生成文件以及生成的 agent 的名称,默认为 transaction 名。 - -### 测试 Examples - -编译完成后,在 picker 目录执行以下命令,进行测试: - -``` -bash example/Adder/release-verilator.sh --lang cpp -bash example/Adder/release-verilator.sh --lang python - -# 默认仅开启 cpp 和 Python 支持 -# 支持其他语言编译命令为:make BUILD_XSPCOMM_SWIG=python,java,scala,golang,lua -bash example/Adder/release-verilator.sh --lang java -bash example/Adder/release-verilator.sh --lang scala -bash example/Adder/release-verilator.sh --lang golang -bash example/Adder/release-verilator.sh --lang lua - -bash example/RandomGenerator/release-verilator.sh --lang cpp -bash example/RandomGenerator/release-verilator.sh --lang python -bash example/RandomGenerator/release-verilator.sh --lang java -``` +## 社区 -### 参考材料 +问题和建议请提交到 [GitHub Issues](https://github.com/XS-MLVP/picker/issues)。社区 QQ 群:600480230。更多验证资料见 [MLVP 文档](https://open-verify.cc/mlvp/docs/)。 -如何基于 picker 进行芯片验证,可参考:[https://open-verify.cc/mlvp/docs/](https://open-verify.cc/mlvp/docs/) +[行为准则](CODE_OF_CONDUCT.md) · [安全报告](SECURITY.md) · [许可证](LICENSE) diff --git a/doc/API.zh.md b/doc/API.zh.md index 11daa58d..710b9edf 100644 --- a/doc/API.zh.md +++ b/doc/API.zh.md @@ -1,166 +1,6 @@ +# DUT API -## DUT验证API和一般驱动流程 +[中文](zh/reference/dut-api.md) | [English](en/reference/dut-api.md) -在DUT中,有XData、XClock、XPort 三类成员变量,如需要调用对应功能可参考:[https://github.com/XS-MLVP/xcomm/blob/master/docs/APIs.cn.md](https://github.com/XS-MLVP/xcomm/blob/master/docs/APIs.cn.md) - -### DUT验证APIs - -在DUT对应的Class中,以**大驼峰命名**的函数为用户需要使用的常用函数,其他命名方式的函数为内部函数,不建议用户使用。 - -|编号|API名称|参数|返回值|说明| -|-|--|---|---|---| -|1|InitClock(name)|字符类型,时钟引脚,或引脚的名称|-|初始化时钟,让DUT中的`XClock`绑定对应的引脚| -|2|Step(i)|int类型,时钟周期个数|-|推进时序电路i个时钟周期| -|3|StepRis(callback)|函数类型,回调函数|-|设置上升沿触发的回调函数| -|4|StepFal(callback)|函数类型,回调函数|-|设置下降沿触发的回调函数| -|5|SetWaveform(file)|字符类型,文件名,含路径|-|设置波形输出的文件| -|6|FlushWaveform()|-|-|将波形内容立即刷新到文件中,**频繁调用可能导致FST压缩能力失效**| -|7|SetCoverage(file)|字符类型,文件名,含路径|-|设置覆盖率输出的文件| -|8|CheckPoint(file)|字符类型,文件名,含路径|int类型,当前时钟周期|保存当前仿真状态到文件| -|9|Restore(file)|字符类型,文件名,含路径|int类型,保存时的时钟周期|从文件中恢复仿真状态| -|10|GetInternalSignal(name)|字符类型,信号名称|XData类型|通过变量名获取的内部信号对象,需要开启 `--vpi`,**影响性能**| -|11|VPIInternalSignalList(prefix, deep)|字符类型,前缀,深度层级|int类型,信号名称列表|获取内部信号列表,需要开启 `--vpi`| -|12|Finish()|-|-|结束仿真,保持波形,覆盖率等结果文件| -|13|RefreshComb()|-|-|推进组合电路| - - -#### C++ -```c++ -void InitClock(std::string name); -void Step(int i = 1); -void StepRis(std::function, void*args=nullptr); -void StepFal(std::function, void*args=nullptr); -void SetWaveform(std::string filename); -void FlushWaveform(); -void SetCoverage(std::string filename); -int CheckPoint(const std::string filename); -int Restore(const std::string filename); -XData GetInternalSignal(const std::string name); -std::vector VPIInternalSignalList(std::string prefix="", int deep=99); -void Finish(); -void RefreshComb(); -``` - - -#### Python -```python -InitClock(name: str) -Step(i:int = 1) -StepRis(callback: Callable, args=None, args=(), kwargs={}) -StepFal(callback: Callable, args=None, args=(), kwargs={}) -SetWaveform(filename) -FlushWaveform() -SetCoverage(filename) -CheckPoint(filename: str) -> int -Restore(filename: str) -> int -GetInternalSignal(name: str) -> XData -VPIInternalSignalList(self, prefix="", deep=99) -> List[str] -Finish() -RefreshComb() -``` - -对于 StepRis 和 StepFal 中的回调函数,第一个参数为cycle,C++支持一个自定义参数 void*,python支持args 和 kwargs 自定义参数。其他编程语言不支持自定义参数: - -```java -// java -StepRis(Consumer callback) -StepFal(Consumer callback) -// scala -StepRis(callback: (Long) => Unit) -StepFal(callback: (Long) => Unit) -// golang -StepRis(callback: func(uint64)) -StepFal(callback: func(uint64)) -``` - -**对于其他API,Java/Scala/Golang等语言类似,此处不再重复** - - -### 驱动DUT的一般流程 - -1. 创建DUT -1. 初始化时钟(如果有) -1. reset电路(如果需要reset) -1. 给DUT输入引脚写入数据 -1. 驱动电路:时序电路用Step,组合电路用RefreshComb -1. 获取DUT输出 - -对应伪代码如下(以Python为例): - -```python -import random -from UT_DUT import * - -# 创建 -dut = DUT() - -# 初始化 -dut.SetWaveform("test.fst") -dut.InitClock("clock") - -dut.reset = 1 -dut.Step(1) -dut.reset = 0 -dut.Step(1) - -# 输入数据 -dut.input_pin1.value = 123 -dut.input_pin2.value = "0x456" -dut.input_pin3.value = "0b1011" - -# 驱动电路 -dut.Step(1) # or dut.RefreshComb() - -# 得到结果 -x = dut.output_pin.value -print("result:", x) - -# 销毁 -dut.Finish() -``` - - -#### DUT引脚取值与赋值 - -所有支持的编程语言都能提过Set(value)进行赋值,通过U()或者S()进行取值,提过At(i)获取第i位的值。 - -```c++ -// Set(value), U(), S() 接口 c++、java、python、golang、scala 通用 -// 由于Java、Scala、Golang支持bigInt类型,其U(),S()返回的也是bigInt类型,如果 -// 需要类似C++返回64位数,需要用 U64() 和 S64() -dut.pin.Set(0x123) -dut.pin.Set("0b100101") -x = dut.pin.S() // 获取有符号数 -x = dut.pin.U() // 获取无符号数 -x = dut.pin.At(12).Get() // 获取第12位 -dut.pin.At(12).Set(1) // 对第12位进行赋值 -``` - -**注1:** 对于Golang,其pin的成员名称首字母将自动转为大写,eg: dut.Pin.Set(0x123) - -**注2:** 如果pin的名称与dut中的成员变量或方法名称冲突,picker会自动加上pin_(对应Golang前缀为Pin_)前缀。冲突名称有:"xclock", "xport", "dut", "initclock", "step", "stepris", "stepfal", "setwaveform", "setcoverage", "finish", "refreshcomb"等 - -由于C++支持运算符重载,因此在赋值和取值上可以进行简化: -```c++ -dut.pin = 0x123 -dut.pin = "0b100101" -auto x = dut.pin -auto x dut.pin[12] -dut.pin[12] = 1 -``` - -python对属性value进行了重载: -```python -dut.pin.value = 0x123 -dut.pin.value = "0b100101" -x = dut.pin.value # 默认为无符号数 -x = dut.pin[12] -dut.pin[12] = 1 -``` - -scala 对运算符":="进行了重载,重载后如下 - -```scala -dut.pin := 0x123 -dut.pin := "0b100101" -``` +完整说明见上方的中英文页面。 +Follow the links above for the complete guide in either language. diff --git a/doc/en/development/contributing.md b/doc/en/development/contributing.md new file mode 100644 index 00000000..bd661fdb --- /dev/null +++ b/doc/en/development/contributing.md @@ -0,0 +1,47 @@ +# Development and testing + +After following [installation](../guides/installation.md) in a source checkout, you can edit, build, and run tests. Read [how generation and simulation work](../explanation/architecture.md) to locate the part you need to change. + +## Source directories + +| Path | Contents | +| --- | --- | +| `src/picker.cpp` | CLI arguments and export/pack flows | +| `src/parser/` | RTL, transactions, file lists, and signal layout parsing | +| `src/codegen/` | Convert parsed data into template inputs | +| `template/lib/` | Simulator wrappers and build configuration | +| `template/python/` and other language directories | Generated language interfaces and build templates | +| `test/` | Unit, export integration, and release script tests | +| `example/` | Runnable designs and tests | +| `doc/zh/`, `doc/en/` | Chinese and English documentation | + +To fix generated code, edit its template and export an example again to verify it. Libraries under `dependence/` are maintained separately; commit dependency changes in their own repositories. + +## Run tests + +Build and run C++ unit tests: + +```sh +make unit_tests NPROC=4 BUILD_XSPCOMM_SWIG=python,java +``` + +Choose integration tests for the change: + +| Change | Command | +| --- | --- | +| Python export and templates | `make -C test export_python` | +| File lists | `make -C test export_filelist` | +| Complex ports | `make -C test export_complex_port` | +| Internal signals and VPI | `make -C test export_vpi_python` | +| Transaction packing | `make -C test pack_transaction` | +| RTL to transactions | `make -C test pack_from_rtl` | +| Release scripts | `python3 -m unittest discover -s test/release -v` | +| Documentation | [Checks and preview](documentation.md) | + +Run the complete integration suite with `make -C test all`, using the corresponding language and simulator environments. Test preflight checks bindings and may rebuild missing ones; use a separate checkout when preserving other build outputs. Record the tests executed and any skips caused by missing tools. + +## Submit a change + +Work on a topic branch and open a PR against `master`. Describe how to reproduce the problem, the resulting behavior, and tests run. Update Chinese and English references and examples when changing an interface. + +Choose one `release:patch`, `release:minor`, or `release:major` label per PR. See [release maintenance](releases.md) for the post-merge process and [troubleshooting](../reference/troubleshooting.md) for issue report details. diff --git a/doc/en/development/documentation.md b/doc/en/development/documentation.md new file mode 100644 index 00000000..cb15c6e8 --- /dev/null +++ b/doc/en/development/documentation.md @@ -0,0 +1,56 @@ +# Maintain documentation and Wiki + +Chinese pages live in `doc/zh` and English pages in `doc/en`, with matching relative paths. Update both languages when editing content. Maintain navigation in `mkdocs.yml`. + +## Organize content around reader needs + +Use the four documentation types from [Diátaxis](https://diataxis.fr/): + +| Type | Reader need | Writing approach | +| --- | --- | --- | +| Tutorial | Complete an exercise with guidance | Give small, connected steps, each with an observable result | +| How-to guide | Complete a known task | Describe actions, necessary choices, and result checks, such as “Save waveforms” | +| Reference | Look up a parameter or method | Group by interface and state signatures, defaults, return values, and conditions precisely | +| Explanation | Understand design and behavior | Explain object relationships, call flow, and design decisions | + +In tutorials, let readers act and see a result before introducing the concepts needed for the next step. Link detailed parameters to reference pages and design reasoning to explanations. + +Use specific actions in titles and describe the procedure directly. For example: “Call `Finish()` to complete output handling, then open the waveform file.” Place limitations beside the relevant operation or interface, with their triggering conditions and effects. Follow the direct, clear style in the [Google technical writing guide](https://developers.google.com/style/highlights). + +## Write examples + +State the command's working directory, the script's file path, and expected output. Complete scripts should run when copied; fragments should identify their existing objects and environment. Use identical executable code in Chinese and English, with explanations in prose. + +## Preview the site + +From the repository root: + +```sh +python3 -m venv /tmp/docs-venv +/tmp/docs-venv/bin/python -m pip install -r requirements-docs.txt +/tmp/docs-venv/bin/python scripts/docs.py check +/tmp/docs-venv/bin/python -m mkdocs build --strict +/tmp/docs-venv/bin/python -m mkdocs serve -a 127.0.0.1:8000 +``` + +Open `http://127.0.0.1:8000` to check language switching, navigation, full-text search, and code rendering. The static site is written to `build/docs-site`. + +`check` validates translated page sets, navigation, links, anchors, and Python syntax. Mark complete executable blocks with `` or ``, then run: + +```sh +/tmp/docs-venv/bin/python scripts/docs.py test --python /path/to/runtime/bin/python +``` + +Picker examples need the tutorial's Adder, an Adder with waveforms and coverage, and the internal-signal guide's vpi model. Put the recording-enabled Adder and vpi packages in one directory and pass that directory with `--cwd`. + +## Export a GitHub Wiki + +The site and Wiki are generated from the same Markdown. Export into an empty directory: + +```sh +/tmp/docs-venv/bin/python scripts/docs.py wiki --output /tmp/picker-wiki +``` + +The output includes bilingual pages, a home page, sidebar, footer, and file manifest. Links are converted to Wiki page names. After review, maintainers can sync these files to `picker.wiki.git`. See [GitHub's Wiki documentation](https://docs.github.com/en/communities/documenting-your-project-with-wikis/adding-or-editing-wiki-pages) for editing the separate repository. + +Documentation CI runs for PRs targeting master, documentation changes pushed to master or `docs/**` branches, and manual dispatches. It checks translated pages, links, and example syntax, then builds the site and exports the Wiki as review artifacts. diff --git a/doc/en/development/releases.md b/doc/en/development/releases.md new file mode 100644 index 00000000..c35f2914 --- /dev/null +++ b/doc/en/development/releases.md @@ -0,0 +1,44 @@ +# Release maintenance + +Picker versions come from `vX.Y.Z` tags. A PR's `release:patch`, `release:minor`, or `release:major` label selects the version increment after merge. + +## Automated release flow + +1. Merge the PR into `master` after version checks and relevant builds pass. +2. Version policy creates a version tag and starts Tagged CI. +3. Tagged CI builds, installs, and validates wheels and native artifacts for the tag. +4. Release Picker waits up to 60 minutes for the source build, checks the commit SHA and artifact hashes, then publishes artifacts to GitHub Releases. + +Release tags identify merged results on the first-parent history of `master`. Wait for tagging to finish before merging the next release PR. Configure branch protection to require version checks and relevant builds. + +## Maintain dependency configuration + +| Configuration | Purpose | +| --- | --- | +| `pyproject.toml` | Python dependency ranges | +| `.build-config.yml` | Source commits and tools used by CI builds | +| `.github/workflows/ci.yml` | Development builds and preview wheel configuration | +| Tagged CI | Select published dependencies satisfying release constraints | + +After changing dependencies, rebuild and verify wheels and generated DUTs. If Picker needs a new dependency version, release that dependency first. + +## Recover failures + +| Failure | Action | +| --- | --- | +| Tagged CI build fails | Fix the build environment and rerun Tagged CI for the existing tag | +| Publication fails | Rerun Release Picker using the successful source run ID | +| A merge event fails to create a tag | Inspect Version policy logs and use its manual bump action | + +Reuse existing tags during recovery to preserve the mapping between commits and artifacts. + +## Local checks + +```sh +python3 -m unittest discover -s test/release -v +bash scripts/build/verify-wheel.sh +``` + +Wheel checks need build outputs in `dist/`. Use `PICKER_WHEEL_DIR` and `XCOMM_WHEEL_DIR` to select other directories. The script installs packages and checks interfaces in a separate environment. + +Release artifacts are published to GitHub Releases. Documentation CI provides site and Wiki previews as build artifacts; see [documentation maintenance](documentation.md). diff --git a/doc/en/explanation/architecture.md b/doc/en/explanation/architecture.md new file mode 100644 index 00000000..60e8bc77 --- /dev/null +++ b/doc/en/explanation/architecture.md @@ -0,0 +1,38 @@ +# How generation and simulation work + +During export, Picker reads RTL modules and ports and generates an interface for the selected language. The simulator executes the circuit. They are compiled into a DUT module that the test program uses to access the design. + +```mermaid +flowchart TD + R[RTL and file lists] --> P[Picker parses modules and ports] + P --> G[Generate wrappers and build files] + G --> C[Compile RTL and language interfaces] + C --> D[Importable or linkable DUT module] + T[Test program] --> D + D --> S[Simulator executes the circuit] + S --> O[Output signals and waveforms] +``` + +## Why export and compile first + +RTL defines the circuit structure. Export options select the language, simulator, and debugging features. Picker uses this information to generate wrappers and build files, which the compiler combines into a model. Tests can then create models and run different inputs, reusing the compiled result. + +Changes to RTL, ports, or export options require another export and build. Changes to Python inputs, assertions, or test organization can run immediately. + +## What happens during Step + +The test stores pending input values in port objects. When it calls `Step()`, inputs are submitted to the simulator, and registered clock pins change as simulation advances. The simulator evaluates the circuit and refreshes output values in the language interface. The test can then read and compare them. + +For sequential circuits, `InitClock()` selects the clock port and `Step(n)` advances complete clock cycles. Combinational circuits can also use `Step()` to update outputs after an input change. To keep the cycle count unchanged, submit the inputs and call `RefreshComb()` as shown in [driving a simulation](../guides/simulation.md). + +## Why waveforms and internal signals need export options + +Waveform recording and internal signal access require additional information at compilation time. `-w` generates waveform recording support; `--vpi` retains signal information for runtime lookup. Ordinary builds can carry less debugging data, while debug builds expose more of the design. + +At runtime, `SetWaveform()` selects the output file and `GetInternalSignal()` looks up retained signals. These methods use the features configured during export. + +## How a test uses different simulators + +The generated DUT wrapper provides common signal access and stepping methods. Simulator templates call the corresponding execution interfaces. You can usually keep the test body, change `--sim`, and rebuild the model. + +Waveform formats, checkpoints, and coverage are supplied by the simulator. See [simulator and language support](../reference/compatibility.md) for availability. To change these implementations, start with the [source map in the development guide](../development/contributing.md). diff --git a/doc/en/guides/export.md b/doc/en/guides/export.md new file mode 100644 index 00000000..0a7dfebc --- /dev/null +++ b/doc/en/guides/export.md @@ -0,0 +1,73 @@ +# Export an RTL project + +Exporting a design requires source files, a top module, a target language, and a simulator. Run the commands below from the Picker repository root. To use your own design, replace the file paths and module names. + +## Export a single file + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/Adder --autobuild false +make -C build/Adder -j4 +``` + +`--sname` selects the RTL top module. `--tdir` sets the output directory, and `--autobuild false` separates generation from compilation. With automatic building enabled by default, Picker compiles the project immediately after generation. + +To use a different Python package name, such as `Arithmetic`, add `--tname Arithmetic` and change the output directory to `build/Arithmetic`. The generated class is then `DUTArithmetic`. + +## Use a file list + +For projects with multiple files, pass a file list through `--fs`. The repository's `example/MultiFileRTL/design.f` includes a header search path and several source files: + +```text ++incdir+inc +inc/defs.vh +inc/outer.svh +leaf.v +top.sv +``` + +These paths are relative to the file list's directory. From the repository root, run: + +```sh +picker export --fs example/MultiFileRTL/design.f \ + --sname MultiFileRTLTop --lang python --sim verilator \ + --tdir build/MultiFileRTLTop --autobuild false +make -C build/MultiFileRTLTop -j4 +``` + +File lists support nested `-f` / `-F`, `+incdir+`, and `+define+` entries. Put the project's include directories and macro definitions in the list so parsing and simulator compilation use the same inputs. + +## Pass compilation options + +| Option | Stage | Common uses | +| --- | --- | --- | +| `-S` | slang parsing | Parser options and top-level parameters | +| `-V` | Simulator compilation | Simulator diagnostics or optimization | +| `-C` | C++ compilation | Compiler options | + +Quote arguments containing spaces. For example, pass a warning option to Verilator: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --tdir build/AdderDebug -V '-Wno-fatal' --autobuild false +``` + +## Export several modules together + +`--sname` accepts module names and instance counts. If `rtl/a.v` defines `A` and `rtl/b.v` defines `B`, this command creates a combined module C with two A instances and three B instances: + +```sh +picker export rtl/a.v,rtl/b.v --sname A,2,B,3 \ + --tname C --lang python --tdir build/C +``` + +Inspect the generated interface for instance and port names before writing the test. + +## Add debugging features + +- Use `-w trace.fst` to enable waveforms; see [record simulation results](simulation.md#recording). +- Use `--coverage` to collect simulator code coverage. +- Use `--vpi` or `--internal` to access internal signals; see [internal signals](internal-signals.md). +- Use `--lang` to change the language; see [language examples](languages.md). + +See the [CLI reference](../reference/cli.md) for all options, defaults, and output directory rules. diff --git a/doc/en/guides/installation.md b/doc/en/guides/installation.md new file mode 100644 index 00000000..8f996a9c --- /dev/null +++ b/doc/en/guides/installation.md @@ -0,0 +1,92 @@ +# Install Picker + +The Python + Verilator examples require Picker, Verilator, SWIG, a C++ compiler, and Python development files. The steps below build from source. If you already have the compilation tools, you can also use a release package described at the end of this page. + +## Prepare the tools + +| Tool | Requirement or purpose | +| --- | --- | +| C++ compiler | C++20 support, such as GCC 11 or newer | +| CMake, make, Git | Configure, compile, and fetch dependencies | +| Python and development headers | Build Python extensions; use the same Python environment for compilation and execution | +| SWIG | 4.2 or newer, for language bindings | +| Verilator | 5.020 or newer, to compile RTL | +| bison, flex, gperf | Build supporting tools | +| zlib and lz4 development packages | Compression dependencies | + +Follow the [Verilator installation guide](https://verilator.org/guide/latest/install.html) and the [SWIG download page](https://www.swig.org/download.html) to install these tools. Then check: + +```sh +c++ --version +cmake --version +python3 --version +swig -version +verilator --version +``` + +On macOS, install the tools with Homebrew: + +```sh +brew install cmake pkgconf python3 swig verilator zlib lz4 +``` + +## Build and install + +Fetch the source and dependencies, then install into your user directory: + +```sh +git clone https://github.com/XS-MLVP/picker.git +cd picker +make init +make install NPROC=4 BUILD_XSPCOMM_SWIG=python \ + ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/.local/picker" +export PATH="$HOME/.local/picker/bin:$PATH" +``` + +`make init` downloads dependencies into `dependence/`. `NPROC=4` runs four compilation jobs; reduce it on machines with less memory. Add the `export PATH=...` line to your shell configuration to make Picker available in new terminals. + +For use within the source directory, replace `make install` with `make build` and run commands through `./build/bin/picker`. + +## Check the installation + +```sh +picker --version +picker --check +``` + +`--check` reports the status of templates and language resources. The tutorial needs successful checks for templates and Python. You can add other languages when you need them. + +Next, export and run the [adder tutorial](../tutorials/first-dut.md) to check the full compilation and simulation process. + +## Use a release package + +[GitHub Releases](https://github.com/XS-MLVP/picker/releases) provides Linux AppImages, installation archives, and Python wheels. Choose a file for your machine's architecture. Wheels must also match the Python minor version. + +For an AppImage, make the downloaded file executable and run it. For an installation archive, extract the full directory and add its `bin` directory to `PATH`. Templates and runtime resources are located through the installation tree, so keep them together when distributing it. + +To install wheels, put Picker and the dependency wheels listed in the release notes into `wheels/`, then run: + +```sh +python3 -m venv .venv +. .venv/bin/activate +python -m pip install --no-index --find-links=wheels picker +python -m pip check +picker --check +``` + +Exporting new models also requires the Verilator, SWIG, and compilation tools listed above. + +## Build wheels locally + +From a source directory where you have run `make init`: + +```sh +python3 -m venv .venv +. .venv/bin/activate +python -m pip install build +make wheel PYTHON="$VIRTUAL_ENV/bin/python" +python -m pip install --no-index --find-links=dist picker +python -m pip check +``` + +The wheels are written to `dist/`. You can copy them to another environment with the same Python minor version and platform. diff --git a/doc/en/guides/internal-signals.md b/doc/en/guides/internal-signals.md new file mode 100644 index 00000000..dbf559fd --- /dev/null +++ b/doc/en/guides/internal-signals.md @@ -0,0 +1,75 @@ +# Access internal signals + +When debugging a circuit, you can read internal registers or change signals by hierarchical name. This page starts with the repository's `vpi` example, then describes other access methods. + +## Export a model with VPI + +Run from the repository root: + +```sh +picker export example/InternalSignals/vpi.v --sname vpi --lang python \ + --sim verilator --vpi --tdir build/docs-internal/vpi --autobuild false +make -C build/docs-internal/vpi -j4 +``` + +`--vpi` enables runtime signal lookup. This design has a clock named `clk` and an internal signal, `_v2_base`, that controls a counter's increment. + +## Find and change a signal + +Save this code as `build/docs-internal/inspect.py`: + + +```python +from vpi import DUTvpi + +dut = DUTvpi() +try: + dut.InitClock("clk") + dut.Step(1) + for name in dut.VPIInternalSignalList(): + print(name) + increment = dut.GetInternalSignal("vpi._v2_base", use_vpi=True) + assert increment is not None + increment.AsImmWrite() + increment.value = 9 + dut.Step(1) + before = dut.v2.value + dut.Step(1) + assert dut.v2.value == (before + 10) & 0xFF + print("v2 increment: 10") +finally: + dut.Finish() +``` + +Run: + +```sh +cd build/docs-internal +python3 inspect.py +``` + +`Step(1)` first runs circuit initialization, and `AsImmWrite()` makes internal signal writes immediate. The output lists accessible hierarchical names and should end with `v2 increment: 10`. The RTL adds `1 + _v2_base` each cycle, so writing 9 makes the counter advance by 10. + +For your own design, query names with `VPIInternalSignalList()`, then pass the actual hierarchical path to `GetInternalSignal()`. Use `prefix` and `deep` to narrow the search. + +## Choose an access method + +| Method | Configuration | Use | +| --- | --- | --- | +| Export selected internal signals | `--internal config-file` | Generate accessors for a known set of signals alongside ports | +| VPI lookup | `--vpi` | Enumerate and access signals by hierarchical name during debugging | +| Native memory access | `--rw mem_direct` | Direct reads and writes for Verilator/GSIM using the model's layout information | + +By default, `GetInternalSignal()` uses generated native layout information when available and otherwise queries VPI. `use_vpi=True` selects VPI explicitly. `example/CacheSignalCFG` contains a complete native-access project. + +## Access a native array + +For models with native layout information, obtain the array once and access its elements: + +```python +memory = dut.GetInternalSignal("Top.memory", is_array=True) +print(memory[0].value) +memory[1].value = 42 +``` + +Replace `Top.memory` with the actual name. Results are cached by name, so keep the array lookup mode consistent for each name. The native access path provides `index` and `is_array`. Use internal signal objects while their DUT is alive, and query them again after creating a new model. diff --git a/doc/en/guides/languages.md b/doc/en/guides/languages.md new file mode 100644 index 00000000..dc98737d --- /dev/null +++ b/doc/en/guides/languages.md @@ -0,0 +1,49 @@ +# Use a DUT from different languages + +`--lang` supports `python`, `cpp`, `java`, `scala`, `golang`, and `lua`. Picker generates the selected language's wrappers, build files, and port interfaces. + +## Build and run an existing example + +From the Picker source directory, build support for the languages you need. For example, Python and Java: + +```sh +make build NPROC=4 BUILD_XSPCOMM_SWIG=python,java +make test_Adder EXAMPLE_LANG=java +``` + +The second command exports Adder, compiles it, and runs `example/Adder/example.java`. Set `EXAMPLE_LANG` to `python`, `cpp`, `scala`, `golang`, or `lua` to run another example. The example script regenerates `output/Adder`. + +Java and Scala need a JDK; Scala also needs its toolchain. Go needs the Go compiler, and Lua needs an interpreter and development headers. Run `picker --check` to inspect resources for the selected language. + +## Export your own design + +For example, export a C++ model: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang cpp \ + --tdir build/AdderCpp --autobuild false +make -C build/AdderCpp -j4 +``` + +Use the corresponding `example/Adder/example.*` to learn the generated interface, then substitute your design and test. + +## Read and write signals + +| Language | Write | Read | +| --- | --- | --- | +| Python | `dut.a.value = 42` | `dut.sum.value` | +| C++ | `dut.a = 42` | `dut.sum.U()` | +| Java | `dut.a.Set(42)` | `dut.sum.U()` | +| Scala | `dut.a.Set(42)` | `dut.sum.U()` | +| Go | `dut.A.Set(42)` | `dut.Sum.U()` | +| Lua | `dut.a:Set(42)` | `dut.sum:U()` | + +Python integers support the full signal width. C++ `U()` / `S()` return the low 64 bits; use `GetBytes()` / `SetBytes()` for wide signals. Java and Scala provide large-integer wrappers. Go and Lua can use byte or string interfaces for wide values; consult the generated signatures and language examples. + +When a port name conflicts with a method, the generator adjusts it according to the language's naming rules, for example by adding `pin_`. Go's exported names start with a capital letter. + +## Distribute the generated model + +A compiled DUT package includes language interfaces, model libraries, and runtime resources. The default `--cp_lib true` copies runtime libraries. Distribute the complete package and run a short test in the target environment to check imports, signal access, and simulation stepping. + +Python extensions must match the target Python minor version, operating system, and architecture. diff --git a/doc/en/guides/simulation.md b/doc/en/guides/simulation.md new file mode 100644 index 00000000..ce8ae212 --- /dev/null +++ b/doc/en/guides/simulation.md @@ -0,0 +1,114 @@ +# Drive a simulation + +This page uses the generated Python DUT interface to set up clocks, apply reset, sample signals, and record results. For a complete model creation example, see the [adder tutorial](../tutorials/first-dut.md). + +## Set up a clock and reset + +For a DUT with `clock` and active-high `reset` ports, run this after creating the object: + +```python +dut.InitClock("clock") +dut.reset.value = 1 +dut.Step(2) +dut.reset.value = 0 +dut.Step(1) +``` + +`InitClock()` registers the clock pin. Each `Step(n)` then advances n complete cycles. This code holds reset for two cycles, releases it, and advances one more cycle. Set the port names, reset polarity, and duration to match your RTL protocol. + +During a test, write inputs, call `Step()`, then read outputs. For example: + +```python +dut.valid.value = 1 +dut.data.value = 42 +dut.Step(1) +print(dut.ready.value) +``` + +This fragment assumes the DUT has `valid`, `data`, and `ready` ports. + +## Sample at an edge + +Register a rising-edge callback with `StepRis()` or a falling-edge callback with `StepFal()`. This example reads `ready` after each rising edge: + +```python +def observe(cycle): + print(cycle, dut.ready.value) + +dut.StepRis(observe) +dut.Step(3) +``` + +The first callback argument is the cycle count. Put sampling, logging, or assertions in the callback, and advance the simulation with `Step()` in the main test flow. + +## Evaluate combinational logic + +Set inputs that need immediate writes to `AsImmWrite()`, then call `RefreshComb()` after assigning them: + +```python +dut.a.AsImmWrite() +dut.b.AsImmWrite() +dut.cin.AsImmWrite() +dut.a.value = 2 +dut.b.value = 3 +dut.cin.value = 1 +dut.RefreshComb() +assert dut.sum.value == 6 +``` + +This fragment uses the tutorial's Adder. Inputs are submitted immediately and combinational logic is evaluated while the cycle count stays unchanged. + + + +## Save waveforms and code coverage + +Enable recording when exporting the model: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-trace/Adder --autobuild false \ + -w trace.fst --coverage +make -C build/docs-trace/Adder -j4 +``` + +Save the following as `build/docs-trace/record.py`: + + +```python +from Adder import DUTAdder + +dut = DUTAdder(waveform_filename="trace.fst", coverage_filename="coverage.dat") +try: + dut.b.value = 1 + dut.cin.value = 0 + for value in range(4): + dut.a.value = value + dut.Step(1) + assert dut.sum.value == value + 1 +finally: + dut.Finish() +``` + +Run the script and inspect the output files: + +```sh +cd build/docs-trace +python3 record.py +ls -lh trace.fst coverage.dat +``` + +Open `trace.fst` in a waveform viewer such as GTKWave. You should see `a` change from 0 to 3 and `sum` from 1 to 4. Process the code coverage file with the simulator's coverage tools. + +For a longer simulation, call `PauseWaveformDump()` to pause recording and `ResumeWaveformDump()` before the interval of interest. Call `FlushWaveform()` to inspect the file before the simulation ends. `Finish()` ends the simulation and completes output handling. + +## Save and restore checkpoints + +For a Verilator project, add `--checkpoints` during export, then call: + +```python +dut.CheckPoint("state.bin") +dut.Step(10) +dut.Restore("state.bin") +``` + +A checkpoint saves simulator state. Save and restore the Python reference model, queues, and random generator state alongside it in your test program. See the [DUT API](../reference/dut-api.md) for return values and simulator support. diff --git a/doc/en/guides/uvm-tlm.md b/doc/en/guides/uvm-tlm.md new file mode 100644 index 00000000..8ec6f00d --- /dev/null +++ b/doc/en/guides/uvm-tlm.md @@ -0,0 +1,59 @@ +# Generate a UVM transaction bridge + +Use `picker pack` with an existing UVM environment to generate Python transaction classes and UVM agents. They exchange data between Python tests and a SystemVerilog testbench. + +## Generate from a transaction class + +`example/Pack/adder_trans.sv` defines `adder_trans`, derived from `uvm_sequence_item`, with `a`, `b`, `cin`, `sum`, and `cout` fields. Run from the repository root: + +```sh +picker pack example/Pack/adder_trans.sv --example +``` + +The output is written to `uvmpy/`: + +```text +uvmpy/ +├── Makefile +├── example.py +├── example.sv +└── adder_trans/ + ├── __init__.py + ├── xagent.py + ├── xagent.sv + ├── utils_pkg.sv + └── ... +``` + +`xagent.py` provides the Python transaction interface, and `xagent.sv` provides the UVM agent. `example.py` and `example.sv` show how the two sides connect and exchange transactions. + +Put one transaction class in each input file. For multiple transactions, collect the files with `--filelist`; see `example/Pack/03_MultiTrans` for an example. + +## Generate from RTL ports + +You can also generate a transaction and DUT wrapper from module ports: + +```sh +picker pack --from-rtl example/Adder/Adder.v --name Adder \ + --generate-dut --example +``` + +This generates `uvmpy/Adder/Adder_trans.sv` and its agent. `--name Adder` selects the module and package name; `--generate-dut` adds a wrapper for pin access. If the output directory already exists, save any manual changes, then use a new directory or regenerate with `--force`. + +## Compile and run + +The generated example Makefile uses VCS, UVM, UVMC, and SystemC, with Verdi PLI for waveforms. Set `VCS_HOME`, `UVM_HOME`, `UVMC_HOME`, and `VERDI_HOME` for your installation. Make sure `vcs`, `vlogan`, `syscan`, SWIG, and Python development tools are available, then run: + +```sh +make -C uvmpy +``` + +The Makefile compiles the bridge library and UVM environment, then runs `example.py`. It locates the TLM SDK under `share/xspcomm/tlm` in the installation tree. Set `XSP_COMM_TLM` when using a separately installed SDK. + +## Connect an existing testbench + +Start from the generated `example.sv`. Connect the driver's transaction receive method to your design interface and send monitor samples back to Python. Use matching channel names and the same transaction field definitions on both sides. + +`example/Adder/example-uvm.sv` shows a complete connection: the driver writes `a`, `b`, and `cin` after receiving a transaction, and the monitor samples and returns `sum` and `cout`. Adapt these driving and sampling steps for your design. + +For build or communication failures, first check generation logs, tool paths, and channel names. See the [pack reference](../reference/cli.md#pack) for command options. diff --git a/doc/en/index.md b/doc/en/index.md new file mode 100644 index 00000000..8fb54751 --- /dev/null +++ b/doc/en/index.md @@ -0,0 +1,24 @@ +# Picker documentation + +Picker turns Verilog/SystemVerilog designs into Python, C++, Java, Scala, Go, or Lua modules. Your tests can assign inputs, advance the simulation, read outputs, and check the results with assertions. + +Start with [installation](guides/installation.md), then follow the [adder tutorial](tutorials/first-dut.md) to run your first test. + +## Use Picker + +| Task | Guide | +| --- | --- | +| Export your RTL | [Export an RTL project](guides/export.md) | +| Set up clocks, reset, and sampling | [Drive a simulation](guides/simulation.md) | +| Save waveforms and collect code coverage | [Record simulation results](guides/simulation.md#recording) | +| Inspect internal registers or memories | [Access internal signals](guides/internal-signals.md) | +| Use C++, Java, or another language | [Language examples](guides/languages.md) | +| Exchange transactions between Python and UVM | [Generate a UVM transaction bridge](guides/uvm-tlm.md) | + +## Look up an interface + +The [CLI reference](reference/cli.md) lists export options. The [DUT API](reference/dut-api.md) describes generated objects and signal access. Use [simulator and language support](reference/compatibility.md) to choose a toolchain, and [troubleshooting](reference/troubleshooting.md) to diagnose errors. + +## Understand and change Picker + +[How generation and simulation work](explanation/architecture.md) follows RTL into a callable simulation module. The [development guide](development/contributing.md) covers source directories and tests. [Documentation maintenance](development/documentation.md) covers bilingual editing, site previews, and Wiki export. diff --git a/doc/en/reference/cli.md b/doc/en/reference/cli.md new file mode 100644 index 00000000..d13962d7 --- /dev/null +++ b/doc/en/reference/cli.md @@ -0,0 +1,70 @@ +# Command-line reference + +Use `picker --help`, `picker export --help`, and `picker pack --help` for command help. The tables below cover global options, RTL export, and UVM packing. + +## Global options + +| Option | Purpose | +| --- | --- | +| `-h, --help` | Show help | +| `-v, --version` | Show build version | +| `--check` | Inspect templates and language resources; read every result | +| `--show_default_template_path` | Print template location | +| `--show_xcom_lib_location_cpp` | Print C++ runtime include/lib locations | +| `--show_xcom_lib_location_python/java/scala/golang/lua` | Locate one language's resources; use one complete option name | + +## export + +| Option | Argument/default | Purpose | +| --- | --- | --- | +| `file` | One or more RTL files | Source inputs; required without `--sname` | +| `--fs, --filelist` | Files or lists, multiple allowed | Additional sources, includes and definitions | +| `--sname, --source_module_name` | Module names, multiple allowed | Select tops | +| `--tname, --target_module_name` | Name | Generated module name; defaults to source name | +| `--tdir, --target_dir` | Path | Destination; a trailing `/` adds a module-named directory | +| `--sdir, --source_dir` | Template directory | Override installed templates | +| `--lang, --language` | `python` | cpp/python/java/scala/golang/lua | +| `--sim` | `verilator` | verilator/vcs/gsim/uvs; requires the toolchain | +| `--rw, --access-mode` | `dpi` | dpi or mem_direct; see the access guide for support | +| `--internal` | Configuration file | Select internal signals | +| `--vpi` | Flag, off | Compile VPI support | +| `--checkpoints` | Flag, off | Compile supported save/restore functionality | +| `-w, --wave_file_name` | Filename, empty | Configure waveform format/output | +| `-c, --coverage` | Flag, off | Compile simulator coverage | +| `-F, --frequency` | `100MHz` | VCS timing; accepts Hz/KHz/MHz/GHz | +| `--verdi-mode` | `legacy` | VCS Verdi integration; modern selects the newer debug setup | +| `--cp_lib, --copy_xspcomm_lib` | `true` | Copy runtime libraries | +| `-V, --vflag` | String | Simulator compilation options | +| `-S, --sflag` | String list | slang parsing options | +| `-C, --cflag` | String | C++ compiler options | +| `-e, --example` | Flag, off | Generate/build an example | +| `--autobuild` | `true` | Build after generation | +| `-j, --build-threads` | 0 | Parallelism; 0 uses all cores | +| `--verbose` | Flag, off | Additional diagnostic output | + +Quote arguments containing spaces, for example `-V '--trace -Wno-fatal'`. See [simulator support](compatibility.md) for tool environments. + +## pack + +| Option | Purpose | +| --- | --- | +| `file` | SV file containing transactions | +| `-f, --filelist` | Transaction file list | +| `--from-rtl` | Derive a transaction from RTL ports | +| `-d, --generate-dut` | Generate a DUT wrapper for pin access | +| `-r, --rename` | Rename a transaction | +| `-n, --name` | Generated package name | +| `-e, --example` | Generate an example project | +| `-c, --force` | Delete and replace an existing generated directory | + +See [UVM transaction bridges](../guides/uvm-tlm.md) for generated directories and examples. + +## Environment variables + +`DUMPVARS_OPTION` passes options to VCS `$fsdbDumpvars`, for example: + +```sh +DUMPVARS_OPTION="+mda" picker export rtl/top.sv --sname Top --sim vcs -w trace.fsdb +``` + +This fragment requires real RTL and configured VCS/Verdi tools. `+mda` enables array waveform support in that environment. diff --git a/doc/en/reference/compatibility.md b/doc/en/reference/compatibility.md new file mode 100644 index 00000000..8b3247f5 --- /dev/null +++ b/doc/en/reference/compatibility.md @@ -0,0 +1,42 @@ +# Simulator and language support + +## Simulators + +`picker export --sim` accepts these values: + +| Option | Environment | Notes | +| --- | --- | --- | +| `verilator` | Verilator and a C++ compiler | Default; used by the tutorials | +| `vcs` | VCS and its license; Verdi for FSDB | DPI/VPI, waveform, and code coverage integration | +| `gsim` | The GSIM toolchain | Export, simulation stepping, and native signal access integration | +| `uvs` | The UVS toolchain and license | Simulation stepping and USDB waveform integration | + +Enable waveforms and checkpoints at export time: + +| Feature | Export option | Support | +| --- | --- | --- | +| FST / VCD waveforms | `-w trace.fst` / `-w trace.vcd` | Verilator | +| FSDB waveforms | `-w trace.fsdb` | VCS + Verdi | +| USDB waveforms | `-w trace.usdb` | UVS | +| Code coverage | `--coverage` | Verilator and VCS; enabled metrics depend on build configuration | +| Checkpoints | `--checkpoints` | Verilator | +| Native memory access | `--rw mem_direct` | Verilator and GSIM | + +## Languages + +| `--lang` | Runtime or compiler | +| --- | --- | +| `python` | Python and matching development headers | +| `cpp` | A C++20 compiler | +| `java` | JDK | +| `scala` | JDK and Scala | +| `golang` | Go and a C++ compiler | +| `lua` | Lua and development headers | + +Export requires installed binding resources for the selected language. See the [language guide](../guides/languages.md) for checks and example commands. + +## Platforms and distribution + +Linux is the primary build environment. macOS supports Verilator and source builds, with dynamic multi-instance use limited by platform loading behavior. Python wheels are specific to a Python minor version, operating system, and architecture; for example, `cp312` means CPython 3.12. + +Use generated models with the toolchain and runtime libraries used during export. Regenerate and recompile after replacing those dependencies. Before distributing a model, run the short test from the [adder tutorial](../tutorials/first-dut.md) in the target environment to check imports, wide signals, and simulation stepping. diff --git a/doc/en/reference/dut-api.md b/doc/en/reference/dut-api.md new file mode 100644 index 00000000..0e79ec79 --- /dev/null +++ b/doc/en/reference/dut-api.md @@ -0,0 +1,86 @@ +# Python DUT API + +The exported Python package provides a `DUT` class. These signatures come from the Python template; see the [language guide](../guides/languages.md) for other wrappers and [simulator support](compatibility.md) for waveforms, coverage, and checkpoints. + +## Create an object and access ports + +```python +from Adder import DUTAdder + +dut = DUTAdder() +dut.a.value = 42 +print(dut.a.value) +print(dut["a"].value) +dut.Finish() +``` + +`DUT(*args, **kwargs)` creates a model. Positional arguments are passed to the simulator. The keyword arguments `waveform_filename` and `coverage_filename` set output paths and require the corresponding features at export time. + +`dut.pin` and `dut["pin"]` return the same port object. Write through `.value` or `Set(value)`. Reading `.value` returns an unsigned Python integer of the full signal width. The port attribute itself is read-only. + +## Clocks and execution + +| Method | Behavior and return value | +| --- | --- | +| `InitClock(name)` | Register the named port as a clock pin; return `None` | +| `Step(i=1)` | Advance i complete cycles and refresh signals; return `None` | +| `StepRis(callback, args=(), kwargs={})` | Register a rising-edge callback as `callback(cycle, *args, **kwargs)` | +| `StepFal(callback, args=(), kwargs={})` | Register a falling-edge callback with the same arguments | +| `RefreshComb()` | Evaluate combinational logic while keeping the cycle count; inputs should already be submitted | +| `Finish()` | End the simulation and complete output handling; call after use | +| `AtClone()` | Reinitialize simulator state in a forked child process | + +Callbacks run after evaluation and signal refresh at the corresponding edge. Drive the RTL reset port to apply reset; see [clock and reset setup](../guides/simulation.md). + +While a test framework holds clock control, `Step()` reports an error. Use the framework's execution method during that period. Shutdown in simulators such as VCS and UVS may terminate the process, so arrange test reporting before `Finish()`. + +## Waveforms + +| Method | Behavior and return value | +| --- | --- | +| `SetWaveform(filename)` | Set the output path, using the format configured at export time | +| `GetWaveFormat()` | Return an extension such as `fst`, or an empty string when disabled | +| `PauseWaveformDump()` | Pause recording | +| `ResumeWaveformDump()` | Resume recording | +| `WaveformPaused()` | Return 1 when paused and 0 when recording | +| `FlushWaveform()` | Write the waveform buffer to the file | + +See [save waveforms](../guides/simulation.md#recording) for export options and a complete script. Frequent flushing adds I/O and affects FST compression efficiency. + +## Code coverage and checkpoints + +| Method | Behavior and return value | +| --- | --- | +| `SetCoverage(filename)` | Set the simulator coverage output location | +| `ResetCoverage()` | Reset coverage counters; currently implemented by the VCS path | +| `GetCovMetrics()` | Return the enabled metric mask; 0 means disabled | +| `CheckPoint(name)` | Save simulator state to a file; requires `--checkpoints`; Python returns `None` | +| `Restore(name)` | Restore simulator state from a checkpoint; Python returns `None` | + +Bits 0–5 of `GetCovMetrics()` represent line, cond, fsm, toggle, branch, and assert. + +## Internal signals + +| Method | Behavior and return value | +| --- | --- | +| `GetInternalSignal(name, index=-1, is_array=False, use_vpi=False)` | Return a signal object by name, or a list with `is_array=True` | +| `GetInternalSignalList(prefix="", deep=99, use_vpi=False)` | List accessible names, preferring native layout information and then VPI | +| `VPIInternalSignalList(prefix="", deep=99)` | Enumerate hierarchical names through VPI | + +For native lookup, `prefix` is a substring filter. For VPI, `prefix` and `deep` select the starting hierarchy and search depth. `index` and `is_array` apply to native layout lookup. + +Results are cached by `name`, and later calls reuse the first object. An ordinary failed lookup returns `None`; an explicit `use_vpi=True` lookup failure raises an assertion. See [access internal signals](../guides/internal-signals.md) for examples. + +## Python asynchronous methods + +| Method | Behavior | +| --- | --- | +| `await dut.AStep(n)` | Wait for n simulation cycles | +| `await dut.ACondition(fn)` | Check fn at cycle notifications and return when it becomes true | +| `await dut.RunStep(n)` | Advance n cycles, allowing other coroutines to run between cycles | + +Run waiting coroutines alongside a coroutine that advances the simulation. `AStep()` and `ACondition()` use Python cycle notifications from the clock. + +## Framework integration + +`GetXPort()` returns the DUT's `XPort` collection and `GetXClock()` returns its `XClock`. Frameworks can use these objects to manage signals and clocks. Use them and internal signal objects while the DUT is alive. diff --git a/doc/en/reference/troubleshooting.md b/doc/en/reference/troubleshooting.md new file mode 100644 index 00000000..dfaee063 --- /dev/null +++ b/doc/en/reference/troubleshooting.md @@ -0,0 +1,36 @@ +# Troubleshooting + +Keep the complete export command and the first error. The parser, compiler, or simulator usually reports the specific cause before a later `make` failure. + +## Export and compilation + +| Symptom | Check and action | +| --- | --- | +| Templates cannot be found | Run `picker --check` and `picker --show_default_template_path`; use the full installation tree or set `--sdir` | +| Top module cannot be found | Check the `--sname` spelling, source list, and conditional compilation macros | +| An include file is missing | Add its directory with `+incdir+` in the file list and check relative paths | +| Port widths differ from expectations | Check top-level parameters, macros, and the elaborated interface | +| SWIG or the compiler cannot be found | Check PATH and prepare the tools in [installation](../guides/installation.md) | +| Language resources are missing | Inspect the corresponding `picker --check` entry and build the required bindings | + +## Python imports and signals + +| Symptom | Check and action | +| --- | --- | +| `No module named 'Adder'` | Run from the generated package's parent directory or add that directory to PYTHONPATH | +| A native extension fails to load | Check the Python minor version, platform, and architecture; rebuild in the same environment | +| `libxspcomm` or a library symbol is missing | Restore the complete generated package and runtime resources; regenerate and compile after replacing dependencies | +| `XData attributes of DUT are read-only` | Assign values through `dut.pin.value = value` | +| Outputs stay unchanged after a write | Call `Step()` after writing inputs; see [drive a simulation](../guides/simulation.md) for combinational evaluation | +| High bits of a wide signal are lost | Use Python `.value` or the full C++ byte interface, and check the widths of temporary variables in the test | +| Internal signal lookup fails | Enable VPI or native layout at export time, enumerate actual names, then query the object | + +## Waveforms and UVM + +For an empty waveform, check `-w` in the export command, the runtime output path, and pause state. Call `Finish()` to complete output handling. The export configuration determines the file format. See [save waveforms](../guides/simulation.md#recording) for complete commands. + +For UVM build failures, check VCS, UVM, UVMC, Verdi, and SDK paths. If transactions do not arrive, check matching channel names and whether the driver and monitor execute; see [UVM transaction bridges](../guides/uvm-tlm.md). + +## Report a problem + +When opening a [GitHub issue](https://github.com/XS-MLVP/picker/issues), include minimal RTL, file lists, the complete export command, and error logs, plus `picker --version`, operating system, Python, and simulator versions. For private designs, provide a public example that retains the relevant syntax or interface. diff --git a/doc/en/tutorials/first-dut.md b/doc/en/tutorials/first-dut.md new file mode 100644 index 00000000..76c9da12 --- /dev/null +++ b/doc/en/tutorials/first-dut.md @@ -0,0 +1,110 @@ +# Test an adder with Python + +This tutorial exports a 128-bit adder as a Python module. You will calculate `2 + 3 + 1`, then check carry and overflow with a repeatable test script. + +Before starting, complete [installation](../guides/installation.md) and prepare Picker, Verilator, SWIG, and Python. + +## 1. Get the adder + +Clone the repository and enter its root directory. If you already have a checkout, enter that directory: + +```sh +git clone https://github.com/XS-MLVP/picker.git +cd picker +``` + +Open `example/Adder/Adder.v` and find the `Adder` module. It has these ports: + +| Port | Direction | Width | Meaning | +| --- | --- | --- | --- | +| `a`, `b` | Input | 128 | The two operands | +| `cin` | Input | 1 | Carry input | +| `sum` | Output | 128 | Low 128 bits of the result | +| `cout` | Output | 1 | Carry output | + +The module computes `assign {cout, sum} = a + b + cin;`. It is a combinational circuit, so updating the inputs is enough to calculate a new result. + +## 2. Export and compile + +Run these commands from the repository root: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-adder/Adder --autobuild false +make -C build/docs-adder/Adder -j4 +``` + +The first command selects the `Adder` module and generates a project in `build/docs-adder/Adder`. The second compiles the RTL and Python interface. After compilation, the `Adder` directory is an importable Python package. + +## 3. Calculate a sum + +Save the following code as `build/docs-adder/check.py`: + + +```python +from Adder import DUTAdder + +dut = DUTAdder() +dut.a.value = 2 +dut.b.value = 3 +dut.cin.value = 1 +dut.Step(1) +print(f"sum={dut.sum.value}, cout={dut.cout.value}") +dut.Finish() +``` + +Run the script from the package's parent directory: + +```sh +cd build/docs-adder +python3 check.py +``` + +The output should include: + +```text +sum=6, cout=0 +``` + +`DUTAdder()` creates a simulation model. Each port has an attribute with the same name; `.value` reads or writes its value. `Step(1)` submits the inputs to the simulator and updates the outputs. `Finish()` ends the simulation. + +Change `cin.value` to `0` and run the script again. You should now get `sum=5, cout=0`. + +## 4. Check carry and overflow + +Replace `check.py` with the code below. It checks three input sets with assertions: an ordinary sum, the maximum value plus one, and two values with the high bit set. + + +```python +from Adder import DUTAdder + +mask = (1 << 128) - 1 +cases = [(2, 3, 1), (mask, 1, 0), (1 << 127, 1 << 127, 1)] +dut = DUTAdder() +try: + for a, b, cin in cases: + dut.a.value = a + dut.b.value = b + dut.cin.value = cin + dut.Step(1) + expected = a + b + cin + assert dut.sum.value == (expected & mask) + assert dut.cout.value == (expected >> 128) + print(f"sum={dut.sum.value}, cout={dut.cout.value}") + print("Adder: 3 cases passed") +finally: + dut.Finish() +``` + +Run `python3 check.py` again. The output should include: + +```text +sum=6, cout=0 +sum=0, cout=1 +sum=1, cout=1 +Adder: 3 cases passed +``` + +Python integers hold the full result. `expected & mask` selects the low 128 bits for comparison with `sum`; `expected >> 128` selects the carry for comparison with `cout`. If a result differs, an assertion identifies the failing check. + +You have exported a model, supplied inputs, advanced the simulation, and checked outputs. Next, [export your own RTL](../guides/export.md), or learn to [set up clocks and reset](../guides/simulation.md) for a sequential circuit. diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/install-macos.en.md b/doc/install-macos.en.md index 4e919374..b3e98759 100644 --- a/doc/install-macos.en.md +++ b/doc/install-macos.en.md @@ -1,59 +1,6 @@ -# Installing Picker on macOS +# Installation / 安装 -## Known Limitations +[中文](zh/guides/installation.md) | [English](en/guides/installation.md) -Due to differences between macOS and Linux in system kernels and development toolchains, Picker has some functional limitations on macOS: - -1. The emulator only supports Verilator -2. Dynamic multi-instance is not supported; please use static multi-instance if multiple instances are needed - -Therefore, we strongly recommend using Picker in a Linux environment for more comprehensive feature support. - -## Dependency Installation - -> [!WARNING] -> We recommend installing Picker dependencies on macOS via [Homebrew](https://brew.sh/). If you do not use Homebrew for dependency setup, you will need to troubleshoot any problems yourself. -> -> The instructions below assume you have Homebrew properly configured. - -### Installing Dependencies - -```bash -brew install cmake lcov lld llvm pkgconf python3 swig systemc verilator zlib -``` - -These dependencies are required when Picker exports C++ and Python DUTs. Among them: - -- `llvm` is optional; you can also use the system’s default `clang` (AppleClang), but AppleClang typically compiles larger DUTs more slowly. -- `lld` is optional but speeds up linking. If not installed, the system will use the default `ld` (Apple Linker). -- If multiple Python versions exist on your system, ensure tools like `python` and `python-config` are not mixed across versions to avoid compilation errors caused by ABI mismatch. - -If you want support for other languages like Java, Go, Lua, or Scala2, please configure the relevant toolchains yourself; this guide does not cover that. - -## Building - -> [!TIP] -> Please refer to the [README.md](README.md) in the project root for build steps. - -Here we demonstrate installing picker to the `~/Applications/Picker` folder. - -First, run this command to compile and install: - -```shell -make init -make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/Applications/Picker" -``` - -This installs picker under: - -- `$HOME/Applications/Picker/bin` -- `$HOME/Applications/Picker/share/picker` -- `$HOME/Applications/Picker/lib` - -Then configure your environment variables: - -```shell -export PATH="$HOME/Applications/Picker/bin:$PATH" -``` - -Finally, run `picker --check` to verify the installation is complete. +完整说明见上方的中英文页面。 +Follow the links above for the complete guide in either language. diff --git a/doc/install-macos.zh.md b/doc/install-macos.zh.md index 2ec1fe19..b3e98759 100644 --- a/doc/install-macos.zh.md +++ b/doc/install-macos.zh.md @@ -1,59 +1,6 @@ -# 在 macOS 上安装 Picker +# Installation / 安装 -## 已知限制 +[中文](zh/guides/installation.md) | [English](en/guides/installation.md) -由于 macOS 与 Linux 在系统内核和开发工具链方面存在差异,Picker 在 macOS 上使用时会有一些功能限制: - -1. 仿真器仅支持 Verilator -2. 不支持动态多实例,如需多实例请使用静态多实例 - -因此,我们强烈建议在 Linux 环境下使用 Picker,以获得更全面的功能支持。 - -## 依赖安装 - -> [!WARNING] -> 我们建议通过 [Homebrew](https://brew.sh/) 来安装 macOS 上的 Picker 依赖。如果您没有使用 Homebrew 进行依赖配置,遇到的问题需要您自行排查解决。 -> -> 以下说明均基于已正确配置 Homebrew 的环境。 - -### 安装依赖项 - -```bash -brew install cmake lcov lld llvm pkgconf python3 swig systemc verilator zlib -``` - -上述依赖都是 Picker 在导出 C++ 和 Python 的 DUT 时所需的。其中: - -- `llvm` 不是必选项,您也可以使用系统自带的 `clang`(AppleClang),但在编译较大规模 DUT 时,AppleClang 的编译速度通常较慢。 -- `lld` 也非必选,但它能够加快链接速度。如果不安装,系统将使用默认的 `ld` (Apple Linker)。 -- 如果您的系统存在多个 Python 版本,请确保 `python`、`python-config` 等工具不会在不同版本间混用,以避免因 ABI 不匹配引起的编译错误。 - -如果您想启用对其他语言的支持(例如 Java、Go、Lua、Scala2 等),请自行配置相关的工具链,这里不再详细说明。 - -## 构建 - -> [!TIP] -> 请参考项目根目录中的 [README.md](README.md) 了解构建步骤。 - -在这里,将演示把 picker 安装到 `~/Applications/Picker` 文件夹下。 - -首先,执行下面的命令进行编译安装: - -```shell -make init -make install ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/Applications/Picker" -``` - -安装完成后,picker 相关文件会位于: - -- `$HOME/Applications/Picker/bin` -- `$HOME/Applications/Picker/share/picker` -- `$HOME/Applications/Picker/lib` - -之后配置好环境变量: - -```shell -export PATH="$HOME/Applications/Picker/bin:$PATH" -``` - -最后,执行 `picker --check` 检查是否完成安装。 +完整说明见上方的中英文页面。 +Follow the links above for the complete guide in either language. diff --git a/doc/maintainer-guidance.md b/doc/maintainer-guidance.md index 0fc3af7e..61074df4 100644 --- a/doc/maintainer-guidance.md +++ b/doc/maintainer-guidance.md @@ -1,81 +1,6 @@ -# Maintaining Picker +# Release maintenance / 发行维护 -## Versions and dependencies +[中文](zh/development/releases.md) | [English](en/development/releases.md) -Picker and xcomm have independent `vX.Y.Z` package tags. Picker derives its -package, CLI and CMake release versions from its own tag using setuptools-scm. -Release a compatible xcomm version before releasing Picker. - -| Setting | Source | Current requirement | -| --- | --- | --- | -| Development xcomm source | `.build-config.yml` | Exact tested commit; `XCOMM_SOURCE_REF` can override it | -| Python dependency | `pyproject.toml` | `xspcomm>=1.0.0.dev0,<2` | -| Development xcomm wheel | Development CI | `1.0.0.dev0` preview until xcomm 1.0 is released | -| Native ABI | `xspcomm.abi_version()` | 3; packages contain `libxspcomm.so.3` | -| Coverage descriptors | `XTriggerEngine.CoverageVersion()` | 5 | - -Package version, native ABI and descriptor protocol are separate identifiers. -When updating xcomm, align the source pin, Python range and preview version, -then rebuild native clients and generated DUT extensions against matching -headers and runtime. ABI checks cannot be replaced by a package version range. - -## Local build and validation - -Use a compiler, CMake, SWIG >= 4.2, Python development headers and a JDK -for Java tests. Run `make init` when source dependencies are missing. Build -from a clean checkout with a fresh wheel output directory; `make wheel` does -not align an existing xcomm checkout to the dependency pin or install packages -into the interpreter. - -```sh -python3 -m venv /tmp/picker-build -/tmp/picker-build/bin/python -m pip install build -make unit_tests BUILD_XSPCOMM_SWIG=python,java -SETUPTOOLS_SCM_PRETEND_VERSION_FOR_XSPCOMM=1.0.0.dev0 \ - make wheel PYTHON=/tmp/picker-build/bin/python -bash scripts/build/verify-wheel.sh -make -C test all -``` - -The preview override affects only xcomm. Picker keeps its Git-derived version. -CI's native build script refuses to switch an xcomm checkout with local changes. -Keep `-O3`, the native `-fno-strict-aliasing` flags and signal-value regressions -enabled. Wheel verification installs both packages into a fresh environment and -checks dependency consistency, native APIs, clock ownership and CLI exit codes. - -## Release procedure - -1. Publish the compatible xcomm release. Tagged CI selects a published stable - release satisfying `pyproject.toml`; it never uses a development preview. -2. Give the Picker master PR exactly one label: `release:patch`, `release:minor` - or `release:major`. Require the version-label and build checks in branch - protection, and test the PR against current master. Merge queues need - `merge_group` checks before they can be used. -3. After merge, **Version policy** creates the next tag and explicitly dispatches - **Tagged CI**. Direct master pushes without an associated merged PR do not - create a tag. Wait for tagging to finish before merging the next release PR. -4. Tagged CI builds and validates the exact tag: CPython 3.12 Linux x86-64 wheel, - plus x86-64/aarch64 AppImages and native archives, using one xcomm release. -5. After bundle upload, Tagged CI dispatches **Release Picker** with its run ID. - The publisher waits up to 60 minutes for successful completion, verifies the - bundle hashes and tag SHA, and publishes those exact artifacts without - rebuilding. GitHub Releases are not automatically uploaded to PyPI. - -Only tags on master's first-parent line that identify merged PR results are -accepted by the tagging/build policy. Configure a `v*` tag ruleset to restrict -manual creation or replacement. Do not publish the current Picker sdist as a -pip fallback: it omits vendored build dependencies; use a full source checkout -when a matching wheel is unavailable. - -## Recovery - -- Build failed: rerun **Tagged CI** with the existing tag and a compatible - published xcomm version. Do not move the tag. -- Publication failed: rerun **Release Picker** with the successful Tagged CI - run ID; it downloads the same checked bundle. -- Merge did not create a tag: inspect **Version policy**, then use its manual - bump input if recovery is needed. - -Generated DUTs may copy xcomm libraries. The package checks do not establish -that independently packaged DUT extensions load the same runtime instance; -verify ABI compatibility and relocation separately before publishing DUT wheels. +完整说明见上方的中英文页面。 +Follow the links above for the complete guide in either language. diff --git a/doc/zh/development/contributing.md b/doc/zh/development/contributing.md new file mode 100644 index 00000000..fc4dbeee --- /dev/null +++ b/doc/zh/development/contributing.md @@ -0,0 +1,47 @@ +# 开发与测试 + +在源码目录完成[安装步骤](../guides/installation.md)后,即可修改、编译和运行测试。先阅读[生成与运行原理](../explanation/architecture.md),有助于确定改动位置。 + +## 源码目录 + +| 路径 | 内容 | +| --- | --- | +| `src/picker.cpp` | 命令行参数和 export/pack 流程 | +| `src/parser/` | RTL、事务、文件列表和信号布局解析 | +| `src/codegen/` | 整理解析结果,生成模板数据 | +| `template/lib/` | 模拟器包装和构建配置 | +| `template/python/` 等语言目录 | 生成的语言接口及构建模板 | +| `test/` | 单元测试、导出集成测试和发布脚本测试 | +| `example/` | 可运行的设计与测试示例 | +| `doc/zh/`、`doc/en/` | 中英文文档 | + +修复生成代码时,在对应模板中修改,然后重新导出示例验证。`dependence/` 下的库各自维护,修改依赖时在其仓库单独提交。 + +## 运行测试 + +构建并执行 C++ 单元测试: + +```sh +make unit_tests NPROC=4 BUILD_XSPCOMM_SWIG=python,java +``` + +按改动选择集成测试: + +| 修改内容 | 测试命令 | +| --- | --- | +| Python 导出与模板 | `make -C test export_python` | +| 文件列表 | `make -C test export_filelist` | +| 复杂端口解析 | `make -C test export_complex_port` | +| 内部信号与 VPI | `make -C test export_vpi_python` | +| 事务打包 | `make -C test pack_transaction` | +| RTL 转事务 | `make -C test pack_from_rtl` | +| 发布脚本 | `python3 -m unittest discover -s test/release -v` | +| 文档 | [检查与预览](documentation.md) | + +完整集成测试使用 `make -C test all`,需要对应语言和模拟器环境。测试的 preflight 会检查绑定,缺失时可能重新构建;需要保留其他构建产物时使用独立 checkout。记录实际执行的测试和工具缺失导致的跳过项。 + +## 提交改动 + +在独立分支修改并向 `master` 提交 PR。说明问题的触发方式、修改后的行为和运行过的测试。接口变更同步更新中英文参考和示例。 + +每个 PR 选择一个 `release:patch`、`release:minor` 或 `release:major` 标签。合并后的发布过程见[发行维护](releases.md)。问题报告需要的材料见[故障排查](../reference/troubleshooting.md)。 diff --git a/doc/zh/development/documentation.md b/doc/zh/development/documentation.md new file mode 100644 index 00000000..ae031ffd --- /dev/null +++ b/doc/zh/development/documentation.md @@ -0,0 +1,56 @@ +# 维护文档与 Wiki + +中文正文放在 `doc/zh`,英文正文放在 `doc/en`,对应页面使用相同相对路径。修改正文时同步两种语言,导航在 `mkdocs.yml` 中维护。 + +## 按读者的需要组织内容 + +采用 [Diátaxis](https://diataxis.fr/) 的四种文档类型: + +| 类型 | 读者需要什么 | 写作方式 | +| --- | --- | --- | +| 教程 | 在指导下完成一次练习 | 给出连续的小步骤,每一步都有能观察到的结果 | +| 操作指南 | 完成一个已知任务 | 说明操作、必要选项和结果检查,例如“保存波形” | +| 接口参考 | 查清一个参数或方法 | 按接口分组,准确写出签名、默认值、返回值和使用条件 | +| 原理说明 | 理解设计和行为 | 解释对象之间的关系、调用过程及设计原因 | + +教程中先让读者操作并看到结果,再引入理解下一步所需的概念。详细参数链接到参考页,设计原因链接到原理页。 + +标题使用具体动作,正文直接说明做法。例如:“调用 `Finish()` 完成输出,然后打开波形文件。”说明限制时写清触发条件和影响,放在相关操作或接口旁。采用 [Google 技术写作指南](https://developers.google.com/style/highlights)建议的直接、清晰表达。 + +## 编写示例 + +标明命令执行目录、代码保存路径和预期输出。完整脚本可直接复制运行;片段说明已有的对象和环境。中文和英文使用相同的可执行代码,将解释放在正文。 + +## 预览网站 + +在仓库根目录执行: + +```sh +python3 -m venv /tmp/docs-venv +/tmp/docs-venv/bin/python -m pip install -r requirements-docs.txt +/tmp/docs-venv/bin/python scripts/docs.py check +/tmp/docs-venv/bin/python -m mkdocs build --strict +/tmp/docs-venv/bin/python -m mkdocs serve -a 127.0.0.1:8000 +``` + +浏览器打开 `http://127.0.0.1:8000`,检查语言切换、导航、全文搜索和代码显示。静态站点输出到 `build/docs-site`。 + +`check` 校验中英文页面对应关系、导航、链接、锚点和 Python 语法。完整可执行代码块前添加 `` 或 ``,可以通过以下命令运行: + +```sh +/tmp/docs-venv/bin/python scripts/docs.py test --python /path/to/runtime/bin/python +``` + +Picker 的示例需要先导出教程中的 Adder、带波形和覆盖率的 Adder,以及内部信号指南中的 vpi。将带记录功能的 Adder 和 vpi 包放在同一个目录后,用 `--cwd` 指定该目录。 + +## 导出 GitHub Wiki + +网站和 Wiki 都由同一份 Markdown 生成。在空目录导出: + +```sh +/tmp/docs-venv/bin/python scripts/docs.py wiki --output /tmp/picker-wiki +``` + +输出包含双语页面、首页、侧栏、页脚和文件清单,页面链接已转换为 Wiki 名称。维护者审阅后,将这些文件同步到 `picker.wiki.git` 即可。[GitHub Wiki 文档](https://docs.github.com/en/communities/documenting-your-project-with-wikis/adding-or-editing-wiki-pages)介绍独立仓库的编辑方式。 + +文档 CI 在面向 master 的 PR、master 或 `docs/**` 分支上的文档改动,以及手动运行时执行。它检查双语页面、链接和示例语法,构建网站并导出 Wiki,结果作为 artifacts 提供评审。 diff --git a/doc/zh/development/releases.md b/doc/zh/development/releases.md new file mode 100644 index 00000000..7d197354 --- /dev/null +++ b/doc/zh/development/releases.md @@ -0,0 +1,44 @@ +# 发行维护 + +Picker 的版本来自 `vX.Y.Z` 标签。PR 上的 `release:patch`、`release:minor` 或 `release:major` 标签决定合并后的版本增量。 + +## 自动发布流程 + +1. PR 通过版本检查和相关构建后,合并到 `master`。 +2. Version policy 创建版本标签,并触发 Tagged CI。 +3. Tagged CI 构建、安装并验证该标签对应的 wheel 和原生产物。 +4. Release Picker 等待源构建完成,最长 60 分钟;随后检查提交 SHA 和产物哈希,将产物发布到 GitHub Release。 + +正式标签对应 `master` 第一父链上的合并结果。等待本次标签创建完成后,再合并下一个发行 PR。仓库分支保护应将版本检查和相关构建设为必需状态。 + +## 维护依赖配置 + +| 配置 | 作用 | +| --- | --- | +| `pyproject.toml` | Python 包依赖范围 | +| `.build-config.yml` | CI 构建依赖的源码提交和工具配置 | +| `.github/workflows/ci.yml` | 开发构建和预览 wheel 配置 | +| Tagged CI | 为正式构建选择满足约束的已发布依赖 | + +更新依赖后,重新构建并验证 wheel 和生成的 DUT。需要新依赖版本时,先完成该依赖的发布,再发布 Picker。 + +## 失败恢复 + +| 失败位置 | 操作 | +| --- | --- | +| Tagged CI 构建失败 | 修复构建环境后,对已有标签重跑 Tagged CI | +| 发布任务失败 | 使用成功的源 run ID 重跑 Release Picker | +| 合并事件未创建标签 | 检查 Version policy 日志,使用其 manual bump 恢复 | + +恢复过程中沿用已创建的标签,保留提交和产物的对应关系。 + +## 本地检查 + +```sh +python3 -m unittest discover -s test/release -v +bash scripts/build/verify-wheel.sh +``` + +wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` 和 `XCOMM_WHEEL_DIR` 指定目录。脚本在独立环境安装并检查包和接口。 + +当前发行产物发布到 GitHub Releases。文档 CI 的站点和 Wiki 预览可从构建 artifacts 下载,见[文档维护](documentation.md)。 diff --git a/doc/zh/explanation/architecture.md b/doc/zh/explanation/architecture.md new file mode 100644 index 00000000..1deb9307 --- /dev/null +++ b/doc/zh/explanation/architecture.md @@ -0,0 +1,38 @@ +# 生成与运行原理 + +Picker 在导出时读取 RTL 的模块和端口,为选定的语言生成调用接口。模拟器负责执行电路逻辑。两者编译成一个 DUT 模块,测试程序随后通过这个模块访问电路。 + +```mermaid +flowchart TD + R[RTL 与文件列表] --> P[Picker 解析模块和端口] + P --> G[生成包装和构建文件] + G --> C[编译 RTL 与语言接口] + C --> D[可导入或链接的 DUT 模块] + T[测试程序] --> D + D --> S[模拟器执行电路] + S --> O[输出信号与波形] +``` + +## 为什么要先导出和编译 + +RTL 决定电路结构,导出选项决定语言、模拟器和调试功能。Picker 根据这些信息生成包装代码和构建文件,编译器再将它们组合起来。完成后,测试程序可以反复创建模型、运行不同输入,多个测试也可以复用同一份编译结果。 + +修改 RTL、端口或导出选项后,需要重新导出和编译。只修改 Python 测试中的输入、断言或测试组织方式,可以直接重新运行测试。 + +## 一次 Step 发生了什么 + +测试代码通过端口对象保存待写入的输入。调用 `Step()` 时,输入被提交给模拟器;已登记的时钟引脚随仿真步骤更新。模拟器计算电路状态后,输出信号刷新到语言接口,测试代码便可以读取和比较结果。 + +时序电路通过 `InitClock()` 指定时钟端口,`Step(n)` 推进完整的时钟周期。组合电路也可以用 `Step()` 完成输入到输出的一次更新。需要保持当前周期计数时,可以提交输入后调用 `RefreshComb()`,具体写法见[驱动仿真](../guides/simulation.md)。 + +## 为什么波形和内部信号需要导出选项 + +波形记录和内部信号访问需要模拟器在编译时保留额外信息。启用 `-w` 会生成记录波形所需的代码;启用 `--vpi` 会保留供运行时查询的信号信息。这样,普通仿真可以使用较少的调试数据,调试构建则可以观察更多细节。 + +运行时的 `SetWaveform()` 选择输出文件,`GetInternalSignal()` 查找已保留的信号。这些方法使用导出时配置好的功能。 + +## 同一份测试如何使用不同模拟器 + +生成的 DUT 包装提供一致的信号和推进方法,各模拟器模板负责调用对应的执行接口。测试主体通常可以保留,导出时更换 `--sim` 后重新编译即可。 + +波形格式、检查点和覆盖率由模拟器提供,支持情况见[模拟器与语言支持](../reference/compatibility.md)。修改这部分实现时,可以从[开发指南中的源码目录](../development/contributing.md)开始。 diff --git a/doc/zh/guides/export.md b/doc/zh/guides/export.md new file mode 100644 index 00000000..c21d6557 --- /dev/null +++ b/doc/zh/guides/export.md @@ -0,0 +1,73 @@ +# 导出 RTL 工程 + +导出时需要确定源文件、顶层模块、目标语言和模拟器。下面的命令在 Picker 仓库根目录运行;接入自己的工程时,替换文件路径和模块名即可。 + +## 导出单个文件 + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/Adder --autobuild false +make -C build/Adder -j4 +``` + +`--sname` 选择 RTL 中的顶层模块。`--tdir` 指定生成目录,`--autobuild false` 让生成和编译分两步执行。保留默认的自动构建时,Picker 会在生成完成后直接编译。 + +如果希望 Python 包使用另一个名字,例如 `Arithmetic`,添加 `--tname Arithmetic`,并将输出目录改成 `build/Arithmetic`。对应的类名为 `DUTArithmetic`。 + +## 使用文件列表 + +工程包含多个文件时,通过 `--fs` 提供文件列表。仓库的 `example/MultiFileRTL/design.f` 包含头文件目录和多个源码文件: + +```text ++incdir+inc +inc/defs.vh +inc/outer.svh +leaf.v +top.sv +``` + +这些路径相对于文件列表所在目录。在仓库根目录执行: + +```sh +picker export --fs example/MultiFileRTL/design.f \ + --sname MultiFileRTLTop --lang python --sim verilator \ + --tdir build/MultiFileRTLTop --autobuild false +make -C build/MultiFileRTLTop -j4 +``` + +文件列表支持嵌套 `-f` / `-F`、`+incdir+` 和 `+define+`。将工程使用的包含目录和宏定义写入列表,让解析和模拟器编译使用同一组输入。 + +## 传入编译选项 + +| 选项 | 作用阶段 | 常见用途 | +| --- | --- | --- | +| `-S` | slang 解析 | 解析器选项、顶层参数配置 | +| `-V` | 模拟器编译 | 模拟器的诊断或优化选项 | +| `-C` | C++ 编译 | 编译器选项 | + +含空格的参数需要加引号。例如,向 Verilator 传入警告选项: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --tdir build/AdderDebug -V '-Wno-fatal' --autobuild false +``` + +## 将多个模块组合导出 + +`--sname` 可以指定模块及实例数。假设 `rtl/a.v` 定义 `A`,`rtl/b.v` 定义 `B`,以下命令生成含两个 A 和三个 B 的组合模块 C: + +```sh +picker export rtl/a.v,rtl/b.v --sname A,2,B,3 \ + --tname C --lang python --tdir build/C +``` + +生成后,查看接口文件中的实例和端口名称,再编写对应测试。 + +## 添加调试功能 + +- 使用 `-w trace.fst` 生成波形支持,具体操作见[记录仿真结果](simulation.md#recording)。 +- 使用 `--coverage` 收集模拟器代码覆盖率。 +- 使用 `--vpi` 或 `--internal` 访问内部信号,见[内部信号指南](internal-signals.md)。 +- 使用 `--lang` 切换语言,见[多语言示例](languages.md)。 + +完整选项、默认值和输出目录规则见[命令行参考](../reference/cli.md)。 diff --git a/doc/zh/guides/installation.md b/doc/zh/guides/installation.md new file mode 100644 index 00000000..0096d05d --- /dev/null +++ b/doc/zh/guides/installation.md @@ -0,0 +1,92 @@ +# 安装 Picker + +运行 Python + Verilator 示例需要 Picker、Verilator、SWIG、C++ 编译器和 Python 开发环境。下面给出源码安装步骤;已有编译环境时,也可以使用页面末尾的发行包。 + +## 准备工具 + +| 工具 | 要求或用途 | +| --- | --- | +| C++ 编译器 | 支持 C++20,例如 GCC 11 或更新版本 | +| CMake、make、Git | 配置、编译和获取依赖 | +| Python 和开发头文件 | 构建 Python 扩展;编译和运行使用同一个 Python 环境 | +| SWIG | 4.2 或更新版本,用于生成语言绑定 | +| Verilator | 5.020 或更新版本,用于编译 RTL | +| bison、flex、gperf | 编译依赖工具 | +| zlib、lz4 开发包 | 压缩库依赖 | + +Verilator 的安装步骤见[官方安装指南](https://verilator.org/guide/latest/install.html),SWIG 见[官方下载页](https://www.swig.org/download.html)。安装完成后检查: + +```sh +c++ --version +cmake --version +python3 --version +swig -version +verilator --version +``` + +macOS 可以用 Homebrew 安装工具: + +```sh +brew install cmake pkgconf python3 swig verilator zlib lz4 +``` + +## 编译并安装 + +获取源码和依赖,安装到用户目录: + +```sh +git clone https://github.com/XS-MLVP/picker.git +cd picker +make init +make install NPROC=4 BUILD_XSPCOMM_SWIG=python \ + ARGS="-DCMAKE_INSTALL_PREFIX=$HOME/.local/picker" +export PATH="$HOME/.local/picker/bin:$PATH" +``` + +`make init` 下载 `dependence/` 中的依赖。`NPROC=4` 使用四个编译任务,内存较少时可以调低。将上面的 `export PATH=...` 加入 shell 配置后,新终端也能找到 Picker。 + +只在源码目录使用时,可以将 `make install` 换成 `make build`,随后通过 `./build/bin/picker` 执行命令。 + +## 检查安装 + +```sh +picker --version +picker --check +``` + +`--check` 列出模板和各语言资源的检查结果。运行本教程需要模板和 Python 项检查成功;其他语言可以在需要时添加。 + +接下来按[加法器教程](../tutorials/first-dut.md)导出并运行一个模型,检查整个编译和仿真过程。 + +## 使用发行包 + +[GitHub Releases](https://github.com/XS-MLVP/picker/releases) 提供 Linux AppImage、安装目录压缩包和 Python wheel。按主机架构选择文件;wheel 还需要匹配 Python 小版本。 + +使用 AppImage 时,赋予下载文件执行权限后运行。使用安装目录压缩包时,完整解压并将其中的 `bin` 加入 `PATH`。模板和运行资源通过安装目录定位,分发时一起保留。 + +安装 wheel 时,将 Picker 和发行说明中列出的配套依赖 wheel 放入 `wheels/`,再执行: + +```sh +python3 -m venv .venv +. .venv/bin/activate +python -m pip install --no-index --find-links=wheels picker +python -m pip check +picker --check +``` + +导出新模型仍需要本页列出的 Verilator、SWIG 和编译工具。 + +## 自行构建 wheel + +在已执行 `make init` 的源码目录中运行: + +```sh +python3 -m venv .venv +. .venv/bin/activate +python -m pip install build +make wheel PYTHON="$VIRTUAL_ENV/bin/python" +python -m pip install --no-index --find-links=dist picker +python -m pip check +``` + +生成的 wheel 位于 `dist/`,可复制到使用相同 Python 小版本和平台的环境中安装。 diff --git a/doc/zh/guides/internal-signals.md b/doc/zh/guides/internal-signals.md new file mode 100644 index 00000000..baa0e2f5 --- /dev/null +++ b/doc/zh/guides/internal-signals.md @@ -0,0 +1,75 @@ +# 访问内部信号 + +调试电路时,可以通过层次名称读取内部寄存器或修改信号。本页先用仓库中的 `vpi` 示例演示查询,再介绍其他访问方式。 + +## 导出带 VPI 的模型 + +在仓库根目录运行: + +```sh +picker export example/InternalSignals/vpi.v --sname vpi --lang python \ + --sim verilator --vpi --tdir build/docs-internal/vpi --autobuild false +make -C build/docs-internal/vpi -j4 +``` + +`--vpi` 在模型中启用运行时信号查询。这个设计有一个时钟 `clk`,以及控制计数步长的内部信号 `_v2_base`。 + +## 查询并修改信号 + +将以下代码保存为 `build/docs-internal/inspect.py`: + + +```python +from vpi import DUTvpi + +dut = DUTvpi() +try: + dut.InitClock("clk") + dut.Step(1) + for name in dut.VPIInternalSignalList(): + print(name) + increment = dut.GetInternalSignal("vpi._v2_base", use_vpi=True) + assert increment is not None + increment.AsImmWrite() + increment.value = 9 + dut.Step(1) + before = dut.v2.value + dut.Step(1) + assert dut.v2.value == (before + 10) & 0xFF + print("v2 increment: 10") +finally: + dut.Finish() +``` + +运行: + +```sh +cd build/docs-internal +python3 inspect.py +``` + +`Step(1)` 先执行电路初始化,`AsImmWrite()` 让内部信号赋值立即提交。输出列出可访问的层次名称,最后应包含 `v2 increment: 10`。RTL 每周期加上 `1 + _v2_base`,所以写入 9 后,每周期增加 10。 + +接入自己的设计时,先用 `VPIInternalSignalList()` 查询名称,再将实际层次路径传给 `GetInternalSignal()`。可以用 `prefix` 和 `deep` 缩小查询范围。 + +## 选择访问方式 + +| 方式 | 配置 | 适用情况 | +| --- | --- | --- | +| 指定内部信号导出 | `--internal 配置文件` | 已知需要观察的信号,随端口一起生成访问接口 | +| VPI 查询 | `--vpi` | 调试时按层次名称枚举和访问 | +| 原生内存访问 | `--rw mem_direct` | Verilator/GSIM 的直接读写路径,需要对应模型的布局信息 | + +`GetInternalSignal()` 默认优先使用模型生成的原生布局信息,否则通过 VPI 查询。`use_vpi=True` 明确选择 VPI。仓库 `example/CacheSignalCFG` 展示了原生访问的完整工程。 + +## 访问原生数组 + +在提供原生布局的模型中,可以一次取得数组,再访问元素: + +```python +memory = dut.GetInternalSignal("Top.memory", is_array=True) +print(memory[0].value) +memory[1].value = 42 +``` + +将 `Top.memory` 替换为实际名称。查询结果按名称缓存,因此同一名称应保持一致的数组查询方式。`index`、`is_array` 由原生访问路径提供。内部信号对象在 DUT 存活期间使用,重新创建模型后重新查询。 diff --git a/doc/zh/guides/languages.md b/doc/zh/guides/languages.md new file mode 100644 index 00000000..c084ef83 --- /dev/null +++ b/doc/zh/guides/languages.md @@ -0,0 +1,49 @@ +# 在不同语言中使用 DUT + +`--lang` 支持 `python`、`cpp`、`java`、`scala`、`golang` 和 `lua`。选择语言后,Picker 会生成对应的包装、构建文件和端口接口。 + +## 构建并运行现有示例 + +在 Picker 源码目录中,先构建需要的语言支持。例如 Python 和 Java: + +```sh +make build NPROC=4 BUILD_XSPCOMM_SWIG=python,java +make test_Adder EXAMPLE_LANG=java +``` + +第二条命令导出 Adder、编译并运行 `example/Adder/example.java`。把 `EXAMPLE_LANG` 改为 `python`、`cpp`、`scala`、`golang` 或 `lua`,即可选择对应示例。示例脚本会重新生成 `output/Adder`。 + +Java/Scala 需要 JDK;Scala 还需要 Scala 工具链;Go 需要 Go 编译器;Lua 需要解释器和开发头文件。可通过 `picker --check` 查看所选语言的资源是否齐全。 + +## 导出自己的设计 + +以 C++ 为例: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang cpp \ + --tdir build/AdderCpp --autobuild false +make -C build/AdderCpp -j4 +``` + +先用仓库中对应语言的 `example/Adder/example.*` 熟悉生成接口,再替换为自己的设计和测试。 + +## 读写信号 + +| 语言 | 写入示例 | 读取示例 | +| --- | --- | --- | +| Python | `dut.a.value = 42` | `dut.sum.value` | +| C++ | `dut.a = 42` | `dut.sum.U()` | +| Java | `dut.a.Set(42)` | `dut.sum.U()` | +| Scala | `dut.a.Set(42)` | `dut.sum.U()` | +| Go | `dut.A.Set(42)` | `dut.Sum.U()` | +| Lua | `dut.a:Set(42)` | `dut.sum:U()` | + +Python 的整数读写支持完整位宽。C++ 的 `U()` / `S()` 返回低 64 位,宽信号使用 `GetBytes()` / `SetBytes()`。Java/Scala 提供大整数包装;Go 和 Lua 的宽值可以通过字节或字符串接口处理,具体签名见生成代码和对应示例。 + +端口名与方法名冲突时,生成器会按语言规则调整名称,例如添加 `pin_` 前缀。Go 的导出名称首字母大写。 + +## 分发生成结果 + +编译后的 DUT 包包含语言接口、模型库和运行资源。默认的 `--cp_lib true` 会复制运行库。将整个包一起交付,并在目标环境运行一份短测试,检查导入、端口读写和仿真推进。 + +Python 扩展需要匹配目标环境的 Python 小版本、操作系统和架构。 diff --git a/doc/zh/guides/simulation.md b/doc/zh/guides/simulation.md new file mode 100644 index 00000000..6a94fc7f --- /dev/null +++ b/doc/zh/guides/simulation.md @@ -0,0 +1,114 @@ +# 驱动仿真 + +本页使用生成的 Python DUT 接口,说明怎样设置时钟、施加复位、采样和记录结果。完整的模型创建示例见[加法器教程](../tutorials/first-dut.md)。 + +## 设置时钟和复位 + +对于包含 `clock` 和高有效 `reset` 端口的 DUT,在创建对象后执行: + +```python +dut.InitClock("clock") +dut.reset.value = 1 +dut.Step(2) +dut.reset.value = 0 +dut.Step(1) +``` + +`InitClock()` 登记时钟引脚,随后每次 `Step(n)` 推进 n 个完整周期。这段代码让复位保持两个周期,然后释放复位并执行一个周期。端口名、复位极性和保持时间应按 RTL 协议设置。 + +运行测试时,先写输入,再调用 `Step()`,最后读取输出。例如: + +```python +dut.valid.value = 1 +dut.data.value = 42 +dut.Step(1) +print(dut.ready.value) +``` + +这里假设 DUT 包含 `valid`、`data` 和 `ready` 端口。 + +## 在边沿采样 + +用 `StepRis()` 注册上升沿回调,用 `StepFal()` 注册下降沿回调。下面在每次上升沿后读取 `ready`: + +```python +def observe(cycle): + print(cycle, dut.ready.value) + +dut.StepRis(observe) +dut.Step(3) +``` + +回调的第一个参数是周期计数。将采样、记录或断言放在回调中,在测试主流程中调用 `Step()` 推进仿真。 + +## 只更新组合逻辑 + +对需要立即生效的输入设置 `AsImmWrite()`,写入后调用 `RefreshComb()`: + +```python +dut.a.AsImmWrite() +dut.b.AsImmWrite() +dut.cin.AsImmWrite() +dut.a.value = 2 +dut.b.value = 3 +dut.cin.value = 1 +dut.RefreshComb() +assert dut.sum.value == 6 +``` + +这段代码适用于教程中的 Adder。输入会立即提交,组合逻辑重新求值,周期计数保持不变。 + + + +## 保存波形和代码覆盖率 + +导出时启用需要的记录功能: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-trace/Adder --autobuild false \ + -w trace.fst --coverage +make -C build/docs-trace/Adder -j4 +``` + +把下面的代码保存为 `build/docs-trace/record.py`: + + +```python +from Adder import DUTAdder + +dut = DUTAdder(waveform_filename="trace.fst", coverage_filename="coverage.dat") +try: + dut.b.value = 1 + dut.cin.value = 0 + for value in range(4): + dut.a.value = value + dut.Step(1) + assert dut.sum.value == value + 1 +finally: + dut.Finish() +``` + +运行脚本并查看生成文件: + +```sh +cd build/docs-trace +python3 record.py +ls -lh trace.fst coverage.dat +``` + +用 GTKWave 等波形查看器打开 `trace.fst`,可以看到 `a` 从 0 到 3 变化,`sum` 对应为 1 到 4。代码覆盖率文件可交给模拟器配套工具处理。 + +较长的仿真可以通过 `PauseWaveformDump()` 暂停记录,在感兴趣的区间前调用 `ResumeWaveformDump()` 恢复。需要在仿真结束前查看文件时,调用 `FlushWaveform()` 刷新缓冲。`Finish()` 负责结束仿真和输出收尾。 + +## 保存和恢复检查点 + +Verilator 工程可以在导出时添加 `--checkpoints`,然后调用: + +```python +dut.CheckPoint("state.bin") +dut.Step(10) +dut.Restore("state.bin") +``` + +检查点保存模拟器状态。Python 测试中的参考模型、队列和随机数状态由测试程序一同保存与恢复。接口返回值及模拟器支持情况见 [DUT API](../reference/dut-api.md)。 diff --git a/doc/zh/guides/uvm-tlm.md b/doc/zh/guides/uvm-tlm.md new file mode 100644 index 00000000..f5a85da5 --- /dev/null +++ b/doc/zh/guides/uvm-tlm.md @@ -0,0 +1,59 @@ +# 生成 UVM 事务桥 + +已有 UVM 环境时,可以用 `picker pack` 生成事务对应的 Python 类和 UVM agent,在 Python 测试与 SystemVerilog testbench 之间传递数据。 + +## 从事务类生成 + +仓库的 `example/Pack/adder_trans.sv` 定义了继承 `uvm_sequence_item` 的 `adder_trans`,包含 `a`、`b`、`cin`、`sum` 和 `cout` 字段。在仓库根目录执行: + +```sh +picker pack example/Pack/adder_trans.sv --example +``` + +生成结果位于 `uvmpy/`: + +```text +uvmpy/ +├── Makefile +├── example.py +├── example.sv +└── adder_trans/ + ├── __init__.py + ├── xagent.py + ├── xagent.sv + ├── utils_pkg.sv + └── ... +``` + +`xagent.py` 提供 Python 事务接口,`xagent.sv` 提供 UVM agent。`example.py` 和 `example.sv` 展示两端如何连接和收发事务。 + +每个输入文件放一个事务类。多个事务分别放入文件后,可用 `--filelist` 汇总;仓库 `example/Pack/03_MultiTrans` 提供示例。 + +## 从 RTL 端口生成 + +也可以从模块端口生成事务和 DUT 包装: + +```sh +picker pack --from-rtl example/Adder/Adder.v --name Adder \ + --generate-dut --example +``` + +这会生成 `uvmpy/Adder/Adder_trans.sv` 和对应 agent。`--name Adder` 选择模块及包名,`--generate-dut` 增加逐引脚操作包装。已有同名输出目录时,先保存手工修改,再选择新目录或用 `--force` 重新生成。 + +## 编译和运行 + +生成的示例 Makefile 使用 VCS、UVM、UVMC 和 SystemC,并通过 Verdi PLI 记录波形。准备好工具环境后,设置 `VCS_HOME`、`UVM_HOME`、`UVMC_HOME`、`VERDI_HOME`,确认 `vcs`、`vlogan`、`syscan`、SWIG 和 Python 开发工具可执行,然后运行: + +```sh +make -C uvmpy +``` + +Makefile 会编译桥接库、编译 UVM 环境,并执行 `example.py`。TLM SDK 默认从安装目录中的 `share/xspcomm/tlm` 查找;单独安装 SDK 时,可通过 `XSP_COMM_TLM` 指定路径。 + +## 接入已有 testbench + +以生成的 `example.sv` 为起点,将 driver 的事务接收方法连接到设计接口,将 monitor 的采样结果发送回 Python。发送端和接收端使用相同通道名,双方使用同一份事务字段定义。 + +`example/Adder/example-uvm.sv` 展示了完整连接:driver 收到事务后写入 `a`、`b`、`cin`,monitor 采样 `sum`、`cout` 并回传。替换设计时,重点修改这些驱动和采样步骤。 + +编译或收发失败时,先检查生成日志、工具路径和通道名称;命令参数见 [pack 参考](../reference/cli.md#pack)。 diff --git a/doc/zh/index.md b/doc/zh/index.md new file mode 100644 index 00000000..5e06d056 --- /dev/null +++ b/doc/zh/index.md @@ -0,0 +1,24 @@ +# Picker 文档 + +Picker 把 Verilog/SystemVerilog 设计生成为 Python、C++、Java、Scala、Go 或 Lua 模块。你可以在测试代码中给电路输入赋值、推进仿真、读取输出,并用断言检查结果。 + +第一次使用,从[安装 Picker](guides/installation.md)开始,然后跟随[加法器教程](tutorials/first-dut.md)完成一个可运行的测试。 + +## 使用 Picker + +| 想做什么 | 文档 | +| --- | --- | +| 导出自己的 RTL | [导出 RTL 工程](guides/export.md) | +| 设置时钟、复位和采样 | [驱动仿真](guides/simulation.md) | +| 保存波形、收集代码覆盖率 | [记录仿真结果](guides/simulation.md#recording) | +| 观察内部寄存器或存储器 | [访问内部信号](guides/internal-signals.md) | +| 使用 C++、Java 等语言 | [多语言示例](guides/languages.md) | +| 在 Python 与 UVM 之间传递事务 | [生成 UVM 事务桥](guides/uvm-tlm.md) | + +## 查询接口 + +[命令行参考](reference/cli.md)列出导出选项;[DUT API](reference/dut-api.md)说明生成对象的方法和信号访问方式。[模拟器与语言支持](reference/compatibility.md)可用于选择工具链,运行中遇到问题可查[故障排查](reference/troubleshooting.md)。 + +## 理解和修改 Picker + +[生成与运行原理](explanation/architecture.md)介绍 RTL 如何成为可调用的仿真模块。[开发指南](development/contributing.md)包含源码目录和测试入口;[文档维护](development/documentation.md)介绍双语编辑、网站预览和 Wiki 导出。 diff --git a/doc/zh/reference/cli.md b/doc/zh/reference/cli.md new file mode 100644 index 00000000..1a76ef14 --- /dev/null +++ b/doc/zh/reference/cli.md @@ -0,0 +1,70 @@ +# 命令行参考 + +使用 `picker --help`、`picker export --help` 和 `picker pack --help` 查看命令帮助。以下按全局选项、RTL 导出和 UVM 打包列出参数。 + +## 全局命令 + +| 选项 | 作用 | +| --- | --- | +| `-h, --help` | 显示帮助 | +| `-v, --version` | 显示构建版本 | +| `--check` | 检查模板与各语言资源,阅读每一项结果 | +| `--show_default_template_path` | 输出模板路径 | +| `--show_xcom_lib_location_cpp` | 输出 C++ 运行库的 include/lib 路径 | +| `--show_xcom_lib_location_python/java/scala/golang/lua` | 查询对应语言资源;实际使用一个完整选项名称 | + +## export + +| 选项 | 参数/默认值 | 用途 | +| --- | --- | --- | +| `file` | RTL 文件,可多个 | 提供源文件;没有 `--sname` 时需要 | +| `--fs, --filelist` | 文件或列表,可多个 | 补充源文件、包含路径和宏定义 | +| `--sname, --source_module_name` | module 名,可多个 | 指定顶层选择 | +| `--tname, --target_module_name` | 名称 | 指定生成模块名,默认源模块名 | +| `--tdir, --target_dir` | 路径 | 输出目录;末尾 `/` 表示在其下按模块名建目录 | +| `--sdir, --source_dir` | 模板目录 | 覆盖安装模板来源 | +| `--lang, --language` | `python` | cpp/python/java/scala/golang/lua | +| `--sim` | `verilator` | verilator/vcs/gsim/uvs;依赖对应工具链 | +| `--rw, --access-mode` | `dpi` | dpi 或 mem_direct;支持范围见访问指南 | +| `--internal` | 配置文件 | 选定内部信号 | +| `--vpi` | flag,关闭 | 编入 VPI 支持 | +| `--checkpoints` | flag,关闭 | 编入受支持的保存/恢复能力 | +| `-w, --wave_file_name` | 文件名,空 | 配置波形格式/输出 | +| `-c, --coverage` | flag,关闭 | 编入模拟器覆盖率 | +| `-F, --frequency` | `100MHz` | VCS 时间配置,支持 Hz/KHz/MHz/GHz 单位 | +| `--verdi-mode` | `legacy` | VCS Verdi 集成;modern 对应较新的调试方式 | +| `--cp_lib, --copy_xspcomm_lib` | `true` | 复制配套运行库 | +| `-V, --vflag` | 字符串 | 传给模拟器的编译参数 | +| `-S, --sflag` | 字符串列表 | 传给 slang 的解析参数 | +| `-C, --cflag` | 字符串 | 传给 C++ 编译器的参数 | +| `-e, --example` | flag,关闭 | 生成/构建示例 | +| `--autobuild` | `true` | 生成后自动构建 | +| `-j, --build-threads` | 0 | 并行度;0 使用所有核心 | +| `--verbose` | flag,关闭 | 增加诊断输出 | + +含空格的参数需要 shell 引号,例如 `-V '--trace -Wno-fatal'`。各模拟器的工具环境见[模拟器支持](compatibility.md)。 + +## pack + +| 选项 | 用途 | +| --- | --- | +| `file` | 含事务声明的 SV 文件 | +| `-f, --filelist` | 事务文件列表 | +| `--from-rtl` | 从 RTL 端口生成事务 | +| `-d, --generate-dut` | 生成支持逐引脚读写的 DUT 包装 | +| `-r, --rename` | 重命名事务 | +| `-n, --name` | 生成包名 | +| `-e, --example` | 生成示例工程 | +| `-c, --force` | 删除已生成目录并重新生成 | + +生成目录和使用示例见 [UVM 事务桥指南](../guides/uvm-tlm.md)。 + +## 环境变量 + +`DUMPVARS_OPTION` 传给 VCS 的 `$fsdbDumpvars` 选项,例如: + +```sh +DUMPVARS_OPTION="+mda" picker export rtl/top.sv --sname Top --sim vcs -w trace.fsdb +``` + +该片段需要实际 RTL 和配置好的 VCS/Verdi 环境;`+mda` 用于相应环境中的数组波形。 diff --git a/doc/zh/reference/compatibility.md b/doc/zh/reference/compatibility.md new file mode 100644 index 00000000..8d62e7ac --- /dev/null +++ b/doc/zh/reference/compatibility.md @@ -0,0 +1,42 @@ +# 模拟器与语言支持 + +## 模拟器 + +`picker export --sim` 接受以下选项: + +| 选项 | 工具环境 | 说明 | +| --- | --- | --- | +| `verilator` | Verilator 与 C++ 编译器 | 默认选项;本文教程使用此环境 | +| `vcs` | VCS 及其许可证;FSDB 需要 Verdi | 提供 DPI/VPI、波形和代码覆盖率适配 | +| `gsim` | GSIM 配套工具链 | 提供导出、仿真推进和原生信号访问适配 | +| `uvs` | UVS 配套工具链及许可证 | 提供仿真推进和 USDB 波形适配 | + +波形和检查点需在导出时启用: + +| 功能 | 导出选项 | 支持情况 | +| --- | --- | --- | +| FST / VCD 波形 | `-w trace.fst` / `-w trace.vcd` | Verilator | +| FSDB 波形 | `-w trace.fsdb` | VCS + Verdi | +| USDB 波形 | `-w trace.usdb` | UVS | +| 代码覆盖率 | `--coverage` | Verilator、VCS;具体指标由编译配置决定 | +| 检查点 | `--checkpoints` | Verilator | +| 原生内存读写 | `--rw mem_direct` | Verilator、GSIM | + +## 语言 + +| `--lang` | 运行或编译环境 | +| --- | --- | +| `python` | Python 及匹配的开发头文件 | +| `cpp` | C++20 编译器 | +| `java` | JDK | +| `scala` | JDK、Scala | +| `golang` | Go 和 C++ 编译器 | +| `lua` | Lua 及开发头文件 | + +生成时需要已安装对应语言的绑定资源。检查方法和示例命令见[多语言指南](../guides/languages.md)。 + +## 平台与分发 + +Linux 是主要构建环境。macOS 可使用 Verilator 和源码构建,动态多实例受平台加载机制限制。Python wheel 按 Python 小版本、操作系统和架构区分,例如 `cp312` 表示 CPython 3.12。 + +生成的模型与导出时的工具链和运行库一起使用。更换这些依赖后,重新生成并编译模型。分发前在目标环境运行[加法器教程](../tutorials/first-dut.md)中的短测试,可以检查导入、宽信号和仿真推进。 diff --git a/doc/zh/reference/dut-api.md b/doc/zh/reference/dut-api.md new file mode 100644 index 00000000..1d592079 --- /dev/null +++ b/doc/zh/reference/dut-api.md @@ -0,0 +1,86 @@ +# Python DUT API + +导出的 Python 包提供 `DUT<模块名>` 类。以下签名来自 Python 模板;其他语言见[多语言指南](../guides/languages.md)。波形、覆盖率和检查点的支持情况见[模拟器支持](compatibility.md)。 + +## 创建对象与访问端口 + +```python +from Adder import DUTAdder + +dut = DUTAdder() +dut.a.value = 42 +print(dut.a.value) +print(dut["a"].value) +dut.Finish() +``` + +`DUT<模块名>(*args, **kwargs)` 创建模型。位置参数传给模拟器;关键字参数 `waveform_filename` 和 `coverage_filename` 设置输出路径,需要在导出时启用对应记录功能。 + +`dut.pin` 和 `dut["pin"]` 返回同一个端口对象。通过 `.value` 或 `Set(value)` 写入,`.value` 读取完整位宽的无符号 Python 整数。端口属性本身只读。 + +## 时钟与执行 + +| 方法 | 行为与返回值 | +| --- | --- | +| `InitClock(name)` | 将指定端口登记为时钟引脚;返回 `None` | +| `Step(i=1)` | 推进 i 个完整周期并刷新信号;返回 `None` | +| `StepRis(callback, args=(), kwargs={})` | 注册上升沿回调,调用形式为 `callback(cycle, *args, **kwargs)` | +| `StepFal(callback, args=(), kwargs={})` | 注册下降沿回调,参数形式同上 | +| `RefreshComb()` | 调用组合求值,保持周期计数;输入应已提交给模型 | +| `Finish()` | 结束仿真、处理输出;使用完成后调用 | +| `AtClone()` | 在 fork 的子进程中重新初始化模拟器状态 | + +回调在相应边沿的求值和信号刷新后执行。复位通过 RTL 复位端口驱动,示例见[设置时钟和复位](../guides/simulation.md)。 + +测试框架取得时钟控制权期间,`Step()` 会报告错误。此时通过框架的执行方法推进仿真。VCS、UVS 等模拟器的结束流程可能终止进程,测试汇总应安排在 `Finish()` 前。 + +## 波形 + +| 方法 | 行为与返回值 | +| --- | --- | +| `SetWaveform(filename)` | 设置波形文件路径,格式与导出时的配置一致 | +| `GetWaveFormat()` | 返回扩展名,如 `fst`;未启用时返回空字符串 | +| `PauseWaveformDump()` | 暂停波形记录 | +| `ResumeWaveformDump()` | 恢复波形记录 | +| `WaveformPaused()` | 返回 1 表示暂停,0 表示记录中 | +| `FlushWaveform()` | 将波形缓冲写入文件 | + +导出选项及完整脚本见[保存波形](../guides/simulation.md#recording)。频繁刷新会增加 I/O,也会影响 FST 压缩效率。 + +## 代码覆盖率与检查点 + +| 方法 | 行为与返回值 | +| --- | --- | +| `SetCoverage(filename)` | 设置模拟器覆盖率输出位置 | +| `ResetCoverage()` | 重置覆盖率计数;当前由 VCS 路径实现 | +| `GetCovMetrics()` | 返回启用的指标位掩码,0 表示关闭 | +| `CheckPoint(name)` | 将模拟器状态保存到文件;需要 `--checkpoints`,Python 返回 `None` | +| `Restore(name)` | 从检查点恢复模拟器状态;Python 返回 `None` | + +`GetCovMetrics()` 中的位 0–5 分别表示 line、cond、fsm、toggle、branch、assert。 + +## 内部信号 + +| 方法 | 行为与返回值 | +| --- | --- | +| `GetInternalSignal(name, index=-1, is_array=False, use_vpi=False)` | 按名称返回信号对象;`is_array=True` 返回列表 | +| `GetInternalSignalList(prefix="", deep=99, use_vpi=False)` | 返回可访问名称;默认优先原生布局,随后 VPI | +| `VPIInternalSignalList(prefix="", deep=99)` | 通过 VPI 枚举层次名称 | + +原生查询中的 `prefix` 按名称子串筛选。VPI 中的 `prefix` 和 `deep` 指定起始层次与搜索深度。`index`、`is_array` 用于原生布局路径。 + +查询结果按 `name` 缓存,后续调用复用首次查询的对象。普通查询未找到时返回 `None`;显式 `use_vpi=True` 查询失败会触发断言。具体示例见[访问内部信号](../guides/internal-signals.md)。 + +## Python 异步方法 + +| 方法 | 行为 | +| --- | --- | +| `await dut.AStep(n)` | 等待仿真推进 n 个周期 | +| `await dut.ACondition(fn)` | 在周期通知时检查 fn,条件成立后返回 | +| `await dut.RunStep(n)` | 推进 n 个周期,并在周期之间让其他协程执行 | + +等待协程需要与推进仿真的协程一起运行。`AStep()` 和 `ACondition()` 使用时钟的 Python 周期通知。 + +## 框架集成 + +`GetXPort()` 返回 DUT 的端口集合 `XPort`,`GetXClock()` 返回时钟对象 `XClock`。框架可通过这两个对象接入信号和时钟管理。它们及内部信号对象在 DUT 存活期间使用。 diff --git a/doc/zh/reference/troubleshooting.md b/doc/zh/reference/troubleshooting.md new file mode 100644 index 00000000..78ae70b1 --- /dev/null +++ b/doc/zh/reference/troubleshooting.md @@ -0,0 +1,36 @@ +# 故障排查 + +先保留完整导出命令和第一条错误。解析器、编译器或模拟器通常会在后续 `make` 报错之前给出具体原因。 + +## 导出和编译 + +| 现象 | 检查与处理 | +| --- | --- | +| 找不到模板 | 运行 `picker --check` 和 `picker --show_default_template_path`;使用完整安装目录,或通过 `--sdir` 指定模板 | +| 找不到顶层 module | 检查 `--sname` 拼写、源码列表和条件编译宏 | +| include 文件缺失 | 将头文件目录写入 filelist 的 `+incdir+`,检查相对路径 | +| 端口宽度与预期不符 | 检查顶层参数、宏定义和展开后的接口文件 | +| 找不到 SWIG 或编译器 | 检查 PATH,并按[安装指南](../guides/installation.md)准备工具 | +| 某种语言资源缺失 | 查看 `picker --check` 对应条目,构建所需语言绑定 | + +## Python 导入和信号访问 + +| 现象 | 检查与处理 | +| --- | --- | +| `No module named 'Adder'` | 从生成包的父目录运行,或把父目录加入 PYTHONPATH | +| 原生扩展加载失败 | 核对 Python 小版本、平台和架构,使用同一环境重新编译 | +| 找不到 `libxspcomm` 或库符号 | 恢复完整的生成包和配套运行资源;更换依赖后重新导出编译 | +| `XData attributes of DUT are read-only` | 通过 `dut.pin.value = value` 写信号值 | +| 写入后输出没变化 | 写入输入后调用 `Step()`;组合求值可参考[驱动仿真](../guides/simulation.md) | +| 宽信号高位丢失 | Python 使用 `.value`;C++ 使用完整字节接口,检查测试代码中的临时变量位宽 | +| 内部信号查询失败 | 导出时启用 VPI 或原生布局,先枚举实际名称,再查询对象 | + +## 波形和 UVM + +波形文件为空时,检查导出命令中的 `-w`、运行时输出路径和暂停状态,并调用 `Finish()` 完成输出。文件格式由导出配置决定。完整命令见[保存波形](../guides/simulation.md#recording)。 + +UVM 编译失败时,检查 VCS、UVM、UVMC、Verdi 和 SDK 路径。收不到事务时,检查两端通道名和 driver/monitor 是否执行,见[UVM 事务桥](../guides/uvm-tlm.md)。 + +## 报告问题 + +提交 [GitHub Issue](https://github.com/XS-MLVP/picker/issues) 时,附上最小 RTL、文件列表、完整导出命令和错误日志,以及 `picker --version`、操作系统、Python 和模拟器版本。私有设计可以简化成保留相关语法或接口的公开例子。 diff --git a/doc/zh/tutorials/first-dut.md b/doc/zh/tutorials/first-dut.md new file mode 100644 index 00000000..f0110910 --- /dev/null +++ b/doc/zh/tutorials/first-dut.md @@ -0,0 +1,110 @@ +# 用 Python 验证一个加法器 + +这篇教程会把一个 128-bit 加法器导出为 Python 模块,先计算 `2 + 3 + 1`,再检查进位和溢出。完成后,你会得到一个可以重复运行的测试脚本。 + +开始前,请完成[安装](../guides/installation.md),并准备好 Picker、Verilator、SWIG 和 Python 环境。 + +## 1. 获取加法器 + +获取仓库并进入根目录。已有源码时,直接进入该目录: + +```sh +git clone https://github.com/XS-MLVP/picker.git +cd picker +``` + +打开 `example/Adder/Adder.v`,找到 `Adder` 模块。它的端口如下: + +| 端口 | 方向 | 位宽 | 含义 | +| --- | --- | --- | --- | +| `a`、`b` | 输入 | 128 | 两个加数 | +| `cin` | 输入 | 1 | 输入进位 | +| `sum` | 输出 | 128 | 结果的低 128 位 | +| `cout` | 输出 | 1 | 输出进位 | + +模块的计算式是 `assign {cout, sum} = a + b + cin;`。它是组合电路,每次更新输入后即可计算结果。 + +## 2. 导出并编译 + +在仓库根目录执行: + +```sh +picker export example/Adder/Adder.v --sname Adder --lang python \ + --sim verilator --tdir build/docs-adder/Adder --autobuild false +make -C build/docs-adder/Adder -j4 +``` + +第一条命令选择 `Adder` 模块,在 `build/docs-adder/Adder` 生成工程。第二条命令编译 RTL 和 Python 接口。编译完成后,`Adder` 目录就是可以导入的 Python 包。 + +## 3. 计算一次加法 + +将下面的代码保存为 `build/docs-adder/check.py`: + + +```python +from Adder import DUTAdder + +dut = DUTAdder() +dut.a.value = 2 +dut.b.value = 3 +dut.cin.value = 1 +dut.Step(1) +print(f"sum={dut.sum.value}, cout={dut.cout.value}") +dut.Finish() +``` + +从包的父目录运行脚本: + +```sh +cd build/docs-adder +python3 check.py +``` + +输出中应包含: + +```text +sum=6, cout=0 +``` + +`DUTAdder()` 创建一个仿真模型。每个端口通过同名属性访问,`.value` 用来读写端口值。`Step(1)` 将输入提交给模拟器并更新输出,`Finish()` 结束仿真。 + +把 `cin.value` 改为 `0`,再次运行脚本。现在应得到 `sum=5, cout=0`。 + +## 4. 检查进位和溢出 + +将 `check.py` 替换为下面的代码。这次用断言自动检查三组输入:普通加法、最大值加一,以及两个高位相加。 + + +```python +from Adder import DUTAdder + +mask = (1 << 128) - 1 +cases = [(2, 3, 1), (mask, 1, 0), (1 << 127, 1 << 127, 1)] +dut = DUTAdder() +try: + for a, b, cin in cases: + dut.a.value = a + dut.b.value = b + dut.cin.value = cin + dut.Step(1) + expected = a + b + cin + assert dut.sum.value == (expected & mask) + assert dut.cout.value == (expected >> 128) + print(f"sum={dut.sum.value}, cout={dut.cout.value}") + print("Adder: 3 cases passed") +finally: + dut.Finish() +``` + +再次执行 `python3 check.py`,输出中应包含: + +```text +sum=6, cout=0 +sum=0, cout=1 +sum=1, cout=1 +Adder: 3 cases passed +``` + +Python 整数保留完整计算结果。`expected & mask` 取低 128 位,与 `sum` 比较;`expected >> 128` 取进位,与 `cout` 比较。任意一项不符合预期,断言都会指出失败的位置。 + +你已经完成了导出、输入激励、推进仿真和检查输出。接下来可以[导出自己的 RTL](../guides/export.md),或学习怎样给时序电路[设置时钟和复位](../guides/simulation.md)。 diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..13aed3f2 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,99 @@ +site_name: Picker +repo_url: https://github.com/XS-MLVP/picker +edit_uri: edit/master/doc/ +docs_dir: doc +site_dir: build/docs-site +theme: + name: material + language: zh + font: false + palette: + primary: indigo + features: + - navigation.tabs + - navigation.sections + - navigation.top + - toc.follow + - content.code.copy + - content.action.edit + - search.suggest + - search.highlight +plugins: +- i18n: + docs_structure: folder + fallback_to_default: false + languages: + - locale: zh + default: true + name: 中文 + build: true + - locale: en + name: English + build: true + nav_translations: + 文档首页: Overview + 入门教程: Tutorials + 第一个 DUT: Your first DUT + 使用指南: How-to guides + 安装: Installation + 导出工程: Export projects + 驱动仿真: Drive simulation + 内部信号: Internal signals + 多语言: Languages + UVM 事务桥: UVM transaction bridges + 接口参考: Reference + 命令行: CLI + DUT API: DUT API + 模拟器与语言支持: Simulator and language support + 故障排查: Troubleshooting + 原理与设计: Design + 生成与运行原理: Generation and simulation + 开发与贡献: Development + 贡献与测试: Contribute and test + 维护发行: Maintain releases + 文档与 Wiki: Documentation and Wiki +- search: {} +nav: +- 文档首页: index.md +- 入门教程: + - 第一个 DUT: tutorials/first-dut.md +- 使用指南: + - 安装: guides/installation.md + - 导出工程: guides/export.md + - 驱动仿真: guides/simulation.md + - 内部信号: guides/internal-signals.md + - 多语言: guides/languages.md + - UVM 事务桥: guides/uvm-tlm.md +- 接口参考: + - 命令行: reference/cli.md + - DUT API: reference/dut-api.md + - 模拟器与语言支持: reference/compatibility.md + - 故障排查: reference/troubleshooting.md +- 原理与设计: + - 生成与运行原理: explanation/architecture.md +- 开发与贡献: + - 贡献与测试: development/contributing.md + - 维护发行: development/releases.md + - 文档与 Wiki: development/documentation.md +validation: + nav: + not_found: warn + omitted_files: warn + links: + not_found: warn + anchors: warn + unrecognized_links: warn +exclude_docs: | + /API.zh.md + /install-macos.en.md + /install-macos.zh.md + /maintainer-guidance.md +markdown_extensions: + - tables + - toc: + permalink: true + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 00000000..53445951 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,4 @@ +mkdocs==1.6.1 +mkdocs-material==9.7.7 +mkdocs-static-i18n==1.3.1 +jieba==0.42.1 diff --git a/scripts/docs.py b/scripts/docs.py new file mode 100644 index 00000000..620864c0 --- /dev/null +++ b/scripts/docs.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +"""Check bilingual documentation, run marked examples, and export a local Wiki.""" +import argparse +import ast +import hashlib +from html.parser import HTMLParser +import json +from pathlib import Path +import re +import subprocess +import sys +import tempfile +from urllib.parse import unquote, urlsplit + +import markdown +import yaml + +ROOT = Path(__file__).resolve().parents[1] +CONFIG = yaml.load((ROOT / 'mkdocs.yml').read_text(), Loader=yaml.BaseLoader) +DOCS = ROOT / CONFIG['docs_dir'] +EXAMPLES = re.compile(r'\s*```(?:python|cpp)\n(.*?)\n```', re.S) +LINK = re.compile(r'(!?\[[^\]\n]*\]\()([^\s)]+)(\))') + + +class Links(HTMLParser): + def __init__(self, text): + super().__init__() + self.targets, self.ids = [], set() + self.feed(markdown.markdown(text, extensions=['toc', 'tables', 'fenced_code'])) + + def handle_starttag(self, tag, attrs): + attrs = dict(attrs) + if 'id' in attrs: + self.ids.add(attrs['id']) + key = 'src' if tag == 'img' else 'href' + if key in attrs: + self.targets.append(attrs[key]) + + +def nav_items(nav): + for entry in nav: + for title, value in entry.items(): + if isinstance(value, list): + yield from nav_items(value) + else: + yield title, value + + +def pages(): + return sorted(p for lang in ('zh', 'en') for p in (DOCS / lang).rglob('*.md')) + + +def check(): + localized = {lang: {p.relative_to(DOCS / lang) for p in (DOCS / lang).rglob('*.md')} + for lang in ('zh', 'en')} + errors = [] + if localized['zh'] != localized['en']: + errors.append('Missing translations: ' + str(localized['zh'] ^ localized['en'])) + navigation = {Path(path) for _, path in nav_items(CONFIG['nav'])} + for lang, files in localized.items(): + if files != navigation: + errors.append(f'{lang}: navigation/page mismatch: {files ^ navigation}') + all_pages = pages() + entrypoints = list(ROOT.glob('README*.md')) + list(ROOT.glob('CONTRIBUTING.md')) + if (ROOT / 'test/README.md').exists(): + entrypoints.append(ROOT / 'test/README.md') + parsed = {p.resolve(): Links(p.read_text()) for p in [*DOCS.rglob('*.md'), *entrypoints]} + link_count = 0 + for path, data in parsed.items(): + for target in data.targets: + url = urlsplit(target) + if url.scheme or url.netloc: + continue + destination = (path.parent / unquote(url.path)).resolve() if url.path else path + if not destination.exists(): + errors.append(f'{path.relative_to(ROOT)}: missing {target}') + elif url.fragment and destination in parsed and unquote(url.fragment) not in parsed[destination].ids: + errors.append(f'{path.relative_to(ROOT)}: missing anchor {target}') + link_count += 1 + for path in all_pages: + content = path.read_text() + if not content.startswith('# ') or len(content.splitlines()) < 8: + errors.append(f'{path.relative_to(ROOT)}: missing title or substantive content') + for code in re.findall(r'^```python\n(.*?)^```', content, re.M | re.S): + try: + ast.parse(code) + except SyntaxError as error: + errors.append(f'{path.relative_to(ROOT)}: Python syntax: {error}') + for relative in sorted(localized['zh'] & localized['en']): + zh = EXAMPLES.findall((DOCS / 'zh' / relative).read_text()) + en = EXAMPLES.findall((DOCS / 'en' / relative).read_text()) + if zh != en: + errors.append(f'{relative}: runnable examples differ between translations') + if errors: + raise SystemExit('\n'.join(errors)) + print(f'Checked {len(all_pages)} localized pages and {link_count} local links; translations and examples match.') + return all_pages + + +def run_examples(args): + checked = check() + count, skipped = 0, 0 + for page in checked: + if page.relative_to(DOCS).parts[0] != 'zh': + continue # check() established identical executable examples. + for language, code in EXAMPLES.findall(page.read_text()): + with tempfile.TemporaryDirectory(prefix='docs-example-') as directory: + directory = Path(directory) + if language == 'python': + command = [args.python, '-c', code] + elif args.include and args.lib: + source, executable = directory / 'example.cpp', directory / 'example' + source.write_text(code) + subprocess.run([args.cxx, '-std=c++20', '-O2', '-I', str(Path(args.include).resolve()), + str(source), '-L', str(Path(args.lib).resolve()), + '-Wl,-rpath,' + str(Path(args.lib).resolve()), '-lxspcomm', + '-o', str(executable)], check=True, timeout=120) + command = [str(executable)] + else: + print(f'SKIP C++ {page}: supply --include and --lib') + skipped += 1 + continue + subprocess.run(command, check=True, cwd=args.cwd or directory, timeout=60) + count += 1 + print(f'PASS {language}: {page.relative_to(DOCS)}') + print(f'{count} executable examples passed, {skipped} skipped (shared by both languages).') + + +def wiki_slug(page): + language, *parts = page.relative_to(DOCS).parts + relative = Path(*parts) + return language + '-' + ('Home' if relative == Path('index.md') else relative.with_suffix('').as_posix().replace('/', '-')) + + +def export_wiki(args): + checked = check() + output = Path(args.output).resolve() + if output.exists() and any(output.iterdir()): + raise SystemExit('Choose an empty output directory; Wiki export does not overwrite existing work.') + output.mkdir(parents=True, exist_ok=True) + slugs = {p.resolve(): wiki_slug(p) for p in checked} + if len(set(slugs.values())) != len(slugs): + raise SystemExit('Wiki page names collide') + for page in checked: + def replace_link(match): + url = urlsplit(match[2]) + if url.scheme or url.netloc or not url.path: + return match[0] + target = (page.parent / unquote(url.path)).resolve() + if target in slugs: + destination = slugs[target] + else: + destination = CONFIG['repo_url'].rstrip('/') + '/blob/master/' + target.relative_to(ROOT).as_posix() + if url.fragment: + destination += '#' + url.fragment + return match[1] + destination + match[3] + chunks = re.split(r'(^```.*?^```[^\n]*$)', page.read_text(), flags=re.M | re.S) + for index in range(0, len(chunks), 2): + chunks[index] = LINK.sub(replace_link, chunks[index]) + relative = page.relative_to(DOCS) + counterpart = DOCS / ('en' if relative.parts[0] == 'zh' else 'zh') / Path(*relative.parts[1:]) + label = 'English' if relative.parts[0] == 'zh' else '中文' + source = CONFIG['repo_url'].rstrip('/') + '/blob/master/' + page.relative_to(ROOT).as_posix() + content = f'[{label}]({slugs[counterpart.resolve()]}) · [源文档 / Source]({source})\n\n' + ''.join(chunks) + (output / (slugs[page.resolve()] + '.md')).write_text(content) + (output / 'Home.md').write_text('# ' + CONFIG['site_name'] + '\n\n[中文](zh-Home) | [English](en-Home)\n') + sidebar = ['[Home](Home)', ''] + translations = CONFIG['plugins'][0]['i18n']['languages'][1].get('nav_translations', {}) + for language, name in [('zh', '中文'), ('en', 'English')]: + sidebar += ['## ' + name, ''] + def add_navigation(entries, indent=''): + for entry in entries: + for title, value in entry.items(): + label = translations.get(title, title) if language == 'en' else title + if isinstance(value, list): + sidebar.append(f'{indent}- **{label}**') + add_navigation(value, indent + ' ') + else: + sidebar.append(f'{indent}- [{label}]({slugs[(DOCS / language / value).resolve()]})') + add_navigation(CONFIG['nav']) + sidebar.append('') + (output / '_Sidebar.md').write_text('\n'.join(sidebar)) + (output / '_Footer.md').write_text('来源 / Source: [' + CONFIG['repo_url'] + '](' + CONFIG['repo_url'] + '). ' + '内容在主仓库维护 / Content is maintained in the source repository.\n') + for page in output.glob('*.md'): + for target in Links(page.read_text()).targets: + url = urlsplit(target) + if not url.scheme and url.path and not (output / (url.path + '.md')).exists(): + raise SystemExit(f'Broken exported Wiki link: {page.name}: {target}') + manifest = {p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in sorted(output.glob('*.md'))} + (output / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n') + print(f'Exported {len(manifest)} Wiki pages to {output}; no remote repository was modified.') + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + sub = parser.add_subparsers(dest='action', required=True) + sub.add_parser('check') + test = sub.add_parser('test') + test.add_argument('--python', default=sys.executable) + test.add_argument('--cwd', help='Working directory for examples importing a generated DUT') + test.add_argument('--cxx', default='c++') + test.add_argument('--include', help='Installed xcomm SDK include directory') + test.add_argument('--lib', help='Installed xcomm native library directory') + wiki = sub.add_parser('wiki') + wiki.add_argument('--output', required=True) + args = parser.parse_args() + if args.action == 'check': + check() + elif args.action == 'test': + run_examples(args) + else: + export_wiki(args) + + +if __name__ == '__main__': + main() diff --git a/test/README.md b/test/README.md index 75f2bfb1..796b0acc 100644 --- a/test/README.md +++ b/test/README.md @@ -1,27 +1,25 @@ -Picker test suite +# Picker tests / Picker 测试 -Overview -- Provides lightweight scripts to validate picker CLI and core flows. -- Focuses on Verilator + Python by default to minimize toolchain needs. +[English testing guide](../doc/en/development/contributing.md) | [中文测试指南](../doc/zh/development/contributing.md) -Prerequisites -- Built picker binary at `./build/bin/picker` (or installed `picker` in PATH). -- Verilator (>=4.218), CMake (>=3.11), a C++ compiler, Python3. +These scripts check the CLI and export/pack flows. Verilator and Python are the default integration path. Prepare a built Picker, CMake, a C++20 compiler, SWIG and matching Python development tools; see [installation](../doc/en/guides/installation.md). -Usage -- Run all: `make -C test all` -- Smoke only (no builds): `make -C test smoke` -- Individual: - - `make -C test export_python` - - `make -C test export_vpi_python` - - `make -C test export_filelist` - - `make -C test export_complex_port` - - `make -C test pack_transaction` - - `make -C test pack_from_rtl` - - `make -C test pack_unsupported_type` - - `make -C test pack_multiple_classes` - - `make -C test pack_python` +这里验证 CLI 和 export/pack 流程,默认集成为 Verilator + Python。先准备 Picker、CMake、C++20 编译器、SWIG 和匹配的 Python 开发环境,见[安装](../doc/zh/guides/installation.md)。 -Notes -- Tests write to subfolders in the repo (e.g. `picker_out_*`, `pack_example`). -- Clean with `make -C test clean`. +| Command / 命令 | Scope / 范围 | +| --- | --- | +| `make -C test all` | Integration suite / 集成测试 | +| `make -C test smoke` | CLI smoke, without DUT builds / CLI 冒烟,不构建 DUT | +| `make -C test export_python` | Python Adder export / Python 加法器 | +| `make -C test export_vpi_python` | VPI export / VPI 导出 | +| `make -C test export_filelist` | File lists / 文件列表 | +| `make -C test export_complex_port` | Complex ports / 复杂端口 | +| `make -C test pack_transaction` | UVM transactions / UVM 事务 | +| `make -C test pack_from_rtl` | Transactions from RTL / 从 RTL 生成事务 | +| `make -C test pack_unsupported_type` | Unsupported types / 不支持的类型 | +| `make -C test pack_multiple_classes` | Multiple classes / 多类事务 | +| `make -C test pack_python` | Python packaging / Python 包装 | + +Tests write generated directories such as picker_out_* and pack_example. `make -C test clean` removes test outputs. The preflight may rebuild missing bindings; use a separate checkout when preserving other build artifacts. + +测试会生成 picker_out_*、pack_example 等目录;`make -C test clean` 清理测试产物。preflight 可能重建缺失绑定;需保留其他构建产物时使用独立 checkout。 From a97371fb917602a1eace36cc508866eaf2349c81 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:33:45 +0800 Subject: [PATCH 2/8] Publish uc-picker with uc-xcomm and pip SWIG dependencies --- .build-config.yml | 2 +- .github/workflows/ci.yml | 8 +++++-- .github/workflows/release-build.yml | 37 +++++++++++++++++------------ .github/workflows/release.yml | 29 +++++++++++++++++++++- CMakeLists.txt | 2 +- Makefile | 2 +- README.md | 2 ++ README.zh.md | 2 ++ doc/en/development/releases.md | 30 ++++++++++++++++++++++- doc/en/guides/installation.md | 25 +++++++++++++++---- doc/zh/development/releases.md | 25 +++++++++++++++++++ doc/zh/guides/installation.md | 24 +++++++++++++++---- pyproject.toml | 21 ++++++++++++++-- scripts/build/verify-wheel.sh | 28 ++++++++++++++++------ 14 files changed, 196 insertions(+), 41 deletions(-) diff --git a/.build-config.yml b/.build-config.yml index 54eead3a..6e30286b 100644 --- a/.build-config.yml +++ b/.build-config.yml @@ -4,4 +4,4 @@ tools: node: 20.12.2 python: 3.11 dependencies: - xcomm: c39db6652cd08d46df05d08f0bb5a033b83e4d2f + xcomm: 69e993d4fc0c8786819d2beae50a2197ea4ab124 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 750cbe7f..aa1279bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,6 +88,10 @@ jobs: echo "NODE_VERSION=$(sed -n 's/^ node:[[:space:]]*//p' .build-config.yml)" >> "$GITHUB_ENV" echo "PYTHON_VERSION=$(sed -n 's/^ python:[[:space:]]*//p' .build-config.yml)" >> "$GITHUB_ENV" + - uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + - name: Install native build toolchain run: bash scripts/build/setup-native-toolchain.sh @@ -156,8 +160,8 @@ jobs: - name: Build Python wheels if: matrix.full_test env: - # Match the planned xcomm 1.x release while it is still in development. - SETUPTOOLS_SCM_PRETEND_VERSION_FOR_XSPCOMM: 1.0.0.dev0 + # Exercise the dependency range with the pinned upcoming uc-xcomm release. + SETUPTOOLS_SCM_PRETEND_VERSION_FOR_UC_XCOMM: 1.1.0 run: | python3 -m venv /tmp/picker-wheel-builder /tmp/picker-wheel-builder/bin/python -m pip install 'build>=1,<2' diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 7ce2885f..1bc0d23f 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -11,7 +11,7 @@ on: required: true type: string xcomm_version: - description: "Optional compatible xspcomm release; latest compatible is selected by default" + description: "Optional compatible uc-xcomm release; latest compatible is selected by default" required: false type: string @@ -56,7 +56,7 @@ jobs: python scripts/release/tag_policy.py verify HEAD echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - - name: Select compatible xspcomm release + - name: Select compatible uc-xcomm release id: xcomm env: GH_TOKEN: ${{ github.token }} @@ -70,11 +70,13 @@ jobs: import os import re import tomllib + from urllib.error import HTTPError + from urllib.request import urlopen from packaging.requirements import Requirement with open("pyproject.toml", "rb") as config: dependencies = tomllib.load(config)["project"]["dependencies"] - requirement = next(Requirement(dependency) for dependency in dependencies if Requirement(dependency).name == "xspcomm") + requirement = next(Requirement(dependency) for dependency in dependencies if Requirement(dependency).name == "uc-xcomm") with open("/tmp/xspcomm-releases.json") as source: releases = json.load(source) compatible = [] @@ -84,19 +86,27 @@ jobs: continue version = tag[1:] if requirement.specifier.contains(version): - compatible.append((tuple(map(int, version.split("."))), version)) + try: + with urlopen(f"https://pypi.org/pypi/uc-xcomm/{version}/json", timeout=30) as response: + published = json.load(response) + except HTTPError as error: + if error.code == 404: + continue + raise + if any(not artifact["yanked"] for artifact in published["urls"]): + compatible.append((tuple(map(int, version.split("."))), version)) requested = os.environ["REQUESTED_VERSION"] if requested: if requested not in {version for _, version in compatible}: - raise SystemExit(f"xspcomm v{requested} is not a compatible published release") + raise SystemExit(f"uc-xcomm v{requested} is not a compatible published release") version = requested elif compatible: version = max(compatible)[1] else: - raise SystemExit(f"No published xspcomm release satisfies {requirement}") + raise SystemExit(f"No published uc-xcomm release satisfies {requirement}") with open(os.environ["GITHUB_OUTPUT"], "a") as output: print(f"version={version}", file=output) - print(f"Using xspcomm v{version}") + print(f"Using uc-xcomm v{version}") PY wheel: needs: resolve @@ -112,21 +122,18 @@ jobs: - name: Build Picker wheel run: | set -euo pipefail - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - build-essential cmake ninja-build bison flex gperf zlib1g-dev liblz4-dev - python -m pip install 'build>=1,<2' + python -m pip install 'cibuildwheel==3.4.1' 'twine>=6,<7' XCOMM_SKIP_ALIGN=1 make init - export CMAKE_BUILD_PARALLEL_LEVEL="$(nproc)" - NO_BUILD_XSPCOMM=1 python -m build --wheel - - name: Download released xspcomm wheel + python -m cibuildwheel --only cp312-manylinux_x86_64 --output-dir dist + python -m twine check --strict dist/*.whl + - name: Download released uc-xcomm wheels env: GH_TOKEN: ${{ github.token }} XCOMM_VERSION: ${{ needs.resolve.outputs.xcomm_version }} run: | mkdir -p wheelhouse gh release download "v${XCOMM_VERSION}" \ - -R XS-MLVP/xcomm --pattern '*.whl' --dir wheelhouse + -R XS-MLVP/xcomm --pattern 'uc_xcomm-*.whl' --dir wheelhouse - name: Install and verify released wheels env: PICKER_WHEEL_DIR: dist diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 45dbcb9c..9e9099f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,7 +66,7 @@ jobs: archives = [name for name in assets if name.endswith(".tar.gz")] assert len(wheels) == 1 and len(appimages) == 2 and len(archives) == 2 assert assets == set(wheels + appimages + archives + ["RELEASE-MANIFEST.json", "SHA256SUMS"]) - assert wheels[0].startswith(f"picker-{tag[1:]}-") + assert wheels[0].startswith(f"uc_picker-{tag[1:]}-") assert set(appimages) == {f"picker-{tag}-linux-{arch}.AppImage" for arch in ("x86_64", "aarch64")} assert set(archives) == {f"picker-{tag}-linux-{arch}.tar.gz" for arch in ("x86_64", "aarch64")} with open(os.environ["GITHUB_OUTPUT"], "a") as output: @@ -92,3 +92,30 @@ jobs: files: release-assets/* fail_on_unmatched_files: true overwrite_files: true + + pypi: + needs: publish + runs-on: ubuntu-24.04 + environment: + name: pypi + url: https://pypi.org/p/uc-picker + permissions: + actions: read + contents: read + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + name: picker-release-bundle + run-id: ${{ inputs.run_id }} + github-token: ${{ github.token }} + path: verified-assets + - name: Select the verified Python distribution + run: | + (cd verified-assets && sha256sum --check SHA256SUMS) + mkdir dist + cp verified-assets/*.whl dist/ + - name: Publish with Trusted Publishing + uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip-existing: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 8080e09b..d4c17d73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) #dependencies -if ("$ENV{NO_BUILD_XSPCOMM}" STREQUAL "") +if (NOT SKBUILD AND "$ENV{NO_BUILD_XSPCOMM}" STREQUAL "") add_subdirectory(dependence/xcomm) # Cover pinned xcomm revisions as well as their SWIG consumers. Standalone # xcomm wheels are built separately by the wheel target in the Makefile. diff --git a/Makefile b/Makefile index 2a6fb65b..5a12c1fe 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,7 @@ wheel: mkdir -p dist && cp dependence/xcomm/dist/*.whl ./dist wheel_install: wheel - @echo "Install in a fresh virtual environment: $(PYTHON) -m pip install --no-index --find-links=dist picker" + @echo "Install in a fresh virtual environment: $(PYTHON) -m pip install --find-links=dist uc-picker" # Run test suite tests: diff --git a/README.md b/README.md index 84029078..b19a52c9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ English | [中文](README.zh.md) Picker exports Verilog/SystemVerilog designs as Python, C++, Java, Scala, Go, or Lua modules, so you can write hardware tests in a familiar language. Tests can read and write signals, advance clocks, check results, and save waveforms. Picker also generates transaction bridges between Python and UVM. +The Python distribution is `uc-picker`; the command remains `picker`. It depends on `uc-xcomm` and SWIG. + ## Get started [Install Picker](doc/en/guides/installation.md), then follow the [adder tutorial](doc/en/tutorials/first-dut.md) to run your first test. From the repository root, export a Python module: diff --git a/README.zh.md b/README.zh.md index 207db645..6c18c776 100644 --- a/README.zh.md +++ b/README.zh.md @@ -4,6 +4,8 @@ Picker 将 Verilog/SystemVerilog 设计导出为 Python、C++、Java、Scala、Go 或 Lua 模块,方便你用熟悉的语言编写硬件测试。测试代码可以读写信号、推进时钟、检查结果和保存波形。Picker 也支持生成连接 Python 与 UVM 的事务桥。 +Python 发行包名为 `uc-picker`,命令仍为 `picker`,依赖 `uc-xcomm` 和 SWIG。 + ## 开始使用 先[安装 Picker](doc/zh/guides/installation.md),再跟随[加法器教程](doc/zh/tutorials/first-dut.md)完成第一次验证。在仓库根目录导出 Python 模块: diff --git a/doc/en/development/releases.md b/doc/en/development/releases.md index c35f2914..72785379 100644 --- a/doc/en/development/releases.md +++ b/doc/en/development/releases.md @@ -41,4 +41,32 @@ bash scripts/build/verify-wheel.sh Wheel checks need build outputs in `dist/`. Use `PICKER_WHEEL_DIR` and `XCOMM_WHEEL_DIR` to select other directories. The script installs packages and checks interfaces in a separate environment. -Release artifacts are published to GitHub Releases. Documentation CI provides site and Wiki previews as build artifacts; see [documentation maintenance](documentation.md). +Release artifacts are published to GitHub Releases. The verified Python wheel is then published to PyPI as `uc-picker`. Documentation CI provides site and Wiki previews as build artifacts; see [documentation maintenance](documentation.md). + +## Python distribution and PyPI setup + +The distribution is `uc-picker`; the executable remains `picker`. It requires +`uc-xcomm>=1.1,<2` and SWIG 4.5.1. Publish `uc-xcomm` first: Tagged CI selects a +compatible stable release available on both GitHub and PyPI. Development CI pins +the corresponding xcomm source and uses a test-only version matching this range. + +The release wheel is built in the pinned manylinux 2.28 x86-64 image, with generic +CPU flags and static C++ runtime linking, then audited before upload. It uses +`py3-none-manylinux_2_28_x86_64`: Picker does not bind to a Python minor version, +but its `uc-xcomm` dependency does. A wheel always omits bundled xcomm bindings; +raw CMake builds can still build them. AppImages and native archives retain their +existing architectures and filenames. Development wheels retain their host tags. + +Create a pending GitHub publisher in [PyPI Publishing](https://pypi.org/manage/account/publishing/): + +| Field | Value | +| --- | --- | +| Project name | `uc-picker` | +| Owner | `XS-MLVP` | +| Repository | `picker` | +| Workflow filename | `release.yml` | +| Environment | `pypi` | + +Create the matching GitHub environment, allowing releases from `master`. No PyPI +API token is needed. If the initial PyPI job fails before setup is complete, +configure the publisher and rerun that job with the same verified CI bundle. diff --git a/doc/en/guides/installation.md b/doc/en/guides/installation.md index 8f996a9c..d757f997 100644 --- a/doc/en/guides/installation.md +++ b/doc/en/guides/installation.md @@ -58,9 +58,24 @@ picker --check Next, export and run the [adder tutorial](../tutorials/first-dut.md) to check the full compilation and simulation process. +## Install with pip + +After the first PyPI release, install `uc-picker` in a Python 3.11+ environment: + +```sh +python -m pip install uc-picker +python -m pip check +picker --version +``` + +Pip installs `uc-xcomm` and SWIG automatically. The official Picker wheel targets +Linux x86-64 with GLIBC 2.28 or newer and is independent of the Python minor +version. CMake, the C++ compiler and the simulator remain system dependencies. +For other environments, use a matching native archive or build from source. + ## Use a release package -[GitHub Releases](https://github.com/XS-MLVP/picker/releases) provides Linux AppImages, installation archives, and Python wheels. Choose a file for your machine's architecture. Wheels must also match the Python minor version. +[GitHub Releases](https://github.com/XS-MLVP/picker/releases) provides Linux AppImages, installation archives, and Python wheels. Choose a file for your machine's architecture. Picker wheels use `py3-none` because the command-line launcher has no Python C API dependency; they still target a specific OS and architecture. The `uc-xcomm` dependency must match the Python minor version. For an AppImage, make the downloaded file executable and run it. For an installation archive, extract the full directory and add its `bin` directory to `PATH`. Templates and runtime resources are located through the installation tree, so keep them together when distributing it. @@ -69,12 +84,12 @@ To install wheels, put Picker and the dependency wheels listed in the release no ```sh python3 -m venv .venv . .venv/bin/activate -python -m pip install --no-index --find-links=wheels picker +python -m pip install --no-index --find-links=wheels uc-picker python -m pip check picker --check ``` -Exporting new models also requires the Verilator, SWIG, and compilation tools listed above. +The Python dependencies include `uc-xcomm>=1.1,<2` and SWIG 4.5.1. For offline installation, include their wheels in `wheels/` too. Exporting new models still requires a system simulator, CMake and a C++ compiler. ## Build wheels locally @@ -85,8 +100,8 @@ python3 -m venv .venv . .venv/bin/activate python -m pip install build make wheel PYTHON="$VIRTUAL_ENV/bin/python" -python -m pip install --no-index --find-links=dist picker +python -m pip install --find-links=dist uc-picker python -m pip check ``` -The wheels are written to `dist/`. You can copy them to another environment with the same Python minor version and platform. +The wheels are written to `dist/`. Picker wheels can be reused across supported Python minor versions on the same platform; the accompanying `uc-xcomm` wheel must match the target interpreter. Pip obtains SWIG separately when installing from `dist/`. diff --git a/doc/zh/development/releases.md b/doc/zh/development/releases.md index 7d197354..8ef29503 100644 --- a/doc/zh/development/releases.md +++ b/doc/zh/development/releases.md @@ -42,3 +42,28 @@ bash scripts/build/verify-wheel.sh wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` 和 `XCOMM_WHEEL_DIR` 指定目录。脚本在独立环境安装并检查包和接口。 当前发行产物发布到 GitHub Releases。文档 CI 的站点和 Wiki 预览可从构建 artifacts 下载,见[文档维护](documentation.md)。 + +## Python 分发包与 PyPI 配置 + +分发包名为 `uc-picker`,命令仍是 `picker`,依赖 `uc-xcomm>=1.1,<2` 和 SWIG 4.5.1。 +先发布 `uc-xcomm`;Tagged CI 选择同时存在于 GitHub 与 PyPI 的兼容稳定版本。 +开发 CI 固定对应 xcomm 提交,仅在测试构建中使用满足目标范围的版本号。 + +发行 wheel 在固定的 manylinux 2.28 x86-64 镜像中构建,使用通用 CPU 参数并静态链接 +C++ 运行库,通过审计后上传。标签为 `py3-none-manylinux_2_28_x86_64`:Picker 本身 +不绑定 Python 小版本,但依赖 `uc-xcomm` 仍绑定。wheel 不再内置 xcomm 绑定,原始 +CMake 构建仍可编译它。AppImage 与原生压缩包保留现有架构和文件名;开发 wheel +保留构建主机的平台标签。 + +在 [PyPI Publishing](https://pypi.org/manage/account/publishing/) 登记 pending GitHub publisher: + +| 字段 | 值 | +| --- | --- | +| Project name | `uc-picker` | +| Owner | `XS-MLVP` | +| Repository | `picker` | +| Workflow filename | `release.yml` | +| Environment | `pypi` | + +创建同名 GitHub 环境,允许从 `master` 发行。无需 PyPI API token。若首次 PyPI 任务 +因配置未完成而失败,补齐发布者后重跑该任务,复用同一份已验证 CI 产物。 diff --git a/doc/zh/guides/installation.md b/doc/zh/guides/installation.md index 0096d05d..6db8009e 100644 --- a/doc/zh/guides/installation.md +++ b/doc/zh/guides/installation.md @@ -58,9 +58,23 @@ picker --check 接下来按[加法器教程](../tutorials/first-dut.md)导出并运行一个模型,检查整个编译和仿真过程。 +## 使用 pip 安装 + +首次 PyPI 发行完成后,在 Python 3.11+ 环境安装 `uc-picker`: + +```sh +python -m pip install uc-picker +python -m pip check +picker --version +``` + +pip 自动安装 `uc-xcomm` 和 SWIG。官方 Picker wheel 面向 GLIBC 2.28 或更新的 Linux +x86-64 环境,不绑定 Python 小版本。CMake、C++ 编译器和仿真器由系统提供。 +其他环境可使用匹配的原生压缩包或从源码构建。 + ## 使用发行包 -[GitHub Releases](https://github.com/XS-MLVP/picker/releases) 提供 Linux AppImage、安装目录压缩包和 Python wheel。按主机架构选择文件;wheel 还需要匹配 Python 小版本。 +[GitHub Releases](https://github.com/XS-MLVP/picker/releases) 提供 Linux AppImage、安装目录压缩包和 Python wheel。按主机架构选择文件;Picker wheel 使用 `py3-none`,命令行启动器不依赖 Python C API,但仍区分操作系统与架构;依赖 `uc-xcomm` 的 wheel 需要匹配 Python 小版本。 使用 AppImage 时,赋予下载文件执行权限后运行。使用安装目录压缩包时,完整解压并将其中的 `bin` 加入 `PATH`。模板和运行资源通过安装目录定位,分发时一起保留。 @@ -69,12 +83,12 @@ picker --check ```sh python3 -m venv .venv . .venv/bin/activate -python -m pip install --no-index --find-links=wheels picker +python -m pip install --no-index --find-links=wheels uc-picker python -m pip check picker --check ``` -导出新模型仍需要本页列出的 Verilator、SWIG 和编译工具。 +Python 依赖包含 `uc-xcomm>=1.1,<2` 与 SWIG 4.5.1;离线安装时也要把它们的 wheel 放入 `wheels/`。导出新模型仍需系统提供仿真器、CMake 与 C++ 编译器。 ## 自行构建 wheel @@ -85,8 +99,8 @@ python3 -m venv .venv . .venv/bin/activate python -m pip install build make wheel PYTHON="$VIRTUAL_ENV/bin/python" -python -m pip install --no-index --find-links=dist picker +python -m pip install --find-links=dist uc-picker python -m pip check ``` -生成的 wheel 位于 `dist/`,可复制到使用相同 Python 小版本和平台的环境中安装。 +生成的 wheel 位于 `dist/`,其中 Picker wheel 可用于相同平台的受支持 Python 小版本,配套的 `uc-xcomm` wheel 仍须匹配目标解释器。使用 `dist/` 安装时,pip 会另行下载 SWIG。 diff --git a/pyproject.toml b/pyproject.toml index bf49267d..46a30b4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,16 @@ requires = ["scikit-build-core>=1.0,<2", "setuptools-scm>=8,<10"] build-backend = "scikit_build_core.build" [project] -name = "picker" +name = "uc-picker" dynamic = ["version"] +description = "Generate hardware simulation interfaces for multiple programming languages" +readme = "README.md" +requires-python = ">=3.11" +license = "MulanPSL-2.0" +license-files = ["LICENSE"] dependencies = [ - "xspcomm>=1.0.0.dev0,<2", + "uc-xcomm>=1.1,<2", + "swig==4.5.1", ] [[tool.dynamic-metadata]] @@ -20,7 +26,18 @@ local_scheme = "no-local-version" [tool.scikit-build] wheel.install-dir = "picker" +wheel.py-api = "py3" +build.targets = ["picker"] wheel.packages = ["src/python/picker"] [project.scripts] picker = "picker:cmd" + +[tool.cibuildwheel] +build = ["cp312-manylinux_x86_64"] +build-frontend = "build" +environment = { CMAKE_GENERATOR = "Unix Makefiles", CMAKE_BUILD_PARALLEL_LEVEL = "4", CXXFLAGS = "-march=x86-64 -mtune=generic", LDFLAGS = "-static-libstdc++ -static-libgcc" } + +[tool.cibuildwheel.linux] +manylinux-x86_64-image = "quay.io/pypa/manylinux_2_28_x86_64@sha256:076b19ef6e698f28649fa817c49d14443201e01da85240e8e52f93e8daa49bff" +repair-wheel-command = "auditwheel repair --only-plat --plat manylinux_2_28_x86_64 -w {dest_dir} {wheel}" diff --git a/scripts/build/verify-wheel.sh b/scripts/build/verify-wheel.sh index af87ad7c..09d9019f 100644 --- a/scripts/build/verify-wheel.sh +++ b/scripts/build/verify-wheel.sh @@ -4,34 +4,48 @@ set -euo pipefail picker_wheel_dir=${PICKER_WHEEL_DIR:-dist} xcomm_wheel_dir=${XCOMM_WHEEL_DIR:-dist} verify_python=${VERIFY_PYTHON:-python3} -picker_spec=picker -xcomm_spec=xspcomm +picker_spec=uc-picker +xcomm_spec=uc-xcomm if [[ -n "${PICKER_VERSION_EXPECTED:-}" ]]; then - picker_spec="picker==${PICKER_VERSION_EXPECTED}" + picker_spec="uc-picker==${PICKER_VERSION_EXPECTED}" fi if [[ -n "${XCOMM_VERSION_EXPECTED:-}" ]]; then - xcomm_spec="xspcomm==${XCOMM_VERSION_EXPECTED}" + xcomm_spec="uc-xcomm==${XCOMM_VERSION_EXPECTED}" fi test_dir=$(mktemp -d /tmp/picker-wheel-test.XXXXXX) trap 'rm -rf -- "${test_dir}"' EXIT +swig_wheel_dir=${SWIG_WHEEL_DIR:-${test_dir}/tools} +if [[ -z "${SWIG_WHEEL_DIR:-}" ]]; then + "${verify_python}" -m pip download --only-binary=:all: --no-deps \ + --dest "${swig_wheel_dir}" 'swig==4.5.1' +fi "${verify_python}" -m venv "${test_dir}/venv" "${test_dir}/venv/bin/python" -m pip install --no-index \ - --find-links="${picker_wheel_dir}" --find-links="${xcomm_wheel_dir}" \ + --find-links="${picker_wheel_dir}" --find-links="${xcomm_wheel_dir}" --find-links="${swig_wheel_dir}" \ "${picker_spec}" "${xcomm_spec}" "${test_dir}/venv/bin/python" -m pip check +export PATH="${test_dir}/venv/bin:${PATH}" cd "${test_dir}" "${test_dir}/venv/bin/python" - <<'PY' import os +from pathlib import Path +import shutil import subprocess import sys from importlib.metadata import version import xspcomm -picker_version = version("picker") -xcomm_version = version("xspcomm") +swig = shutil.which("swig") +assert swig and Path(swig).parent == Path(sys.executable).parent, swig +subprocess.run([swig, "-version"], check=True) +Path("CMakeLists.txt").write_text('cmake_minimum_required(VERSION 3.15)\nproject(InstalledSWIG NONE)\nfind_package(SWIG 4.5 REQUIRED)\n') +subprocess.run(["cmake", "-S", ".", "-B", "swig-check"], check=True) + +picker_version = version("uc-picker") +xcomm_version = version("uc-xcomm") if os.environ.get("PICKER_VERSION_EXPECTED"): assert picker_version == os.environ["PICKER_VERSION_EXPECTED"] if os.environ.get("XCOMM_VERSION_EXPECTED"): From 0761a8e8b994cece4dec01b846dada8f121a1f49 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:38:49 +0800 Subject: [PATCH 3/8] Disable native runtime tuning in tagged Picker releases --- doc/en/development/releases.md | 3 ++- doc/zh/development/releases.md | 4 ++-- scripts/build/build-native.sh | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/en/development/releases.md b/doc/en/development/releases.md index 72785379..c7ebeb3a 100644 --- a/doc/en/development/releases.md +++ b/doc/en/development/releases.md @@ -54,7 +54,8 @@ The release wheel is built in the pinned manylinux 2.28 x86-64 image, with gener CPU flags and static C++ runtime linking, then audited before upload. It uses `py3-none-manylinux_2_28_x86_64`: Picker does not bind to a Python minor version, but its `uc-xcomm` dependency does. A wheel always omits bundled xcomm bindings; -raw CMake builds can still build them. AppImages and native archives retain their +raw CMake builds can still build them. Tagged native releases also disable +`XSPCOMM_NATIVE` for the bundled runtime. AppImages and native archives retain their existing architectures and filenames. Development wheels retain their host tags. Create a pending GitHub publisher in [PyPI Publishing](https://pypi.org/manage/account/publishing/): diff --git a/doc/zh/development/releases.md b/doc/zh/development/releases.md index 8ef29503..7203da72 100644 --- a/doc/zh/development/releases.md +++ b/doc/zh/development/releases.md @@ -41,7 +41,7 @@ bash scripts/build/verify-wheel.sh wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` 和 `XCOMM_WHEEL_DIR` 指定目录。脚本在独立环境安装并检查包和接口。 -当前发行产物发布到 GitHub Releases。文档 CI 的站点和 Wiki 预览可从构建 artifacts 下载,见[文档维护](documentation.md)。 +发行产物先发布到 GitHub Releases,已验证的 Python wheel 随后发布到 PyPI。文档 CI 的站点和 Wiki 预览可从构建 artifacts 下载,见[文档维护](documentation.md)。 ## Python 分发包与 PyPI 配置 @@ -52,7 +52,7 @@ wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` 发行 wheel 在固定的 manylinux 2.28 x86-64 镜像中构建,使用通用 CPU 参数并静态链接 C++ 运行库,通过审计后上传。标签为 `py3-none-manylinux_2_28_x86_64`:Picker 本身 不绑定 Python 小版本,但依赖 `uc-xcomm` 仍绑定。wheel 不再内置 xcomm 绑定,原始 -CMake 构建仍可编译它。AppImage 与原生压缩包保留现有架构和文件名;开发 wheel +CMake 构建仍可编译它。正式原生发行也会关闭所带 runtime 的 `XSPCOMM_NATIVE`。AppImage 与原生压缩包保留现有架构和文件名;开发 wheel 保留构建主机的平台标签。 在 [PyPI Publishing](https://pypi.org/manage/account/publishing/) 登记 pending GitHub publisher: diff --git a/scripts/build/build-native.sh b/scripts/build/build-native.sh index 599e92fc..2458dfa2 100644 --- a/scripts/build/build-native.sh +++ b/scripts/build/build-native.sh @@ -33,6 +33,7 @@ if [[ -n "${PICKER_RELEASE_VERSION:-}" ]]; then cmake_args+=( "-DSKBUILD_PROJECT_VERSION=${PICKER_RELEASE_VERSION}" "-DSKBUILD_PROJECT_VERSION_FULL=${PICKER_RELEASE_VERSION}" + "-DXSPCOMM_NATIVE=OFF" ) fi cmake_args+=('-DCMAKE_INSTALL_RPATH=$ORIGIN/../lib') From 3e6a8a34be376fa7c56a457ee448adad0055dd59 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Sat, 24 Oct 2026 08:04:29 +0800 Subject: [PATCH 4/8] Build fully static Picker wheels for manylinux 2.17 --- .github/workflows/ci.yml | 5 ++ .github/workflows/portable-wheel.yml | 93 +++++++++++++++++++++++ .github/workflows/release-build.yml | 26 +++---- CMakeLists.txt | 1 + doc/en/development/releases.md | 29 +++++-- doc/en/guides/installation.md | 2 +- doc/zh/development/releases.md | 21 +++-- doc/zh/guides/installation.md | 2 +- pyproject.toml | 6 +- scripts/release/check_installed_picker.py | 67 ++++++++++++++++ scripts/release/check_static_wheel.py | 57 ++++++++++++++ src/CMakeLists.txt | 5 +- test/release/test_static_wheel.py | 51 +++++++++++++ 13 files changed, 335 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/portable-wheel.yml create mode 100644 scripts/release/check_installed_picker.py create mode 100644 scripts/release/check_static_wheel.py create mode 100644 test/release/test_static_wheel.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa1279bb..2fc8fee6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,6 +52,11 @@ jobs: echo 'run_build=false' >> "$GITHUB_OUTPUT" fi + portable-wheel: + needs: branch-or-pr + if: needs.branch-or-pr.outputs.run_build == 'true' + uses: ./.github/workflows/portable-wheel.yml + build-and-test: needs: branch-or-pr if: needs.branch-or-pr.outputs.run_build == 'true' diff --git a/.github/workflows/portable-wheel.yml b/.github/workflows/portable-wheel.yml new file mode 100644 index 00000000..ba145b88 --- /dev/null +++ b/.github/workflows/portable-wheel.yml @@ -0,0 +1,93 @@ +name: Portable Picker wheel + +on: + workflow_call: + inputs: + ref: + type: string + default: '' + artifact-name: + type: string + default: picker-portable-wheel + xcomm-version: + type: string + default: '' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref || github.sha }} + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Build and audit the fully static wheel + run: | + python -m pip install 'cibuildwheel==3.4.1' 'twine>=6,<7' + XCOMM_SKIP_ALIGN=1 make init + python -m cibuildwheel --only cp312-manylinux_x86_64 --output-dir dist + python scripts/release/check_static_wheel.py dist/*.whl + python -m twine check --strict dist/*.whl + - uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact-name }} + path: dist/*.whl + if-no-files-found: error + + compatibility: + needs: build + runs-on: ubuntu-24.04 + strategy: + matrix: + python: [cp311-cp311, cp312-cp312] + glibc: ['2.17', '2.28'] + include: + - glibc: '2.17' + image: quay.io/pypa/manylinux2014_x86_64@sha256:3a591c1109773dbd79f16c038588fd1867d9f2f708b360dab5715852c7f96ef0 + - glibc: '2.28' + image: quay.io/pypa/manylinux_2_28_x86_64@sha256:076b19ef6e698f28649fa817c49d14443201e01da85240e8e52f93e8daa49bff + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref || github.sha }} + - uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact-name }} + path: dist + - name: Fetch the released runtime and SWIG for integration checks + if: inputs.xcomm-version != '' + env: + GH_TOKEN: ${{ github.token }} + XCOMM_VERSION: ${{ inputs.xcomm-version }} + run: | + mkdir -p dependencies + gh release download "v${XCOMM_VERSION}" -R XS-MLVP/xcomm \ + --pattern 'uc_xcomm-*.whl' --dir dependencies + python3 -m pip download --only-binary=:all: --no-deps \ + --dest dependencies 'swig==4.5.1' + - name: Install and exercise the same wheel on the target platform + env: + TEST_IMAGE: ${{ matrix.image }} + TEST_PYTHON: ${{ matrix.python }} + EXPECTED_GLIBC: ${{ matrix.glibc }} + CHECK_PICKER_RUNTIME: ${{ inputs.xcomm-version != '' && '1' || '' }} + run: | + docker run --rm --network none \ + -v "$PWD:/project:ro" -e EXPECTED_GLIBC -e TEST_PYTHON -e CHECK_PICKER_RUNTIME \ + "$TEST_IMAGE" bash -euo pipefail -c ' + /opt/python/$TEST_PYTHON/bin/python -m venv /tmp/picker-test + export PATH="/tmp/picker-test/bin:$PATH" + if [[ "$CHECK_PICKER_RUNTIME" == 1 ]]; then + python -m pip install --no-index --find-links /project/dependencies /project/dist/*.whl + python -m pip check + else + python -m pip install --no-index --no-deps /project/dist/*.whl + fi + /tmp/picker-test/bin/python /project/scripts/release/check_installed_picker.py + ' diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 1bc0d23f..2b4d1a9a 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -108,8 +108,16 @@ jobs: print(f"version={version}", file=output) print(f"Using uc-xcomm v{version}") PY - wheel: + portable-wheel: needs: resolve + uses: ./.github/workflows/portable-wheel.yml + with: + ref: ${{ github.event.client_payload.tag || inputs.tag }} + artifact-name: picker-release-wheel + xcomm-version: ${{ needs.resolve.outputs.xcomm_version }} + + wheel: + needs: [resolve, portable-wheel] runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -119,13 +127,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" - - name: Build Picker wheel - run: | - set -euo pipefail - python -m pip install 'cibuildwheel==3.4.1' 'twine>=6,<7' - XCOMM_SKIP_ALIGN=1 make init - python -m cibuildwheel --only cp312-manylinux_x86_64 --output-dir dist - python -m twine check --strict dist/*.whl + - uses: actions/download-artifact@v4 + with: + name: picker-release-wheel + path: dist - name: Download released uc-xcomm wheels env: GH_TOKEN: ${{ github.token }} @@ -142,11 +147,6 @@ jobs: XCOMM_VERSION_EXPECTED: ${{ needs.resolve.outputs.xcomm_version }} VERIFY_PYTHON: python run: bash scripts/build/verify-wheel.sh - - uses: actions/upload-artifact@v4 - with: - name: picker-release-wheel - path: dist/*.whl - if-no-files-found: error native: needs: resolve diff --git a/CMakeLists.txt b/CMakeLists.txt index d4c17d73..239366ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ if(is_top_level_project) endif() # options +option(PICKER_REQUIRE_STATIC "Require a fully static Picker executable" OFF) option(CPPAST_BUILD_TEST "whether or not to build the tests" OFF) option(CPPAST_BUILD_EXAMPLE "whether or not to build the examples" OFF) option(CPPAST_BUILD_TOOL "whether or not to build the tool" OFF) diff --git a/doc/en/development/releases.md b/doc/en/development/releases.md index c7ebeb3a..8239958a 100644 --- a/doc/en/development/releases.md +++ b/doc/en/development/releases.md @@ -50,13 +50,28 @@ The distribution is `uc-picker`; the executable remains `picker`. It requires compatible stable release available on both GitHub and PyPI. Development CI pins the corresponding xcomm source and uses a test-only version matching this range. -The release wheel is built in the pinned manylinux 2.28 x86-64 image, with generic -CPU flags and static C++ runtime linking, then audited before upload. It uses -`py3-none-manylinux_2_28_x86_64`: Picker does not bind to a Python minor version, -but its `uc-xcomm` dependency does. A wheel always omits bundled xcomm bindings; -raw CMake builds can still build them. Tagged native releases also disable -`XSPCOMM_NATIVE` for the bundled runtime. AppImages and native archives retain their -existing architectures and filenames. Development wheels retain their host tags. +The release wheel is built with a modern compiler in the pinned manylinux 2.28 +x86-64 image, with generic CPU flags and **fully static linking**, including libc. +`PICKER_REQUIRE_STATIC=ON` makes missing static libraries a build error. The wheel +check rejects an ELF interpreter, shared-library dependencies, or bundled native +bindings before auditwheel assigns `py3-none-manylinux_2_17_x86_64` (also carrying +the equivalent `manylinux2014_x86_64` tag). The tag describes the supported runtime, +not the build image. + +The same reusable workflow runs in PR CI and Tagged CI. It installs the same +wheel on Python 3.11 and 3.12 in both GLIBC 2.17 and 2.28 containers, then checks +CLI behavior and installed templates. For tagged releases, these checks also +install the selected published xcomm and SWIG wheels, import the runtime, parse +RTL into a UVM package and export a Python DUT without compiling the simulator. +These container tests exercise the target userspace; they share the runner's +kernel and do not independently establish an old-kernel support guarantee. +Tagged CI also verifies the installed `uc-xcomm` and SWIG dependency chain. + +Picker does not bind to a Python minor version, but its `uc-xcomm` dependency +does. A wheel always omits bundled xcomm bindings; raw CMake builds can still +build them. Tagged native releases disable `XSPCOMM_NATIVE` for the bundled +runtime. AppImages and native archives retain their existing architectures and +filenames. Development wheels built outside this workflow retain their host tags. Create a pending GitHub publisher in [PyPI Publishing](https://pypi.org/manage/account/publishing/): diff --git a/doc/en/guides/installation.md b/doc/en/guides/installation.md index d757f997..3568e0e1 100644 --- a/doc/en/guides/installation.md +++ b/doc/en/guides/installation.md @@ -69,7 +69,7 @@ picker --version ``` Pip installs `uc-xcomm` and SWIG automatically. The official Picker wheel targets -Linux x86-64 with GLIBC 2.28 or newer and is independent of the Python minor +Linux x86-64 with GLIBC 2.17 or newer and is independent of the Python minor version. CMake, the C++ compiler and the simulator remain system dependencies. For other environments, use a matching native archive or build from source. diff --git a/doc/zh/development/releases.md b/doc/zh/development/releases.md index 7203da72..1079f3ff 100644 --- a/doc/zh/development/releases.md +++ b/doc/zh/development/releases.md @@ -49,11 +49,22 @@ wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` 先发布 `uc-xcomm`;Tagged CI 选择同时存在于 GitHub 与 PyPI 的兼容稳定版本。 开发 CI 固定对应 xcomm 提交,仅在测试构建中使用满足目标范围的版本号。 -发行 wheel 在固定的 manylinux 2.28 x86-64 镜像中构建,使用通用 CPU 参数并静态链接 -C++ 运行库,通过审计后上传。标签为 `py3-none-manylinux_2_28_x86_64`:Picker 本身 -不绑定 Python 小版本,但依赖 `uc-xcomm` 仍绑定。wheel 不再内置 xcomm 绑定,原始 -CMake 构建仍可编译它。正式原生发行也会关闭所带 runtime 的 `XSPCOMM_NATIVE`。AppImage 与原生压缩包保留现有架构和文件名;开发 wheel -保留构建主机的平台标签。 +发行 wheel 在固定的 manylinux 2.28 x86-64 镜像中使用较新编译器构建,采用通用 +CPU 参数并**完全静态链接**,包括 libc。`PICKER_REQUIRE_STATIC=ON` 让缺少静态库 +直接导致构建失败。wheel 检查拒绝 ELF 动态解释器、共享库依赖和内置原生绑定, +随后由 auditwheel 标记为 `py3-none-manylinux_2_17_x86_64`,同时携带等价的 +`manylinux2014_x86_64` 标签。标签表示运行兼容范围,与构建镜像版本无须一致。 + +PR CI 与 Tagged CI 复用同一工作流,将同一份 wheel 分别安装到 GLIBC 2.17、2.28 +容器中的 Python 3.11、3.12,检查 CLI 行为和安装的模板。正式发行还会安装选定的 +xcomm、SWIG 已发布 wheel,导入 runtime,将 RTL 解析为 UVM 包,并导出 Python +DUT,不编译仿真器。容器测试覆盖对应用户态环境,但共享 runner 的内核,不能单独证明旧内核 +兼容性。Tagged CI 还会验证安装后的 `uc-xcomm` 和 SWIG 依赖链。 + +Picker 本身不绑定 Python 小版本,但依赖 `uc-xcomm` 仍绑定。wheel 不内置 xcomm +绑定,原始 CMake 构建仍可编译它。正式原生发行关闭所带 runtime 的 +`XSPCOMM_NATIVE`。AppImage 与原生压缩包保留现有架构和文件名;未使用此工作流 +构建的开发 wheel 保留主机平台标签。 在 [PyPI Publishing](https://pypi.org/manage/account/publishing/) 登记 pending GitHub publisher: diff --git a/doc/zh/guides/installation.md b/doc/zh/guides/installation.md index 6db8009e..80ddaea7 100644 --- a/doc/zh/guides/installation.md +++ b/doc/zh/guides/installation.md @@ -68,7 +68,7 @@ python -m pip check picker --version ``` -pip 自动安装 `uc-xcomm` 和 SWIG。官方 Picker wheel 面向 GLIBC 2.28 或更新的 Linux +pip 自动安装 `uc-xcomm` 和 SWIG。官方 Picker wheel 面向 GLIBC 2.17 或更新的 Linux x86-64 环境,不绑定 Python 小版本。CMake、C++ 编译器和仿真器由系统提供。 其他环境可使用匹配的原生压缩包或从源码构建。 diff --git a/pyproject.toml b/pyproject.toml index 46a30b4b..06f62a38 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,10 @@ build = ["cp312-manylinux_x86_64"] build-frontend = "build" environment = { CMAKE_GENERATOR = "Unix Makefiles", CMAKE_BUILD_PARALLEL_LEVEL = "4", CXXFLAGS = "-march=x86-64 -mtune=generic", LDFLAGS = "-static-libstdc++ -static-libgcc" } +[tool.cibuildwheel.config-settings] +"cmake.define.PICKER_REQUIRE_STATIC" = "ON" + [tool.cibuildwheel.linux] manylinux-x86_64-image = "quay.io/pypa/manylinux_2_28_x86_64@sha256:076b19ef6e698f28649fa817c49d14443201e01da85240e8e52f93e8daa49bff" -repair-wheel-command = "auditwheel repair --only-plat --plat manylinux_2_28_x86_64 -w {dest_dir} {wheel}" +before-all = "dnf install -y glibc-static" +repair-wheel-command = "python {project}/scripts/release/check_static_wheel.py {wheel} && auditwheel repair --only-plat --plat manylinux_2_17_x86_64 -w {dest_dir} {wheel}" diff --git a/scripts/release/check_installed_picker.py b/scripts/release/check_installed_picker.py new file mode 100644 index 00000000..804c8dc7 --- /dev/null +++ b/scripts/release/check_installed_picker.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Exercise an installed Picker wheel, optionally with its released runtime.""" + +import ast +from importlib.metadata import version +import os +from pathlib import Path +import subprocess +import sys +import tempfile + + +picker = str(Path(sys.executable).parent / "picker") +expected_glibc = os.environ.get("EXPECTED_GLIBC") +if expected_glibc: + assert os.confstr("CS_GNU_LIBC_VERSION") == f"glibc {expected_glibc}" + +with tempfile.TemporaryDirectory(prefix="picker-installed-") as directory: + root = Path(directory) + output = subprocess.check_output([picker, "--version"], cwd=root, text=True) + assert version("uc-picker") in output, output + subprocess.run([picker, "export", "--help"], cwd=root, check=True, capture_output=True) + invalid = subprocess.run([picker, "--not-a-picker-option"], cwd=root, capture_output=True) + assert invalid.returncode != 0, "the launcher swallowed the native error" + + templates = subprocess.check_output([picker, "--show_default_template_path"], cwd=root, text=True) + template_path = Path(templates.strip().splitlines()[-1]) + assert template_path.is_relative_to(Path(sys.prefix)), template_path + assert (template_path / "uvm/xagent.py").is_file() + + # Release checks use the exact published xcomm wheels. PR checks can run + # before that dependency has been published and cover the standalone CLI. + if os.environ.get("CHECK_PICKER_RUNTIME") == "1": + import xspcomm + + signal = xspcomm.XData(8, xspcomm.XData.InOut) + signal.Set(0xA5) + assert signal.U() == 0xA5 + subprocess.run(["swig", "-version"], check=True, capture_output=True) + source = root / "Adder.sv" + source.write_text("""module Adder(input logic [7:0] a, b, output logic [8:0] sum); +assign sum = {1'b0, a} + {1'b0, b}; +endmodule +""") + subprocess.run([picker, "pack", "--from-rtl", str(source), "--name", "Adder"], cwd=root, check=True) + package = root / "Adder" + for name in ["xagent.py", "__init__.py"]: + ast.parse((package / name).read_text()) + assert (package / "xagent.sv").is_file() + transactions = list(package.glob("*_trans.sv")) + assert len(transactions) == 1, transactions + transaction = transactions[0].read_text() + assert "sum" in transaction and "[7:0]" in transaction, transaction + output = root / "dut" + result = subprocess.run([ + picker, "export", str(source), "--sname", "Adder", "--lang", "python", + "--tdir", str(output), "--autobuild", "false", + ], cwd=root, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode: + print(result.stdout) + result.check_returncode() + assert (output / "signals.json").is_file() + ast.parse((output / "python/dut.py").read_text()) + print("Runtime import, SWIG, RTL packing and Python DUT export passed") + +print(f"Installed Picker passed on Python {sys.version_info.major}.{sys.version_info.minor}, " + f"{os.confstr('CS_GNU_LIBC_VERSION')}") diff --git a/scripts/release/check_static_wheel.py b/scripts/release/check_static_wheel.py new file mode 100644 index 00000000..dcf8cd0b --- /dev/null +++ b/scripts/release/check_static_wheel.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +"""Reject release wheels whose Picker executable is not fully static x86-64.""" + +import argparse +import os +from pathlib import Path +import re +import struct +import subprocess +import tempfile +import zipfile + + +EXECUTABLE = "picker/bin/picker" + + +def check_wheel(path: Path) -> None: + with zipfile.ZipFile(path) as wheel: + elf_files = [] + for name in wheel.namelist(): + with wheel.open(name) as member: + header = member.read(20) + if header.startswith(b"\x7fELF"): + elf_files.append(name) + if len(header) < 20 or header[4:6] != b"\x02\x01" or struct.unpack_from("> 16) & 0o111: + raise ValueError(f"{EXECUTABLE} is not executable") + with tempfile.TemporaryDirectory(prefix="picker-static-check-") as directory: + executable = Path(directory) / "picker" + executable.write_bytes(wheel.read(EXECUTABLE)) + env = dict(os.environ, LC_ALL="C") + program_headers = subprocess.check_output(["readelf", "-lW", str(executable)], text=True, env=env) + dynamic = subprocess.check_output(["readelf", "-dW", str(executable)], text=True, env=env) + versions = subprocess.check_output(["readelf", "-VW", str(executable)], text=True, env=env) + if re.search(r"^\s*INTERP\s", program_headers, re.MULTILINE) or "(NEEDED)" in dynamic: + raise ValueError("Picker is dynamically linked; release wheels require a fully static executable") + if "Version needs section" in versions: + raise ValueError("Picker still requires versioned symbols from shared libraries") + print(f"{path.name}: fully static x86-64 Picker; no bundled native bindings") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("wheels", type=Path, nargs="+") + args = parser.parse_args() + for path in args.wheels: + try: + check_wheel(path) + except ValueError as error: + parser.exit(1, f"{path.name}: {error}\n") + + +if __name__ == "__main__": + main() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3788ada2..986db60e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,9 @@ install( search_libs(ALL_FOUND LIBS libm.a libc.a) if (ALL_FOUND) - target_link_options(${PROJECT_NAME} PRIVATE "-static") + target_link_options(${PROJECT_NAME} PRIVATE "-static") +elseif(PICKER_REQUIRE_STATIC) + message(FATAL_ERROR "PICKER_REQUIRE_STATIC needs libc.a and libm.a; install the static C library development package") else() message(WARNING "picker cannot be built statically") endif() @@ -27,4 +29,3 @@ endif() # # Add AppImage target # add_custom_target(appimage - \ No newline at end of file diff --git a/test/release/test_static_wheel.py b/test/release/test_static_wheel.py new file mode 100644 index 00000000..4a992608 --- /dev/null +++ b/test/release/test_static_wheel.py @@ -0,0 +1,51 @@ +"""Exercise the release guard with actual static and dynamic ELF executables.""" + +import importlib.util +from pathlib import Path +import platform +import subprocess +import tempfile +import unittest +import zipfile + + +ROOT = Path(__file__).resolve().parents[2] +spec = importlib.util.spec_from_file_location("static_wheel", ROOT / "scripts/release/check_static_wheel.py") +static_wheel = importlib.util.module_from_spec(spec) +spec.loader.exec_module(static_wheel) + + +@unittest.skipUnless(platform.system() == "Linux" and platform.machine() == "x86_64", "Linux x86-64 release guard") +class StaticWheelTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.directory = tempfile.TemporaryDirectory(prefix="picker-static-test-") + cls.addClassCleanup(cls.directory.cleanup) + cls.root = Path(cls.directory.name) + source = cls.root / "main.c" + source.write_text("int main(void) { return 0; }\n") + for name, flags in [("static", ["-static"]), ("dynamic", [])]: + subprocess.run(["cc", str(source), *flags, "-o", str(cls.root / name)], check=True, capture_output=True) + + def wheel(self, executable, extra=False): + path = self.root / "test.whl" + with zipfile.ZipFile(path, "w") as archive: + archive.write(self.root / executable, static_wheel.EXECUTABLE) + if extra: + archive.write(self.root / "dynamic", "xspcomm/_xspcomm.so") + return path + + def test_fully_static_executable_passes(self): + static_wheel.check_wheel(self.wheel("static")) + + def test_dynamic_executable_is_rejected(self): + with self.assertRaisesRegex(ValueError, "dynamically linked"): + static_wheel.check_wheel(self.wheel("dynamic")) + + def test_bundled_native_bindings_are_rejected(self): + with self.assertRaisesRegex(ValueError, "native payload"): + static_wheel.check_wheel(self.wheel("static", extra=True)) + + +if __name__ == "__main__": + unittest.main() From c3b30e5dff3b15ebd2643b844b7e975aa39c2438 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Sat, 24 Oct 2026 08:31:58 +0800 Subject: [PATCH 5/8] Accept supported SWIG 4.x versions for Python installs --- .build-config.yml | 2 +- .github/workflows/portable-wheel.yml | 2 +- .github/workflows/release-build.yml | 4 ++++ doc/en/development/releases.md | 2 +- doc/en/guides/installation.md | 2 +- doc/zh/development/releases.md | 2 +- doc/zh/guides/installation.md | 2 +- pyproject.toml | 2 +- scripts/build/verify-wheel.sh | 7 ++++--- 9 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.build-config.yml b/.build-config.yml index 6e30286b..eb73c63c 100644 --- a/.build-config.yml +++ b/.build-config.yml @@ -4,4 +4,4 @@ tools: node: 20.12.2 python: 3.11 dependencies: - xcomm: 69e993d4fc0c8786819d2beae50a2197ea4ab124 + xcomm: e3220142baec761009a182bde18f1dee2fa18aee diff --git a/.github/workflows/portable-wheel.yml b/.github/workflows/portable-wheel.yml index ba145b88..a79cd522 100644 --- a/.github/workflows/portable-wheel.yml +++ b/.github/workflows/portable-wheel.yml @@ -70,7 +70,7 @@ jobs: gh release download "v${XCOMM_VERSION}" -R XS-MLVP/xcomm \ --pattern 'uc_xcomm-*.whl' --dir dependencies python3 -m pip download --only-binary=:all: --no-deps \ - --dest dependencies 'swig==4.5.1' + --dest dependencies 'swig>=4.2.1,<5' - name: Install and exercise the same wheel on the target platform env: TEST_IMAGE: ${{ matrix.image }} diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 2b4d1a9a..a65bc796 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -119,6 +119,9 @@ jobs: wheel: needs: [resolve, portable-wheel] runs-on: ubuntu-24.04 + strategy: + matrix: + swig: ['4.2.1', '4.5.1'] steps: - uses: actions/checkout@v4 with: @@ -146,6 +149,7 @@ jobs: PICKER_VERSION_EXPECTED: ${{ needs.resolve.outputs.version }} XCOMM_VERSION_EXPECTED: ${{ needs.resolve.outputs.xcomm_version }} VERIFY_PYTHON: python + SWIG_SPEC: swig==${{ matrix.swig }} run: bash scripts/build/verify-wheel.sh native: diff --git a/doc/en/development/releases.md b/doc/en/development/releases.md index 8239958a..44feea9a 100644 --- a/doc/en/development/releases.md +++ b/doc/en/development/releases.md @@ -46,7 +46,7 @@ Release artifacts are published to GitHub Releases. The verified Python wheel is ## Python distribution and PyPI setup The distribution is `uc-picker`; the executable remains `picker`. It requires -`uc-xcomm>=1.1,<2` and SWIG 4.5.1. Publish `uc-xcomm` first: Tagged CI selects a +`uc-xcomm>=1.1,<2` and `swig>=4.2.1,<5`. Publish `uc-xcomm` first: Tagged CI selects a compatible stable release available on both GitHub and PyPI. Development CI pins the corresponding xcomm source and uses a test-only version matching this range. diff --git a/doc/en/guides/installation.md b/doc/en/guides/installation.md index 3568e0e1..fe10133e 100644 --- a/doc/en/guides/installation.md +++ b/doc/en/guides/installation.md @@ -89,7 +89,7 @@ python -m pip check picker --check ``` -The Python dependencies include `uc-xcomm>=1.1,<2` and SWIG 4.5.1. For offline installation, include their wheels in `wheels/` too. Exporting new models still requires a system simulator, CMake and a C++ compiler. +The Python dependencies include `uc-xcomm>=1.1,<2` and `swig>=4.2.1,<5`. For offline installation, include their wheels in `wheels/` too. Exporting new models still requires a system simulator, CMake and a C++ compiler. ## Build wheels locally diff --git a/doc/zh/development/releases.md b/doc/zh/development/releases.md index 1079f3ff..8e81b9ad 100644 --- a/doc/zh/development/releases.md +++ b/doc/zh/development/releases.md @@ -45,7 +45,7 @@ wheel 检查需要 `dist/` 中有构建产物,也可通过 `PICKER_WHEEL_DIR` ## Python 分发包与 PyPI 配置 -分发包名为 `uc-picker`,命令仍是 `picker`,依赖 `uc-xcomm>=1.1,<2` 和 SWIG 4.5.1。 +分发包名为 `uc-picker`,命令仍是 `picker`,依赖 `uc-xcomm>=1.1,<2` 和 `swig>=4.2.1,<5`。 先发布 `uc-xcomm`;Tagged CI 选择同时存在于 GitHub 与 PyPI 的兼容稳定版本。 开发 CI 固定对应 xcomm 提交,仅在测试构建中使用满足目标范围的版本号。 diff --git a/doc/zh/guides/installation.md b/doc/zh/guides/installation.md index 80ddaea7..55ac6092 100644 --- a/doc/zh/guides/installation.md +++ b/doc/zh/guides/installation.md @@ -88,7 +88,7 @@ python -m pip check picker --check ``` -Python 依赖包含 `uc-xcomm>=1.1,<2` 与 SWIG 4.5.1;离线安装时也要把它们的 wheel 放入 `wheels/`。导出新模型仍需系统提供仿真器、CMake 与 C++ 编译器。 +Python 依赖包含 `uc-xcomm>=1.1,<2` 与 `swig>=4.2.1,<5`;离线安装时也要把它们的 wheel 放入 `wheels/`。导出新模型仍需系统提供仿真器、CMake 与 C++ 编译器。 ## 自行构建 wheel diff --git a/pyproject.toml b/pyproject.toml index 06f62a38..c1afeb2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ license = "MulanPSL-2.0" license-files = ["LICENSE"] dependencies = [ "uc-xcomm>=1.1,<2", - "swig==4.5.1", + "swig>=4.2.1,<5", ] [[tool.dynamic-metadata]] diff --git a/scripts/build/verify-wheel.sh b/scripts/build/verify-wheel.sh index 09d9019f..acce41e7 100644 --- a/scripts/build/verify-wheel.sh +++ b/scripts/build/verify-wheel.sh @@ -4,6 +4,7 @@ set -euo pipefail picker_wheel_dir=${PICKER_WHEEL_DIR:-dist} xcomm_wheel_dir=${XCOMM_WHEEL_DIR:-dist} verify_python=${VERIFY_PYTHON:-python3} +swig_spec=${SWIG_SPEC:-'swig>=4.2.1,<5'} picker_spec=uc-picker xcomm_spec=uc-xcomm if [[ -n "${PICKER_VERSION_EXPECTED:-}" ]]; then @@ -18,12 +19,12 @@ trap 'rm -rf -- "${test_dir}"' EXIT swig_wheel_dir=${SWIG_WHEEL_DIR:-${test_dir}/tools} if [[ -z "${SWIG_WHEEL_DIR:-}" ]]; then "${verify_python}" -m pip download --only-binary=:all: --no-deps \ - --dest "${swig_wheel_dir}" 'swig==4.5.1' + --dest "${swig_wheel_dir}" "${swig_spec}" fi "${verify_python}" -m venv "${test_dir}/venv" "${test_dir}/venv/bin/python" -m pip install --no-index \ --find-links="${picker_wheel_dir}" --find-links="${xcomm_wheel_dir}" --find-links="${swig_wheel_dir}" \ - "${picker_spec}" "${xcomm_spec}" + "${picker_spec}" "${xcomm_spec}" "${swig_spec}" "${test_dir}/venv/bin/python" -m pip check export PATH="${test_dir}/venv/bin:${PATH}" @@ -41,7 +42,7 @@ import xspcomm swig = shutil.which("swig") assert swig and Path(swig).parent == Path(sys.executable).parent, swig subprocess.run([swig, "-version"], check=True) -Path("CMakeLists.txt").write_text('cmake_minimum_required(VERSION 3.15)\nproject(InstalledSWIG NONE)\nfind_package(SWIG 4.5 REQUIRED)\n') +Path("CMakeLists.txt").write_text('cmake_minimum_required(VERSION 3.15)\nproject(InstalledSWIG NONE)\nfind_package(SWIG 4.2.1 REQUIRED)\n') subprocess.run(["cmake", "-S", ".", "-B", "swig-check"], check=True) picker_version = version("uc-picker") From 85fb45bc7432e9e94b59f8bb8805c40f0d544a0a Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Sat, 24 Oct 2026 08:35:06 +0800 Subject: [PATCH 6/8] Run wheel verification with the latest supported SWIG --- .build-config.yml | 4 ++-- .github/workflows/release-build.yml | 4 ---- scripts/build/verify-wheel.sh | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.build-config.yml b/.build-config.yml index eb73c63c..9daabd87 100644 --- a/.build-config.yml +++ b/.build-config.yml @@ -1,7 +1,7 @@ tools: verilator: v5.052 - swig: v4.2.1 + swig: v4.5.1 node: 20.12.2 python: 3.11 dependencies: - xcomm: e3220142baec761009a182bde18f1dee2fa18aee + xcomm: b3f48f40d3aa362b021fb8e4955ebd3765d56705 diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index a65bc796..2b4d1a9a 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -119,9 +119,6 @@ jobs: wheel: needs: [resolve, portable-wheel] runs-on: ubuntu-24.04 - strategy: - matrix: - swig: ['4.2.1', '4.5.1'] steps: - uses: actions/checkout@v4 with: @@ -149,7 +146,6 @@ jobs: PICKER_VERSION_EXPECTED: ${{ needs.resolve.outputs.version }} XCOMM_VERSION_EXPECTED: ${{ needs.resolve.outputs.xcomm_version }} VERIFY_PYTHON: python - SWIG_SPEC: swig==${{ matrix.swig }} run: bash scripts/build/verify-wheel.sh native: diff --git a/scripts/build/verify-wheel.sh b/scripts/build/verify-wheel.sh index acce41e7..1ccc0307 100644 --- a/scripts/build/verify-wheel.sh +++ b/scripts/build/verify-wheel.sh @@ -4,7 +4,7 @@ set -euo pipefail picker_wheel_dir=${PICKER_WHEEL_DIR:-dist} xcomm_wheel_dir=${XCOMM_WHEEL_DIR:-dist} verify_python=${VERIFY_PYTHON:-python3} -swig_spec=${SWIG_SPEC:-'swig>=4.2.1,<5'} +swig_spec='swig>=4.2.1,<5' picker_spec=uc-picker xcomm_spec=uc-xcomm if [[ -n "${PICKER_VERSION_EXPECTED:-}" ]]; then From 8d439449b521fe6a71076870d153d604bcb8d38f Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Sat, 24 Oct 2026 09:42:03 +0800 Subject: [PATCH 7/8] Unify README badges and validate documentation links --- README.md | 21 ++++++++++++++------- README.zh.md | 21 ++++++++++++++------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b19a52c9..a5cc3e3c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # Picker -English | [中文](README.zh.md) +[![PyPI: not published](https://img.shields.io/badge/pypi-not%20published-lightgrey?style=flat-square&logo=pypi&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/installation.md) +[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue?style=flat-square&logo=python&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/installation.md) +[![PR CI](https://img.shields.io/github/actions/workflow/status/XS-MLVP/picker/ci.yml?event=pull_request&style=flat-square&label=PR%20CI&logo=github)](https://github.com/XS-MLVP/picker/actions/workflows/ci.yml?query=event%3Apull_request) +[![License](https://img.shields.io/badge/license-MulanPSL--2.0-blue?style=flat-square)](https://github.com/XS-MLVP/picker/blob/master/LICENSE) +[![Docs](https://img.shields.io/badge/docs-Guide-0A7EA4?style=flat-square)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/index.md) +[![GitHub Stars](https://img.shields.io/github/stars/XS-MLVP/picker?style=social)](https://github.com/XS-MLVP/picker) + +English | [中文](https://github.com/XS-MLVP/picker/blob/master/README.zh.md) Picker exports Verilog/SystemVerilog designs as Python, C++, Java, Scala, Go, or Lua modules, so you can write hardware tests in a familiar language. Tests can read and write signals, advance clocks, check results, and save waveforms. Picker also generates transaction bridges between Python and UVM. @@ -8,7 +15,7 @@ The Python distribution is `uc-picker`; the command remains `picker`. It depends ## Get started -[Install Picker](doc/en/guides/installation.md), then follow the [adder tutorial](doc/en/tutorials/first-dut.md) to run your first test. From the repository root, export a Python module: +[Install Picker](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/installation.md), then follow the [adder tutorial](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/tutorials/first-dut.md) to run your first test. From the repository root, export a Python module: ```sh picker export example/Adder/Adder.v --sname Adder --lang python \ @@ -20,14 +27,14 @@ Create a test in the generated package's parent directory to assign inputs by po ## Documentation -[English documentation](doc/en/index.md) · [完整中文文档](doc/zh/index.md) +[English documentation](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/index.md) · [完整中文文档](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/index.md) -- Use Picker: [export RTL](doc/en/guides/export.md), [clocks and waveforms](doc/en/guides/simulation.md), [internal signals](doc/en/guides/internal-signals.md), [languages](doc/en/guides/languages.md), [UVM](doc/en/guides/uvm-tlm.md). -- Look up an interface: [CLI](doc/en/reference/cli.md), [DUT API](doc/en/reference/dut-api.md), [troubleshooting](doc/en/reference/troubleshooting.md). -- Develop Picker: [how it works](doc/en/explanation/architecture.md), [contributing and tests](CONTRIBUTING.md), [documentation and Wiki](doc/en/development/documentation.md). +- Use Picker: [export RTL](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/export.md), [clocks and waveforms](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/simulation.md), [internal signals](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/internal-signals.md), [languages](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/languages.md), [UVM](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/uvm-tlm.md). +- Look up an interface: [CLI](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/reference/cli.md), [DUT API](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/reference/dut-api.md), [troubleshooting](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/reference/troubleshooting.md). +- Develop Picker: [how it works](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/explanation/architecture.md), [contributing and tests](https://github.com/XS-MLVP/picker/blob/master/CONTRIBUTING.md), [documentation and Wiki](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/development/documentation.md). ## Community Report issues and suggestions through [GitHub Issues](https://github.com/XS-MLVP/picker/issues). The community QQ group is 600480230. More verification resources are available in the [MLVP documentation](https://open-verify.cc/mlvp/docs/). -[Code of conduct](CODE_OF_CONDUCT.md) · [Security reports](SECURITY.md) · [License](LICENSE) +[Code of conduct](https://github.com/XS-MLVP/picker/blob/master/CODE_OF_CONDUCT.md) · [Security reports](https://github.com/XS-MLVP/picker/blob/master/SECURITY.md) · [License](https://github.com/XS-MLVP/picker/blob/master/LICENSE) diff --git a/README.zh.md b/README.zh.md index 6c18c776..115c933e 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,6 +1,13 @@ # Picker -中文 | [English](README.md) +[![PyPI: not published](https://img.shields.io/badge/pypi-not%20published-lightgrey?style=flat-square&logo=pypi&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/installation.md) +[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue?style=flat-square&logo=python&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/installation.md) +[![PR CI](https://img.shields.io/github/actions/workflow/status/XS-MLVP/picker/ci.yml?event=pull_request&style=flat-square&label=PR%20CI&logo=github)](https://github.com/XS-MLVP/picker/actions/workflows/ci.yml?query=event%3Apull_request) +[![License](https://img.shields.io/badge/license-MulanPSL--2.0-blue?style=flat-square)](https://github.com/XS-MLVP/picker/blob/master/LICENSE) +[![Docs](https://img.shields.io/badge/docs-Guide-0A7EA4?style=flat-square)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/index.md) +[![GitHub Stars](https://img.shields.io/github/stars/XS-MLVP/picker?style=social)](https://github.com/XS-MLVP/picker) + +中文 | [English](https://github.com/XS-MLVP/picker/blob/master/README.md) Picker 将 Verilog/SystemVerilog 设计导出为 Python、C++、Java、Scala、Go 或 Lua 模块,方便你用熟悉的语言编写硬件测试。测试代码可以读写信号、推进时钟、检查结果和保存波形。Picker 也支持生成连接 Python 与 UVM 的事务桥。 @@ -8,7 +15,7 @@ Python 发行包名为 `uc-picker`,命令仍为 `picker`,依赖 `uc-xcomm` ## 开始使用 -先[安装 Picker](doc/zh/guides/installation.md),再跟随[加法器教程](doc/zh/tutorials/first-dut.md)完成第一次验证。在仓库根目录导出 Python 模块: +先[安装 Picker](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/installation.md),再跟随[加法器教程](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/tutorials/first-dut.md)完成第一次验证。在仓库根目录导出 Python 模块: ```sh picker export example/Adder/Adder.v --sname Adder --lang python \ @@ -20,14 +27,14 @@ make -C build/docs-adder/Adder -j4 ## 文档 -[完整中文文档](doc/zh/index.md) · [English documentation](doc/en/index.md) +[完整中文文档](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/index.md) · [English documentation](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/index.md) -- 使用:[导出 RTL](doc/zh/guides/export.md)、[时钟与波形](doc/zh/guides/simulation.md)、[内部信号](doc/zh/guides/internal-signals.md)、[多语言](doc/zh/guides/languages.md)、[UVM](doc/zh/guides/uvm-tlm.md)。 -- 查询:[命令行](doc/zh/reference/cli.md)、[DUT API](doc/zh/reference/dut-api.md)、[故障排查](doc/zh/reference/troubleshooting.md)。 -- 开发:[工作原理](doc/zh/explanation/architecture.md)、[贡献与测试](CONTRIBUTING.md)、[文档与 Wiki](doc/zh/development/documentation.md)。 +- 使用:[导出 RTL](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/export.md)、[时钟与波形](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/simulation.md)、[内部信号](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/internal-signals.md)、[多语言](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/languages.md)、[UVM](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/uvm-tlm.md)。 +- 查询:[命令行](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/reference/cli.md)、[DUT API](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/reference/dut-api.md)、[故障排查](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/reference/troubleshooting.md)。 +- 开发:[工作原理](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/explanation/architecture.md)、[贡献与测试](https://github.com/XS-MLVP/picker/blob/master/CONTRIBUTING.md)、[文档与 Wiki](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/development/documentation.md)。 ## 社区 问题和建议请提交到 [GitHub Issues](https://github.com/XS-MLVP/picker/issues)。社区 QQ 群:600480230。更多验证资料见 [MLVP 文档](https://open-verify.cc/mlvp/docs/)。 -[行为准则](CODE_OF_CONDUCT.md) · [安全报告](SECURITY.md) · [许可证](LICENSE) +[行为准则](https://github.com/XS-MLVP/picker/blob/master/CODE_OF_CONDUCT.md) · [安全报告](https://github.com/XS-MLVP/picker/blob/master/SECURITY.md) · [许可证](https://github.com/XS-MLVP/picker/blob/master/LICENSE) From c6559af064a85508deab66c27fc4d9742f291305 Mon Sep 17 00:00:00 2001 From: Makiras <22570332+Makiras@users.noreply.github.com> Date: Sat, 24 Oct 2026 10:33:56 +0800 Subject: [PATCH 8/8] Use final PyPI version badges for the first release --- README.md | 2 +- README.zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a5cc3e3c..984d4c0b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Picker -[![PyPI: not published](https://img.shields.io/badge/pypi-not%20published-lightgrey?style=flat-square&logo=pypi&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/installation.md) +[![PyPI](https://img.shields.io/pypi/v/uc-picker?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/uc-picker/) [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue?style=flat-square&logo=python&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/en/guides/installation.md) [![PR CI](https://img.shields.io/github/actions/workflow/status/XS-MLVP/picker/ci.yml?event=pull_request&style=flat-square&label=PR%20CI&logo=github)](https://github.com/XS-MLVP/picker/actions/workflows/ci.yml?query=event%3Apull_request) [![License](https://img.shields.io/badge/license-MulanPSL--2.0-blue?style=flat-square)](https://github.com/XS-MLVP/picker/blob/master/LICENSE) diff --git a/README.zh.md b/README.zh.md index 115c933e..6fc6fe83 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,6 +1,6 @@ # Picker -[![PyPI: not published](https://img.shields.io/badge/pypi-not%20published-lightgrey?style=flat-square&logo=pypi&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/installation.md) +[![PyPI](https://img.shields.io/pypi/v/uc-picker?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/uc-picker/) [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue?style=flat-square&logo=python&logoColor=white)](https://github.com/XS-MLVP/picker/blob/85fb45bc7432e9e94b59f8bb8805c40f0d544a0a/doc/zh/guides/installation.md) [![PR CI](https://img.shields.io/github/actions/workflow/status/XS-MLVP/picker/ci.yml?event=pull_request&style=flat-square&label=PR%20CI&logo=github)](https://github.com/XS-MLVP/picker/actions/workflows/ci.yml?query=event%3Apull_request) [![License](https://img.shields.io/badge/license-MulanPSL--2.0-blue?style=flat-square)](https://github.com/XS-MLVP/picker/blob/master/LICENSE)