
我们已经对程序, 指令集, 硬件有简单的认识
ISA作为软件和硬件之间的桥梁, 对计算机系统有重要的影响
本次课内容: RISC-V指令集

真正的RISC-V手册

《The RISC-V Reader》是一本科普读物
《RISC-V开放架构设计之道》
| 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是一条指令, 没法拆开push和mov,
提升指令执行的并行度enter指令#include <stdio.h>
#include <stdint.h>
uint64_t f(uint64_t a, uint64_t b) {
return a + b;
}
int main() {
uint64_t sum = 0;
for (int i = 0; i < 1000000000; i ++) {
sum = f(sum, i);
}
printf("sum = %lld\n", sum);
return 0;
}不使用enter指令
使用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 -> 200beq指令的执行结果为不跳转:
100 -> 101 -> 102j指令: 201 -> 202 -> 102
很巧妙!
nop =
处理器执行时浪费1周期
没办法啊, 一旦写进ISA手册, 就不能删掉 😂
变长指令集可以一直添加
定长指令集, 总有一天会把操作码空间用完, 就看是哪天了

右图: 使用GCC编译的SPEC CPU2006基准测试的代码大小
enter指令 😂
个人观点: 总计43.36%的1字节操作码空间的使用并不合理
动态链接库需要PIC机制的支持
beq, x86的jmpauipc + lw,
x86-64的mov %eax, 4(%rip)UC Berkeley团队在2010年为下一个项目选ISA时的副产品
没有就自己搞一套!
4种基础整数指令集: RV32I, RV64I, RV128I, RV32E
16个寄存器的RV32I变种
标准扩展:
除了压缩指令, 上述指令均采用固定4字节的指令长度
根据需求自由组合:
正解: 需要结合应用场景来看待
事实: IoT领域的需求, 及其软硬件生态, 天然就是碎片化的

x86和MIPS才做选择, RISC-V全都要!
本质: 利用模块化特性, 对不同需求的处理器的实现细节进行隔离
32个通用寄存器(GPR, x0~x31) + PC
x0中读出结果恒为零


rd, rs1,
rs2总是在相同的位置
inst[15:11](R型)或inst[20:16](I型)0x00000000是非法指令0x0000是add %al,(%eax)0x00000000是空指令, 总是能成功执行#include <stdio.h>
#include <sys/mman.h>
__attribute__((aligned(4096))) char a[1024] = {0};
int b[2] = {0};
__attribute__((noinline)) int* f() { return &b[1]; }
int main() {
a[1022] = 0xc3; // ret in x86
mprotect(a, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
printf("Before calling: &a = %p, b[1] = 0x%08x, &b[1] = %p\n", a, b[1], &b[1]);
void (*p)(int *) = (void *)a;
p(f());
printf("I am back: b[1] = 0x%08x\n", b[1]);
return 0;
}0xffffffff是非法指令0xffffffff是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型/jalr的12位立即数组合
U + I型计算, 可得到32位常数U + I型访存/S, 可访问32位地址空间中的内存区域
U为auipc,
可访问当前PC前后各2GB范围中的内存区域U + jalr, 可跳转到32位地址空间中的代码区域
U为auipc,
可跳转到当前PC前后各2GB范围中的代码立即数划分成20 + 12的考量
没有专门的push, pop指令,
可通过以sp作为基址寄存器来实现
不对齐访存(访存地址不被访存数据位宽整除)的处理
lwl + lwr指令组合来实现不对齐访存
RISC-V的方案更灵活: 让执行环境来决定是否支持不对齐访存
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实现jjalr rd, rs1, imm - 返回地址保存到rd,
然后跳转到rs1 + imm
rd = x0和imm = 0实现jrj和jr属于伪指令(pseudo-instruction),
不额外占用操作码
x0的伪指令, 共32条ret = jalr x0, x1, 0nop = addi x0, x0, 0neg rd, rs = sub rd, x0, rssnez rd, rs = sltu rd, x0, rsbeqz rs, offset = beq rs, x0, offsetx0无关的伪指令, 共28条li rd, imm = lui + addimv rd, rs = addi rd, rs, 0not rd, rs = xori rd, rs, -1seqz rd, rs = sltiu rd, rs, 1bgt rs, rt, offset =
blt rt, rs, offset更多伪指令可参考《RISC-V汇编语言编程手册》
0出现的频率很高, 用5比特表示, 节省代码大小
20 + 12 - 牺牲范围中等的常数的表示效率,
换来更丰富的指令编码空间
优秀的指令集设计体现了架构师对整个计算机系统的深入理解
强烈推荐大家阅读《The RISC-V Reader》和RISC-V官方手册
无论RISC-V说自己多有前瞻性, 在历史的车轮下都会变得千疮百孔
fence.i和CSR指令独立成标准扩展