我们已经对程序, 指令集, 硬件有简单的认识
本次课内容: RISC-V指令集
一本科普读物
真正的RISC-V手册 ✅
《The RISC-V Reader》
预计发售时间: 2023年11月
ARM Cortex-A5 | RISC-V Rocket | |
---|---|---|
ISA | 32位ARM-v7 | 64位RISC-V |
微结构 | 顺序单发射 | 顺序单发射5级流水 |
Dhrystone性能 | 1.57 DMIPS/MHz | 1.72 DMIPS/MHz |
工艺 | TSMC 40GPLUS | TSMC 40GPLUS |
不带缓存面积 | 0.27 mm2 | 0.14 mm2 |
带16KB缓存面积 | 0.53 mm2 | 0.39 mm2 |
动态功耗 | < 0.08 mW/MHz | 0.034 mW/MHz |
更小的芯片 = 一个晶圆中有更多可用芯片 = 每颗芯片的成本更低
更简洁的ISA = 更小的芯片面积
更简洁的ISA = 更简单的设计和验证 = 更小的人力成本
ldmiaeq SP!, {R4-R7, PC}
指令
另一个反例: x86中的enter
指令, 功能等价于
enter
指令在现代x86处理器上译码成10~20条uop(慢,
占空间)push
+mov
只译码成3~5条uopenter
在一个core2处理器上需要执行8个时钟周期push
+mov
只需要2个时钟周期(有数据依赖关系,
不能同时执行)enter
是一条指令, 没法拆开性能 = 程序执行时间
给定一个程序, 性能优化的方向
inst/prog
- 编译优化, 更好的指令集设计cycle/inst
(CPI) - 增加IPC, 体系结构优化
time/cycle
- 增加主频, 电路关键路径优化,
后端物理设计优化
性能 = 程序执行时间
inst/prog
& cycle/inst
inst/prog
小cycle/inst
大inst/prog
大cycle/inst
小性能 = 程序执行时间
cycle/inst
& time/cycle
cycle/inst
小time/cycle
大cycle/inst
大time/cycle
小原则: 不要让指令集手册的定义约束微结构的实现
反例: MIPS的延迟槽(delay slot)
程序分析领域中的两个定义
延迟槽方案: 修改分支指令的语义, 跳转操作延迟一条指令进行
动态指令流
beq
指令的执行结果为跳转:
100 -> 101 -> 200
beq
指令的执行结果为不跳转:
100 -> 101 -> 102
j
指令: 201 -> 202 -> 102
很巧妙!
nop
=
处理器执行时浪费1周期
没办法啊, 一旦写进ISA手册, 就不能删掉 😂
可以添加指令
可以自由地添加指令
右图: 使用GCC编译的SPEC CPU2006基准测试的代码大小
个人观点: 总计43.36%的1字节操作码空间的使用并不合理
UC Berkeley团队在2010年为下一个项目选ISA时的副产品
没有就自己搞一套!
4种基础整数指令集: RV32I, RV64I, RV128I, RV32E
标准扩展:
除了RVC, 上述指令均采用固定4字节的指令长度
正解: 需要结合应用场景来看待
事实: IoT的软硬件生态本来就是碎片化的
大人才做选择, 小孩全都要!
本质: 模块化特性根据需求对不同处理器的实现细节进行隔离
32个通用寄存器(GPR) + PC
R[0]
中读出结果恒为零
rd
, rs1
,
rs2
总是在相同的位置
0x00000000
和0xffffffff
是非法指令
0x0000
是add %al,(%eax)
sdc3 $31,-1(ra)
0xfff
解释成-1
,
对软件来说比4095
常用得多addi
来实现subi
你很可能会觉得立即数的编码方式匪夷所思
对于生成的立即数, 其中每个比特来源于不同类型指令的不同位置
imm[5]
只来源于inst[25]
或0
(U型),
只需要2选1选择器imm[31]
只来源于inst[31]
, 无需选择器,
可低延迟进行符号扩展U型指令(lui
/auipc
)的20位立即数与I/S/J型指令的12位立即数组合
U + I型计算
, 可得到32位常数U + I型访存/S
, 可访问32位地址空间中的内存区域
U
为auipc
,
可访问当前PC前后各2GB范围中的内存区域U + J
, 可跳转到32位地址空间中的代码区域
U
为auipc
,
可跳转到当前PC前后各2GB范围中的代码没有专门的push
, pop
指令,
可通过以sp
作为基址寄存器来实现
不对齐访存的处理
lwl + lwr
指令组合来实现不对齐访存
lb
的组合来实现MIPS有4条无条件跳转指令
+------+-----+-----+-----+-----+------+
|000000| rs |00000|00000|00000|001000| jr (浪费较多比特)
+------+-----+-----+-----+-----+------+
+------+-----+-----+-----+-----+------+
|000000| rs |00000| rd |00000|001001| jalr (浪费较多比特)
+------+-----+-----+-----+-----+------+
+------+------------------------------+
|000010| offset | j
+------+------------------------------+
+------+------------------------------+
|000011| offset | jal
+------+------------------------------+
RISC-V只需要2条
jal rd, imm
- 返回地址保存到rd
,
然后跳转到PC + imm
rd = x0
实现j
jalr rd, rs1, imm
- 返回地址保存到rd
,
然后跳转到rs1 + imm
rd = x0
和imm = 0
实现jr
优秀的指令集设计体现了架构师对整个计算机系统的深入理解
强烈推荐大家阅读《The RISC-V Reader》和RISC-V官方手册
无论RISC-V说自己多有前瞻性, 在历史的车轮下都会变得千疮百孔
fence.i
和CSR指令独立成标准扩展