概述
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