Design of the RISC-V Instruction Set Architecture笔记(chapter5)
RISC-V Compressed ISA Extension:旨在通过以更密集的格式编码最频繁的指令来减少RISC-V程序的静态代码大小和动态获取流量
MIPS等其他RISC ISA扩展压缩指令集的缺点:基本ISA不是考虑压缩指令而设计的,因此操作码空间没有为压缩指令保留。因此使用压缩指令的方法就是制作新的,不兼容的指令集。这就阻止了和基本ISA的混合。基本指令集不可能用会带来很大的性能影响。
Although the base ISA consists of only 32-bit instructions that must be naturally aligned, the base control-flow instructions have a displacement granularity of 16 bits.
两个主要的设计约束指导了RVC的设计:
- 首先,RVC程序不应该采用比RISC-V对应程序更多的编码指令,因此至少应该具有高性能。用无模式设计可轻松实现此目标,其中基本ISA指令始终可用。 这种设计的一个重要结果是RVC不需要是独立的ISA,因此宝贵的RVC操作码空间不需要花费在必要但相对不频繁的操作上,例如通过系统调用来调用操作系统。 相反,该操作码空间可专用于减小最常见代码序列的大小。
- 每条RVC指令必须是扩展成单条RISC-V基本指令集中的指令。其中一个最重要的原因是简化了RVC处理器的实现和验证:在指令译码期间,RVC指令可以简单的扩展成对应的基本ISA中的指令,因此处理器的后端可以在很大程度上与它们的存在无关。同时,这样可以使得汇编语言程序员和编译器无须了解RVC:代码压缩留给汇编器和链接器即可。当然这种约束却是会阻碍一些重要代码的大小优化
压缩指令集的设计被简化为:压缩比和译码难易程度之间的权衡。在极端情况下,可以将每个可用的RVC操作码映射到最常见的RISC-V的操作码,甚至将每个RVC操作码对应于一个程序字典中的程序。虽然压缩比很高,但是会存在三个主要的缺点:字典查找成本高,译码延迟变大,增加了体系结构状态
RISC-V指令具有四个特点,从而非常适合进行压缩指令的设计
Instructions express great spatial locality of register reference.
Instructions tend to have few unique operands
Immediate operands and offsets tend to be small
Roughly half of immediate operands can be represented in five bits. Statically, branch and jump offsets are often quite large; dynamically, however, almost 90% fit within eight bits, reflecting the dominance of relatively small loops
A small number of unique opcodes dominates
RVC Operand Encoding
- RVC的某些指令可以访问到32个寄存器,但是有些指令只能够访问一小部分最常见的寄存器,这些寄存器成为RVC寄存器
- RVC中有几种格式的指令隐含地访问ABI中具有特殊意义的寄存器:零寄存器,链接寄存器x1,堆栈寄存器
- RVC中某些指令会进行立即数的零扩展,而不像基本指令集中只有符号扩展。如果我们只选择符号扩展的立即数,12%的load和store将是可压缩的。
- 基本ISA中的load/store指令的偏移量很多都是自然对齐的(四字节),如果RVC考虑这一点,将会有44%的store/load可以被压缩
RVC instructions:44条指令,包括RV64C和RV32C
- 定点算术运算最多,占用了19个opcodes。许多算术指令都具有破坏性,只能针对RVC寄存器; 最常用的可以针对任何寄存器。
- load/store指令占用了16个opcodes。RV64C支持读取32/64位定点数和64位浮点数。RV32C 32位浮点加载和存储占用与RV64C 64位整数加载和存储相同的操作码空间。索引方式:基址+偏址,stack-pointer-relative。在所有情况下,displacement都是无符号的,并且可以随着数据类型的不同而进行缩放
- RVC提供了条件跳转指令,直接跳转和寄存器间接跳转指令。
RVC指令译码
- 许多操作码保留供将来使用。指令0x0000被永久保留,以提高错误代码的可能性。除了规定了无操作的指令之外,所有不修改体系结构状态的指令(例如,将寄存器递增为0)都保留用于未来的微体系结构提示。在hints字段无意义的情况下,这些指令将执行无操作,无须额外的硬件成本
RVC Performance Implications
- 通常情况下,RVC的代码应该和RISC-V的代码一样,不会减少性能。但是不对齐的分支目标会减少前端性能,从而产生一个额外的流水线bubble。解决是使用超标量处理器,处理器的前端处理和后端处理分开,从而保证前端的stall对后端的影响很小。同时由于更加精确的分支预测,这个损失会更小
- RVC will improve performance as compared to RISC-V code, by means of reducing cache misses, TLB misses, and page faults. Using RVC instead of RISC-V is more beneficial than increasing
the associativity, and almost as performant as doubling the cache size - 在不降低性能的情况下,减少面积和功耗,带来更高的能效性
RVC中是否包含load/store-multiple指令的考虑
- Thumb/microMIPS 包含了这些指令,主要用于减少被调用者在过程进入和退出时保存寄存器和填充寄存器的代码。
- 这些指令违反了设计约束:每个RVC指令都可以映射到RISC-V指令。同时还要要求编译器知道RVC的存在,增加实现的复杂程度。在超标量的系统中,这些指令可能会降低性能,因为发射过程由于这些指令被阻塞。在具有虚拟存储的计算机中,这些指令可能会在执行过中触发缺页中断,使得精确中断的实现更加复杂。
- when static code size matters more than runtime performance, we can obtain most of the benefit of load-multiple and store-multiple with a purely software technique. 在过程调用开始的寄存器保存代码和调用结束时的寄存器恢复代码基本都是一样的,因此可以将其作为一个过程调用使用。
RVC Security Implications
- One feature of the base RISC-V ISA encoding is that instructions are all four bytes long and must be aligned to a four-byte boundary. Attempts to jump to the middle of an instruction word generate an exception. RVC, by design, lacks this property; indeed, the semantics of jumping into the middle of a four-byte instruction are well defined.
- The dual interpretations of RVC code require either that both paths be proven safe, or that a higher-level constraint prevents the second path from executing.