modified the structure of the files
本仓库是一个 RISC-V RV64 裸机量化大模型推理工程:在带 AME 矩阵加速器 与 RVV 向量扩展 的自研 SoC(AMD Versal Premium VP1902 FPGA / RTL 仿真)上运行 Qwen3-0.6B 的 W8A8 / W4A8 推理。
本文件是在一台干净 Linux 上从零复现编译环境的操作手册。照着 §1→§5 走即可。
apt
-lgcc
lld
pip
真正特殊、且无法用发行版软件替代的只有第 3 项。其余都是标准 apt/pip 包。
环境基线(本机已验证):Ubuntu 22.04(源 WSL2,正迁往原生 Linux),x86_64,Python 3.10.12。 整机迁移到 Linux 的完整搬运 / 避坑清单见 §7。
sudo apt update sudo apt install -y build-essential make cmake ninja-build \ python3 python3-pip git file coreutils gawk bc
(file/awk/od/dd/stat 被 test/sim/*/elf_to_verilog.sh 用到,coreutils/gawk 已包含。)
file/awk/od/dd/stat
test/sim/*/elf_to_verilog.sh
sudo apt install -y \ gcc-riscv64-linux-gnu \ binutils-riscv64-linux-gnu \ binutils-riscv64-unknown-elf
gcc-riscv64-linux-gnu
/usr/riscv64-linux-gnu
libgcc
binutils-riscv64-linux-gnu
riscv64-linux-gnu-objcopy
-readelf
binutils-riscv64-unknown-elf
riscv64-unknown-elf-objcopy
-objdump
所有 Makefile 给 clang 传的固定三元组参数就是基于这个 sysroot:
--target=riscv64-linux-gnu --sysroot=/usr/riscv64-linux-gnu --gcc-toolchain=/usr
可选:tools/bench/firmware 里的 RVV/SPM/AME operator L1 固件默认仍会找 /opt/riscv/riscv64-unknown-elf 这个 newlib 裸机 sysroot;DMA/SPM 和 AME pure 固件走 /usr/riscv64-linux-gnu + -lgcc。
tools/bench/firmware
/opt/riscv/riscv64-unknown-elf
工程所有裸机目标都用一个支持 AME 自定义指令的 LLVM/Clang fork。 发行版 apt install clang 装出来的 clang 不认识 AME 助记符(msettile*/mlae8/ mqma.b.mm 等),无法编译 models/qwen3/ame_mix_offline_i8.c 这类用真助记符的固件。 ⚠️ 注意发行版 clang-21 与本 fork 同名易混,迁移时尤其要确认走的是 fork——详见 §7.2。
apt install clang
msettile*
mlae8
mqma.b.mm
models/qwen3/ame_mix_offline_i8.c
clang-21
https://gitlink.org.cn/michaelcjl/llvm-project_riscv.git
ad6e3420706aaf5ab557d3023b5a3fac6e2954d7
clang version 21.0.0git
~/opt/llvm-project_riscv/build/bin/
clang
clang++
ld.lld
-fuse-ld=lld
llvm-ar
llvm-objcopy
llvm-objdump
llvm-nm
有两条路,优先选 A(自建一次要几个小时)。
如果还能访问已装好的旧机器,直接把整棵 build 目录搬过去最省事。
# 在旧机:打包(整棵约 7 GB,未裁剪) tar -C ~/opt -czf llvm-riscv-build.tgz llvm-project_riscv # 在新机:解到同样路径 mkdir -p ~/opt && tar -C ~/opt -xzf llvm-riscv-build.tgz
最小拷贝集(若想省空间,~4.3 GB → 可再 strip 减小):只需
strip
build/bin/
build/lib/clang/21/
stddef.h
二进制为未 strip 版本,体积大但可直接用。clang 会相对自身定位 ../lib/clang/21,所以保持 bin 与 lib 的相对结构即可。
../lib/clang/21
bin
lib
git clone https://gitlink.org.cn/michaelcjl/llvm-project_riscv.git ~/opt/llvm-project_riscv cd ~/opt/llvm-project_riscv git checkout ad6e3420706aaf5ab557d3023b5a3fac6e2954d7 cmake -S llvm -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DLLVM_TARGETS_TO_BUILD="RISCV" \ -DLLVM_ENABLE_EXPERIMENTAL_EXTENSIONS=ON ninja -C build clang clang-resource-headers lld llvm-ar llvm-objcopy llvm-objdump llvm-nm
(clang-resource-headers 确保生成 build/lib/clang/21/include。编译需 ~30+ GB 磁盘、较长时间。)
clang-resource-headers
build/lib/clang/21/include
Makefile 顶部用 CUSTOM_LLVM ?= $(HOME)/opt/llvm-project_riscv/build/bin 和 CLANG ?= .../clang-21 引用。装到默认路径就无需改任何东西。装别处则:
CUSTOM_LLVM ?= $(HOME)/opt/llvm-project_riscv/build/bin
CLANG ?= .../clang-21
make CLANG=/abs/path/clang-21 CUSTOM_LLVM=/abs/path/bin ...
✅ 重组时已清除历史硬编码用户路径(旧的 /home/luoyue、/home/zhang1)。 kernel/Makefile 与 models/qwen3/Makefile 现统一走 ~/opt/llvm-project_riscv/build/bin 默认通配;装别处用 make CLANG=... 覆盖即可。
/home/luoyue
/home/zhang1
kernel/Makefile
models/qwen3/Makefile
~/opt/llvm-project_riscv/build/bin
make CLANG=...
权重量化 / 生成 blob 的脚本(tools/quantization/*.py、tools/tokenizer/*.py、 tools/*.sh、tests/*/extract_real_case.py)需要:
tools/quantization/*.py
tools/tokenizer/*.py
tools/*.sh
tests/*/extract_real_case.py
python3 -m pip install torch transformers safetensors numpy
模型源:转换脚本默认从 /tmp/Qwen3-0.6B(HF safetensors)读取,可用 MODEL_SOURCE=/path/to/Qwen3-0.6B 覆盖。
/tmp/Qwen3-0.6B
MODEL_SOURCE=/path/to/Qwen3-0.6B
仓库不使用 git-lfs,也没有 requirements.txt。models/qwen3/model_data/*.bin(量化模型 blob) 是构建产物,由转换脚本生成,已被 .gitignore 排除,不随 git 迁移——迁移时只需带上 HF safetensors 源 + 转换脚本。
models/qwen3/model_data/*.bin
.gitignore
~/opt/llvm-project_riscv/build/bin/clang-21 --version # 应显示 21.0.0git ~/opt/llvm-project_riscv/build/bin/ld.lld --version riscv64-linux-gnu-objcopy --version riscv64-unknown-elf-objdump --version python3 -c "import torch,transformers,safetensors,numpy; print('ok')"
printf 'int f(int x){return x+1;}\n' > /tmp/_smoke.c ~/opt/llvm-project_riscv/build/bin/clang-21 \ --target=riscv64-linux-gnu --sysroot=/usr/riscv64-linux-gnu --gcc-toolchain=/usr \ -march=rv64imafdc -mabi=lp64d -mcmodel=medany -c /tmp/_smoke.c -o /tmp/_smoke.o file /tmp/_smoke.o # 期望: ELF 64-bit LSB relocatable, UCB RISC-V ...
# 算子库 libops_kernels(唯一可信源) make -C kernel static # -> kernel/build/libops_kernels.a # FPGA benchmark 固件(L1 峰值与 operator profile) make -C tools/bench/firmware l1_peaks # -> tools/bench/firmware/build/*.bin # W8A8 端到端裸机固件 # 若缺模型 blob,先转换(需 §4 的 Python 环境 + safetensors 源): MODEL_SOURCE=/path/to/Qwen3-0.6B bash tools/generate_w8a8_model.sh make -C models/qwen3 # -> models/qwen3/build/qwen3_chat_w8a8_ame_fpga.bin # RTL 波形仿真镜像(用到 riscv64-unknown-elf-objcopy/objdump) make -C tests/sim/dma_spm_w8a8 # -> build/verilog/ # FPGA flash bin(W4A8 路径示例) bash tests/flash/perf_dma_dequant_w4a8/build.sh # L1 峰值微基准(DDR/SPM、纯 SPM 口、AME MAC/cyc、RVV MEM+ARITH;须在仓库根目录) make -C tools/bench/firmware dma_spm_usage make -C tools/bench/firmware spm_port_peak_fpga make -C tools/bench/firmware ame_operator_profile_fpga make -C tools/bench/firmware rvv_flops_peak_fpga # 详情:models/qwen3/README.md「L1 峰值微基准编译」、docs/bench/measure_peaks_flash.md
所有裸机 ELF 在链接后会用 readelf 校验入口为 0x80000000,bin 按 64 字节对齐填充。 各模块的测试分类与运行要求见 tests/README.md;文档索引见 docs/README.md。
readelf
0x80000000
tests/README.md
docs/README.md
-mabi=lp64d -mcmodel=medany
-march=rv64imafdc
-march=rv64gcv
rv64gcv_zfh_zvfh_zicsr_zifencei
csrr vlenb
-mllvm -riscv-v-vector-bits-min=N -mllvm -riscv-v-vector-bits-max=N
*.ld
本节面向把整个工程从 WSL2 搬到一台原生 Linux。照 §7.1 把工具链配齐,§7.2 把 该带的东西带全,§7.3 落地后清理,最后用 §5 验证。
21.0.0git
ad6e342…
riscv64-unknown-unknown-elf
~/opt/llvm-project_riscv/build/lib/clang/21/include
riscv64-linux-gnu-{gcc,objcopy,readelf}
riscv64-unknown-elf-{objcopy,objdump}
python3
torch numpy transformers safetensors
make file awk od dd stat
elf_to_verilog.sh
落地后用 §5.1 的命令逐项核对版本。
/usr/bin/clang-21
x86_64
kernel/
.word 0x…
CLANG := $(if $(wildcard $(CUSTOM_LLVM)/clang-21),…,clang-21)
make CLANG=/abs/clang-21
搬运清单:
git
~/opt/llvm-project_riscv/build/
build/bin
build/lib/clang/21
tools/generate_w8a8_model.sh
tools/tokenizer/generate_tokenizer_blob.sh
MODEL_SOURCE=…
落地后必做(顺序很重要):
build/
.d
/mnt/d/...
find . -type d -name build -not -path './.git/*' -exec rm -rf {} +
/mnt/d
chmod +x tools/*.sh tools/tokenizer/*.sh tests/flash/*/build.sh
bash <script>
bad interpreter: /usr/bin/env bash^M
sed -i 's/\r$//' <script>
dos2unix
*:Zone.Identifier
/opt/riscv
tests/sim/*/elf_to_verilog.sh
riscv64-unknown-elf-objcopy/objdump
models/qwen3/
KERNEL_DIR=../../kernel
仓库按「编译内核 ↔ 模型运行时 ↔ 平台抽象 ↔ 工具 ↔ 测试 ↔ 文档」分层,每一类只有单一可信源(不再有三份内核 / 两份模型工作区的复制)。
work/ ├── kernel/ # 唯一算子库 libops_kernels(= vLLM csrc / pytorch aten) │ ├── include/backends/{scalar,rvv,ame,mix,w4a8}/ │ ├── src/backends/{scalar,rvv,ame,mix,w4a8}/ │ └── tests/ # 旧算子单元测试 / 探针,benchmark 已迁到 tools/bench/firmware ├── platform/ # 设备/启动抽象:uart、crt、encoding(= vLLM platforms) │ └── linker/ # *.ld 链接脚本 ├── tokenizer/ # 分词器组件:tokenizer_bpe.c + data/(词表/merges) ├── models/qwen3/ # Qwen3-0.6B W8A8 端到端运行时(= model_executor/models) │ └── model_data/ # config.json 入树;*.bin 权重 blob 为生成物(gitignore) ├── tools/ # 离线脚本(= pytorch/tools + vLLM 量化转换) │ ├── quantization/ # 权重量化 / 打包:W8A8 tile、W4A8、prune_lm_head… │ ├── tokenizer/ # tokenizer blob 生成 │ ├── calib/ # 激活校准统计 │ └── bench/firmware/ # FPGA benchmark 固件(L1 峰值 / DMA-SPM / operator profile) ├── tests/ # 集成测试:sim(RTL 波形镜像)/ flash(FPGA 烧录 bin) └── docs/ # ame/ dma/ quantization/ operator_report/ disasm/
libops_kernels
tools/bench/firmware/
platform/
encoding.h
linker/*.ld
tokenizer/
tools/
tests/sim/*
tests/flash/*
docs/
W8A8 vs beta:原 qwen3-w8a8 与 qwen3-w8a8-beta 已合并为单一主干 models/qwen3/(非 beta 为正统:更新、且含 SPM 流式 decode)。beta 的实验性运行时(窗口注意力、no-sat 激活量化)保留在重组前检查点的 git 历史中,可按需作为构建开关复活;其可复用工具(prune_lm_head.py)与数据变体已并入 tools/。
qwen3-w8a8
qwen3-w8a8-beta
prune_lm_head.py
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
work — Linux 环境复现指南
本仓库是一个 RISC-V RV64 裸机量化大模型推理工程:在带 AME 矩阵加速器 与 RVV 向量扩展 的自研 SoC(AMD Versal Premium VP1902 FPGA / RTL 仿真)上运行 Qwen3-0.6B 的 W8A8 / W4A8 推理。
本文件是在一台干净 Linux 上从零复现编译环境的操作手册。照着 §1→§5 走即可。
0. 需要装的东西(总表)
apt-lgcc、objcopy/readelf/objdumpaptlld链接器pip环境基线(本机已验证):Ubuntu 22.04(源 WSL2,正迁往原生 Linux),x86_64,Python 3.10.12。 整机迁移到 Linux 的完整搬运 / 避坑清单见 §7。
1. 主机基础工具
(
file/awk/od/dd/stat被test/sim/*/elf_to_verilog.sh用到,coreutils/gawk 已包含。)2. RISC-V GNU 交叉工具链
gcc-riscv64-linux-gnu/usr/riscv64-linux-gnu+libgcc(链接用-lgcc)binutils-riscv64-linux-gnuriscv64-linux-gnu-objcopy/-readelfbinutils-riscv64-unknown-elfriscv64-unknown-elf-objcopy/-objdump(仅 sim 生成 Verilog 镜像/反汇编时用)所有 Makefile 给 clang 传的固定三元组参数就是基于这个 sysroot:
3. 自研 AME-aware clang-21(核心步骤)
工程所有裸机目标都用一个支持 AME 自定义指令的 LLVM/Clang fork。 发行版
apt install clang装出来的 clang 不认识 AME 助记符(msettile*/mlae8/mqma.b.mm等),无法编译models/qwen3/ame_mix_offline_i8.c这类用真助记符的固件。 ⚠️ 注意发行版clang-21与本 fork 同名易混,迁移时尤其要确认走的是 fork——详见 §7.2。https://gitlink.org.cn/michaelcjl/llvm-project_riscv.gitad6e3420706aaf5ab557d3023b5a3fac6e2954d7(clang version 21.0.0git)~/opt/llvm-project_riscv/build/bin/clang-21、clang、clang++、lld/ld.lld(-fuse-ld=lld)、llvm-ar、llvm-objcopy、llvm-objdump、llvm-nm有两条路,优先选 A(自建一次要几个小时)。
路 A:拷贝预编译产物(推荐)
如果还能访问已装好的旧机器,直接把整棵 build 目录搬过去最省事。
最小拷贝集(若想省空间,~4.3 GB → 可再
strip减小):只需build/bin/(上面列出的那几个二进制;clang按相对路径找资源目录)build/lib/clang/21/(clang 自带头文件,必须一起拷,仅 ~8 MB;缺了会报找不到stddef.h等)路 B:从源码编译
(
clang-resource-headers确保生成build/lib/clang/21/include。编译需 ~30+ GB 磁盘、较长时间。)让构建找到它
Makefile 顶部用
CUSTOM_LLVM ?= $(HOME)/opt/llvm-project_riscv/build/bin和CLANG ?= .../clang-21引用。装到默认路径就无需改任何东西。装别处则:4. Python 模型转换环境
权重量化 / 生成 blob 的脚本(
tools/quantization/*.py、tools/tokenizer/*.py、tools/*.sh、tests/*/extract_real_case.py)需要:模型源:转换脚本默认从
/tmp/Qwen3-0.6B(HF safetensors)读取,可用MODEL_SOURCE=/path/to/Qwen3-0.6B覆盖。5. 验证环境
5.1 工具链可见性
5.2 编译器冒烟测试(确认 AME clang 能产出 RV64 目标)
5.3 实际构建各模块
所有裸机 ELF 在链接后会用
readelf校验入口为0x80000000,bin 按 64 字节对齐填充。 各模块的测试分类与运行要求见tests/README.md;文档索引见docs/README.md。6. 目标 ISA / 关键编译开关(排错参考)
-mabi=lp64d -mcmodel=medany-march=rv64imafdc-march=rv64gcv(tools/bench/firmware的部分 L1 固件用rv64gcv_zfh_zvfh_zicsr_zifencei)csrr vlenb的 trap)-mllvm -riscv-v-vector-bits-min=N -mllvm -riscv-v-vector-bits-max=N(tests=256,model/sim/flash=512)lld(-fuse-ld=lld)+-lgcc0x80000000(链接脚本*.ld)7. 环境迁移到 Linux:完整工具链 + 避坑
本节面向把整个工程从 WSL2 搬到一台原生 Linux。照 §7.1 把工具链配齐,§7.2 把 该带的东西带全,§7.3 落地后清理,最后用 §5 验证。
7.1 完整工具链清单(“确保工具链完全”)
~/opt/llvm-project_riscv/build/bin/:clang-21clangclang++ld.lldlldllvm-arllvm-objcopyllvm-objdumpllvm-nm21.0.0git(commitad6e342…),targetriscv64-unknown-unknown-elf~/opt/llvm-project_riscv/build/lib/clang/21/include-lgcc)riscv64-linux-gnu-{gcc,objcopy,readelf}+ sysroot/usr/riscv64-linux-gnuapt(§2)riscv64-unknown-elf-{objcopy,objdump}apt(§2)python3+torch numpy transformers safetensorspip(§4,CPU 版即可)make file awk od dd stat(被elf_to_verilog.sh用)apt(§1)落地后用 §5.1 的命令逐项核对版本。
7.2 两个会“静默踩坑”的 clang 陷阱
/usr/bin/clang-21是发行版 clang,不是 fork。 本机 apt 装的clang-21(Ubuntu 21.1.8,targetx86_64)不认 AME 助记符。后果很隐蔽:kernel/全部用.word 0x…固定编码写 AME,发行版 clang 也能编过;models/qwen3/ame_mix_offline_i8.c用真助记符(msettile*/mlae8/mqma.b.mm),只有 fork 能编。 各 Makefile 默认CLANG := $(if $(wildcard $(CUSTOM_LLVM)/clang-21),…,clang-21): fork 装在默认路径就优先用 fork;fork 没装时会悄悄回退到发行版 clang-21,于是 kernel 编过、model 报错。→ 迁移后第一件事就是确认 fork 在~/opt/llvm-project_riscv/build/bin,或显式make CLANG=/abs/clang-21。7.3 该带什么 / 落地后必做
搬运清单:
git(已重组,干净)。~/opt/llvm-project_riscv/build/,或最小集build/bin+build/lib/clang/21(~4.3 GB;§3 路 A)。models/qwen3/model_data/*.bin(数百 MB ~ GB)已被.gitignore排除,不随 git 走。二选一:① rsync/tar 单独拷过去;② 带上 HF safetensors 源后用tools/generate_w8a8_model.sh+tools/tokenizer/generate_tokenizer_blob.sh重生成。/tmp/Qwen3-0.6B,可MODEL_SOURCE=…覆盖。落地后必做(顺序很重要):
build/**:旧.d依赖文件里写死了/mnt/d/...绝对路径,换机/换路径后 不清会直接报 “No rule to make target”。/mnt/d是 777,搬到 ext4 或经 zip/Windows 盘中转可能丢 exec 位。chmod +x tools/*.sh tools/tokenizer/*.sh tests/flash/*/build.sh,或直接bash <script>。bad interpreter: /usr/bin/env bash^M。sed -i 's/\r$//' <script>(或dos2unix)。/mnt/d):避免 777 权限、*:Zone.Identifier残留、 以及跨文件系统的慢 IO。7.4 其它既有约束
/usr/riscv64-linux-gnu;/opt/riscv(newlib)仅tools/bench/firmware的部分 L1 固件目标需要。tests/sim/*/elf_to_verilog.sh额外依赖riscv64-unknown-elf-objcopy/objdump。kernel/,models/qwen3/经KERNEL_DIR=../../kernel引用,别再往 模型目录里拷内核。kernel/一份;models/qwen3/Makefile经KERNEL_DIR=../../kernel引用, 不要再在模型目录内拷贝内核。附:项目结构(PyTorch / vLLM 式分层)
仓库按「编译内核 ↔ 模型运行时 ↔ 平台抽象 ↔ 工具 ↔ 测试 ↔ 文档」分层,每一类只有单一可信源(不再有三份内核 / 两份模型工作区的复制)。
kernel/libops_kernels(scalar / RVV / AME / mix / w4a8 后端)tools/bench/firmware/platform/encoding.h、linker/*.ldtokenizer/models/qwen3/tools/tests/sim/*tests/flash/*docs/