|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
9 {9 ~; b0 ?/ ~; ?; L9 Y" E( b
芯片开放社区(OCC)面向开发者推出RISC-V系列内容,通过多角度、全方位解读RISC-V,系统性梳理总结相关理论知识,构建RISC-V知识图谱,促进开发者对RISC-V生态全貌的了解。本期内容将通过阐述代码密度的决定因素,带大家了解RISC-V架构代码密度的现状,并简单介绍平头哥对RISC-V代码密度的优化成果。
$ c# E& w( V: @; }
+ J) o2 `5 U: C! O对于内存受限的嵌入式芯片(包括mcu和成本要求的AP类芯片)来说,代码密度非常重要。同样功能的程序,如果代码密度过大,就可能导致因ROM空间装载不下而无法使用。所以,在嵌入式领域中,代码密度是最重要的指标之一。那么,代码密度由什么决定?如何提高代码密度呢?RISC-V的代码密度现状又如何?通过本文,我们将为大家一一解答。
' b$ r- Y: `: A1 ?# i0 u
, \2 P5 ~4 O6 h( j/ Z1、代码密度的决定因素0 S) Y7 D9 L8 r8 n9 p
0 c/ a7 g: G: a" D) d
如上面的倒金字塔所示,代码密度主要由指令集、ABI、编译器、Runtime库、程序代码五个部分决定。处在金字塔的越底端,说明该因素越底层,更新的频率越小,但辐射和影响的范围却越广。- O0 i( v' |/ Z* f1 r' g; [3 G
, L& y( u, ^( }2、指令集. T+ ?" ]/ o& c* [
指令集是代码密度最根本的决定性因素,它决定了一个操作在最优的情况下需要编译成多少位宽的编码。" v, N- c/ Z1 [
很多体系结构比如ARM、RISC-V、C-SKY都是16位指令、32位指令混编的,同样的一条指令,如果能够被编译成16位指令,那么它显然比编译成32位指令占用更小的空间;再比如,一个乘累加的操作,如果指令集中存在乘累加指令,那么它只需要一条指令来实现乘累加操作,如果没有则需要至少两条指令来完成相同的操作,假设指令都是32位的,显然一条指令将占用更少的空间。) t4 }$ i2 j$ {1 I! h
由于指令集的编码空间是有限的,所以指令集设计的核心是将哪些指令(包括指令操作数的范围)放到编码空间当中,就像一个商场的店面是有限的,当我们把需求最广的商家引进来时,商场的销量就会达到最高。, y9 z& Q* m Y+ Z4 |+ ?: ~8 O
( `' C t) J6 W/ L3 r r
3、ABI8 @% F6 C! a2 h; O" G& o, O. t' L# c) t
ABI的全称是APPlication Binary InteRFace,是二进制级别的协议,它指导着编译器如何生成代码和二进制程序,同样也指导着用户如何写汇编代码。它主要包含函数调用约定(calling convention)、数据的对齐方式等内容。/ ]# ?2 z* I/ e( `! W. Q- \1 |
其中对代码密度影响最大的就是函数调用约定,它规定了堆栈寄存器、链接寄存器、哪些寄存器需要在函数头尾保存和恢复、哪些寄存器可以作为参数寄存器等,还有一些特殊用途的寄存器。大部分特殊寄存器都是会被高频使用的,配合指令集设计可以降低代码密度;需要保存和恢复的寄存器个数同样也会影响代码密度。7 H, W1 Z6 a, S \6 |8 \2 A
' p3 ?& ?0 i7 k: z" K
4、编译器
. r# e& V2 Y# X( q: s9 M8 [编译器是开发者最直接接触的工具,也是给开发者体感最强的代码密度影响因素。它对代码密度的影响主要体现在两方面:% O0 S& J( z; o' i; c) P. N/ q
① 编译器本身的优化能力,优化能力的强弱是影响编译器产品竞争力的最主要的因素。
# [6 d. S- l3 Q② 编译器的使用方法,比如GCC,除了添加-Os之外,还可以添加-ffunction-sections -fdata-sections -Wl,--gc-sections来删除没有用到的函数。" r3 O7 x$ @, j+ C
" k7 G2 t: N" e K0 }5、Runtime库
0 J4 `" E; k$ T5 X. c/ \* ]Runtime库是指程序运行所需的一些基本的函数库,它们一般都是预先编译好,和编译器一起打包发布,是工具链的一部分。由于这些函数的使用频率较高,一般程序都会用到一部分Runtime库的函数,对这些函数做针对性地优化会有比较好的收益。
( [; {! W _+ O- B$ Z
1 E5 D3 ?" p# d6、程序代码7 |3 Z% o a6 v) |! W2 Q5 H) ~
开发者书写的代码质量也会影响程序的代码密度,虽然编译器能够优化一部分冗余代码,但是并不能保证百分之百的优化,所以开发者也要注意代码的质量。3 w( t9 [6 x& d% o
6 B* k" ^/ n; }+ S
7、RISC-V架构的代码密度现状
; m# K# [/ T; `) o9 T1 i# zRISC-V的代码密度表现一直被人诟病,那么,它的现状真的这么不值一提吗?: j% r) R4 L, s1 ? l( g
首先,RISC-V对代码密度做过一些专门的优化:
0 O; K' t0 y4 J# c2 } e4 \在指令集方面,它通过量化分析的方法测试了SPEC等benchmark,找到高频指令并将它们放到16位指令的编码当中,这就是目前的compress指令集;
+ C7 n- n0 d/ l: K; g: v1 ?% P' R7 _在ABI方面,rv32e通过限制16个寄存器,使代码可以生产更多的16位指令;
1 ]# i2 [9 I# v4 V* S' e在编译器和Runtime中,它支持-msave-restore功能通过库函数调用的方式弥补了由于没有push/pop指令造成的一部分代码密度损失。 |
|