RISC-V 的一点简单入门简介

816 阅读10分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路!

名词尝鲜

  • ISA: (Instruction Set Architechture):指令集架构
  • RISC-V("RISC five")的目标是成为一个通用的指令集架构(ISA)

RISC-V的特异性

  1. 它的不同寻常在于,除了在于它是最近诞生和开源之后。还在于:和几乎所有以往的ISA不同,它是模块化的它的核心是一个名为RV32I的基础ISA,运行一个完整的软件栈。RV32I是固定的,永远不会改变。

了解计算机架构师在设计ISA时的基本原则和必须做出的权衡是有用的,以下列出了七种衡量标准

  • 成本
  • 简洁性(ISA的简洁性还能缩短芯片的设计和验证时间,这也构成了芯片开发的大部分成本)
  • 性能 (处理器的性能和成本都能成为架构师的关注对象)
  • 架构和具体实现的分离
  • 提升空间【后摩尔时代,对性价比进行重大改进的唯一途径是为特定领域添加自定义指令,即意味着如今的ISA必须保留操作码以供未来提升】
  • 程序大小(程序越小,存储所需的芯片面积就越小,更小的程序还能减少指令缓存的未命中问题,从未节省了功耗【因为片外DRAM访问比SRAM访问功耗更多】,也提高了性能。短的代码长度是ISA架构师的目标之一)
  • 易于编程/编译/链接(由于寄存器的数据访问起来要比存储器中的快得多,编译器在寄存器分配这方面做得很好,RISC-V都有32个整形寄存器)
  • 一般每条RISC-V指令最多用一个时钟周期执行(忽略缓存未命中)。

指令集架构

在设计一款处理器之前,我们需要确定他的指令集架构。而指令集架构又包括指令格式、寻址方式、指令类型

RISC-V 的指令集架构

RV32I(RISC-32 ISA简称)

  • 它是RISC-V固定不变的基础整数指令集,是RISC-V的核心内容

1.指令格式:

  • 用于寄存器-寄存器操作的R类型指令
  • 用于短立即数和访问load操作的I型指令
  • 用于访问store操作的S型指令
  • 用于条件跳转操作的B型指令(分支指令)
  • 用于长立即数的U型指令
  • 用于无条件跳转的J型指令(跳转指令)

image.png 这些指令格式规范有序,体现着数学之美,有点如下:

  1. 这种指令格式可提高性能功耗比,指令只有六种格式,并且所有的的指令都是32位长,这简化了指令编码;
  2. RISC-V 指令提供了三个寄存器操作数,而不是像x86-32一样,让源操作数和目的操作数共享一个字段,减少了软件的程序操作【减少了一条move(搬运)指令,来保存目的寄存器的值】
  3. 对于所有指令,要读写的寄存器标识符总是在同一位置,将源寄存器(rs1和rs2)和目标寄存器(rd)固定在同样的位置,以简化指令译码,即意味着在解码之前,就可以先开始访问寄存器。
  4. 立即数被打包,朝着最左边可用位的方向,并且已分配好以减少硬件复杂度。所有立即数的符号位总是在指令的第31位,以加速符号位扩展电路。(这些格式的立即数字段总是符号扩展,符号位总是在指令中最高位。意味着可能成为关键路径的立即数符号扩展,可以在指令解码之前进行。)

2. RV32I 寄存器

RISC-V有32个寄存器,RV32I有31寄存器加上一个值恒为0的x0寄存器。与之相比,ARM-32只有16个寄存器,x86-32甚至只有8个寄存器
有何不同】:为常量0单独分配一个寄存器是RISC-V ISA能如此简单的原因; RSIC-V(包括大多数现代ISA)都有32个整型寄存器。寄存器越多,编译器和汇编程序员工作会更轻松。一般每条RISC-V指令最多用一个时钟周期执行(忽略缓存未命中情况),ARM-32和x86-32都需要多个时钟周期执行的指令。

3. RV32I 整数计算

【区别】:

  • RISC-V 中没有字节或半字节宽度的整数计算操作操作始终是以完整的寄存器宽度内存访问需要的能量比算术运算高几个数量级。因此低宽度的数据访问可以节省大量的能量,但低宽度运算不会。ARM-32有一个不寻常的功能,对于大多数算数逻辑运算中的一个操作数,你可以选择对它进行移位。RV32I提供了单独的移位指令。
  • RV32I也不包含乘法和除法,它们包含在可选在可选的RV32M扩展中。与ARM-32和x86-32不同,即使处理器没有添加乘除法扩展,完整的RISC-V软件栈也可以运行,这可以缩小嵌入式芯片的面积。

4. RV32I的Load 和Store

除了提供32位字(lw,sw)的加载和存储外,RV32I支持加载有符号和无符号字节和半字节(lb,lbu,lh,lhu)和存储字节和半字节(sb,sh)。有符号字节和半字符号扩展为32位再写入目的寄存器。

  • 即使是自然数据类型更窄,低位宽数据也是被扩展后再处理,这使得后续的整数计算指令能正确处理所有的32位。
  • 在文本和无符号整数中常用的无符号字节和半字,在写入目标寄存器之前都被无符号扩展到32位。
  • 加载和存储的支持的唯一寻址模式是符号扩展 12 位立即数到基地址寄存器,这在 x86-32 中被称为位偏移寻址模式。

【有何不同】:

  • RV32I省略了ARM-32和x86-32的复杂寻址模式【ARM-32和MIPS-32要求存储在内存中的数据,要按照数据的自然大小进行边界对齐,但RISC-V没有这个要求】。RISC-V没有特殊的堆栈指令,是将31个寄存器中的某个作为堆栈指针。与MIPS-32不同,RISC-V不支持延迟加载(delayed load),对于更长的流水线,延迟加载带来的收益逐渐消失,因此RISC-V无延迟槽。
  • RISC-V去掉了MIPS-32,Orcale SPARC等指令集中被广为诟病的延迟分支特性等;对于条件分支,它还没有像ARM-32和x86-32那样使用条件码。

补充说明:字节序问题 RISC-V选择了小尾端字节序,因为它在商业上占主导地位:所有x86-32和微软 Windows for ARM 都是低字节优先序。由于字节顺序仅在同时以按字访问和按字节访问同一份数据时才会有影响,字节序只会影响很少一部分的程序员。

5. RV32I 条件分支

RV32I 可以比较两个寄存器并根据比较结果上进行分支跳转。比较可以是:相等(beq),不相等(bne),大于等于(bge),或小于(blt).最后两种比较有符号比较,RV32I也提供相应的无符号版本比较:bgeu和bltu。剩下的两个比较关系(大于和小于等于)可以通过简单地交换两个操作数,即可完成比较。【因为x<y表示y>x且x>=y表示y<=x.】

  • 由于RISC-V指令长度必须是两个字节倍数——关于可选的双字节指令——分支指令的寻址方式是12位的立即数乘以2,符号扩展它,然后将得到值加到PC上作为分支的跳转地址。PC相对地址可用于位置无关的代码,简化了连接器和加载器的工作。 【有何不同】: RISC-V去掉了MIPS-32,Orcale SPARC等指令集中被广为诟病的延迟分支特性等;对于条件分支,它还没有像ARM-32和x86-32那样使用条件码。(条件码的存在使得大多数指令都需要隐式设置一些额外的状态,这使乱序执行的依赖计算复杂化)

6. RV32I 无条件的跳转

【有何不同】:RV32I避开了错综复杂的程序调用指令,例如x86-32的进入和离开指令,或Intel Itanium,Oracle SPARC 和 Cadence Tensilica 中的寄存器窗口。

7. RV32I 杂项

【有何不同】:RISC-V使用内存映射I/O而不是x86-32一样,使用in,ins,insb,insw和out,outsb等指令进行I/O。为支持字符串处理,RISC-V实现了字节存取,而不是像x86-32那样实现了rep,movs,coms,scas,lods等16条特殊的字符串处理指令。

8、 访问指令(较为重要)

  • RISC-V架构的指令数目很简洁,基本指令只有40多条,采用小端格式,采用松散存储器模型。
  • RISC-V架构有6条带条件跳转指令,减少了指令的条数,同时硬件设计上更简单
  • RISC-V对于没有分支预测器的低端CPU,采用静态分支预测机制,对于配有硬件分支预测器的高端CPU,还可以采用高级的动态分支预测机制来保证性能。

9. 定制指令集

RISC-V支持第三方的扩展,用户可以扩展自己的指令子集。如乘除法扩展,浮点运算扩展,原子指令,向量指令等。除此之外,可将CNN集成到硬件中,未来可扩展。几乎可以构建任何一个领域的微处理器,如云计算、存储、并行计算、虚拟化、MCU、应用处理器和DSP处理器等。 总结:RISC-V的特性如下:

  1. 32位字节寻址的地址空间
  2. 所有指令均为32位长
  3. 31个寄存器组,全部为32位宽,寄存器0硬连线为零
  4. 所有的指令操作都是从寄存器到寄存器,访问快(没有寄存器到内存的操作)
  5. 加载/存储字加上有符号和无符号加载/存储字节和半字
  6. 所有算术、逻辑和移位指令都有立即数版本的指令。
  7. 立即数总是符号扩展
  8. 仅提供一种数据寻址模式(寄存器+立即数)和PC相对分支
  9. 无乘法或除法指令
  10. 一个指令,用于将大立即数加载到寄存器的高位,这样加载32位常量到寄存器只需要两条指令。

参考引用:

zhuanlan.zhihu.com/p/264836697