概述
RISC-V定义了压缩指令扩展(compressed instruction-set extension ),命名为“C”扩展。压缩指令使用16位宽指令替换32位宽指令,从而减少代码量。这个C扩展可运用在RV32、RV64和RV128指令集上,通常使用“RVC”来表示支持该扩展指令集。一个程序通常有50%的指令可以使用RVC指令替代,可以减少25%~30%的代码量。
RISC-V还定义了另外一组压缩指令扩展“Zc*”,扩展现有的C扩展,并新增了一些16位扩展,包括Zca、Zcd、Zcf和Zcb、Zcmp、Zcmt。
RISC-V定义了B扩展(bit-manipulation extension),用于位操作,包括Zba、Zbb和Zbs。B扩展可以减少代码量,提升性能和降低功耗。
CSiBE
CSiBE是用于代码大小测试的benchmark。
环境准备
下载CSiBE,如下:
$ git clone https://github.com/szeged/csibe.git
工具链下载芯来的Nuclei RISC-V Toolchain,这里下载2024.02版本,下载完成解压即可。
编译
CSiBE是采用cmake的方式进行构建的,cmake文件在toolchain-files
目录,我们参考已有的模板编写,命名为gcc-risc-v.cmake
,内容如下:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR RISCV32)
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_C_COMPILER /toolchain/gcc/bin/riscv64-unknown-elf-gcc)
set(CMAKE_CXX_COMPILER /toolchain/gcc/bin/riscv64-unknown-elf-g++)
# 1. 无c和b扩展
set(RISCV_FLAGS "-Os -march=rv32imaf -mabi=ilp32f -D__GLIBC_HAVE_LONG_LONG")
# 2. 基础c扩展
# set(RISCV_FLAGS "-Os -march=rv32imafc -mabi=ilp32f -D__GLIBC_HAVE_LONG_LONG")
# 3. zc和b扩展
# set(RISCV_FLAGS "-Os -march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs -mabi=ilp32f -D__GLIBC_HAVE_LONG_LONG")
# 4. zc、b和芯来Xxlcz扩展
# set(RISCV_FLAGS "-Os -march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxlcz -mabi=ilp32f -D__GLIBC_HAVE_LONG_LONG")
set(CMAKE_C_FLAGS "${RISCV_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${RISCV_FLAGS}" CACHE STRING "" FORCE)
- CMAKE_C_COMPILER和CMAKE_C_COMPILER:配置risc-v的c和c++编译器
- RISCV_FLAGS:指定
-march
参数,这里测试c和b扩展、基础c扩展以及zc和b扩展三种情况
在顶级目录新建一个build
目录,编译如下:
$ ./csibe.py --build-dir=build/ --toolchain gcc-risc-v CSiBE-v2.1.1
- build-dir:指定编译目录
- toolchain:制定工具链文件,即上面的
gcc-risc-v.cmake
编译的结果在build
目录下。
结果分析
CSiBE的测试结果列出所有的程序文件编译大小,这里我们采用所有文件的平均值进行对比。
选项 | 扩展 | 代码量均值 | 对比 |
---|---|---|---|
rv32imaf | 无压缩扩展 | 4370 | 100% |
rv32imafc | 基础c扩展 | 3571 | 82% |
rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs | zc新扩展+b扩展 | 3358 | 76.9% |
rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxlcz | zc新扩展+b扩展+芯来Xxlcz扩展 | 3349 | 76.6% |
可以看出,采用基础c扩展代码量量缩减18%,而采用zc新扩展和b扩展缩减23%。
Embench-IoT
Embench-IoT是嵌入式的性能测试工具,嵌入式系统的特点是:没有OS,最小C库支持,没有输出流。Embench-IoT运行结束后会打印19个测试程序的尺寸大小,类似如下:
Benchmark size
--------- ----
aha-mont64 1,388
crc32 588
cubic 35,018
edn 1,870
huffbench 5,958
matmult-int 1,040
md5sum 5,168
minver 4,332
nbody 8,868
nettle-aes 2,874
nettle-sha256 4,358
nsichneu 16,292
picojpeg 7,774
primecount 624
qrduino 10,044
sglib-combined 6,784
slre 2,646
st 8,930
statemate 3,958
tarfind 4,752
ud 3,336
wikisort 12,576
--------- -----
Geometric mean 4,292
Geometric SD 2.72
Geometric range 10,072.17910752827
All benchmarks sized successfully
环境准备
下载Embench-IoT,如下:
$ git clone https://github.com/embench/embench-iot.git
工具链下载芯来的Nuclei RISC-V Toolchain,这里下载2024.02版本,下载完成解压即可。
另外需要安装python3.6或以后版本,还需要python包pyelftools:
$ pip3 install pyelftools
编译
Embench-IoT使用build_all.py
脚本编译,编译完成后使用benchmark_size.py
脚本查看代码大小,还可以使用benchmark_speed.py
脚本测试速度性能。
无压缩
$ ./build_all.py --clean --arch riscv32 --chip generic --board ri5cyverilator --cc /toolchains/gcc/bin/riscv64-unknown-elf-gcc '--cflags=-c -Os -march=rv32imaf -mabi=ilp32f -ffunction-sections' '--ldflags=-march=rv32imafc -mabi=ilp32f -specs=nosys.specs -specs=nano.specs -Wl,-gc-sections' --user-libs=-lm --dummy-libs=
$ ./benchmark_size.py --absolute
Geometric mean 5,595
Geometric SD 2.60
Geometric range 12,379.939559115413
All benchmarks sized successfully
基础C扩展
$ ./build_all.py --clean --arch riscv32 --chip generic --board ri5cyverilator --cc /toolchains/gcc/bin/riscv64-unknown-elf-gcc '--cflags=-c -Os -march=rv32imafc -mabi=ilp32f -ffunction-sections' '--ldflags=-march=rv32imafc -mabi=ilp32f -specs=nosys.specs -specs=nano.specs -Wl,-gc-sections' --user-libs=-lm --dummy-libs=
$ ./benchmark_size.py --absolute
Geometric mean 4,795
Geometric SD 2.70
Geometric range 11,148.051624219981
All benchmarks sized successfully
Zc和B扩展
$ ./build_all.py --clean --arch riscv32 --chip generic --board ri5cyverilator --cc /toolchains/gcc/bin/riscv64-unknown-elf-gcc '--cflags=-c -Os -march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs -mabi=ilp32f -ffunction-sections' '--ldflags=-march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs -mabi=ilp32f -mabi=ilp32f -specs=nosys.specs -specs=nano.specs -Wl,-gc-sections' --user-libs=-lm --dummy-libs=
$ ./benchmark_size.py --absolute
Geometric mean 4,301
Geometric SD 2.72
Geometric range 10,099.132824302542
All benchmarks sized successfully
Zc、B和Xxlcz扩展
$ ./build_all.py --clean --arch riscv32 --chip generic --board ri5cyverilator --cc /toolchains/gcc/bin/riscv64-unknown-elf-gcc '--cflags=-c -Os -march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxlcz -mabi=ilp32f -ffunction-sections' '--ldflags=-march=rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxlcz -mabi=ilp32f -mabi=ilp32f -specs=nosys.specs -specs=nano.specs -Wl,-gc-sections' --user-libs=-lm --dummy-libs=
$ ./benchmark_size.py --absolute
Geometric mean 4,290
Geometric SD 2.72
Geometric range 10,069.520004018736
All benchmarks sized successfully
结果分析
Embench-IoT的测试结果会打印输出代码量的几何平均值、方差等,这里我们采用几何平均值进行对比。
选项 | 扩展 | 代码量均值 | 对比 |
---|---|---|---|
rv32imaf | 无压缩扩展 | 5595 | 100% |
rv32imafc | 基础c扩展 | 4795 | 86% |
rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs | zc新扩展+b扩展 | 4301 | 76.9% |
rv32imaf_zca_zcb_zcf_zcmp_zcmt_zba_zbb_zbc_zbs_xxlcz | zc新扩展+b扩展+芯来自研的代码缩减Xxlcz扩展 | 4290 | 76.7% |
可以看出,采用基础c扩展代码量量缩减14%,而采用zc新扩展和b扩展缩减33%。
参考
- RISC-V C扩展和Zce扩展Code Size实测
- Embench的介绍和在RISCV32模拟器上的运行
- nuclei sdk documentation