目录

  • 基于RISC-V的流水线处理器
    • RISC-V指令集
    • RV32I
      • R-Type
      • I-Type
      • J-Type
      • B-Type
      • Load & Store
    • 总结
    • 后记

基于RISC-V的流水线处理器

RISC-V是一个基于精简指令集原则的开源指令集架构。它由加州大学伯克利分校的David Patterson教授领导下的小组完成,至今已成为RISC处理器中一股强劲的新生力量。

至今github上已有多款优秀的基于RISC-V指令集的微处理器项目被发布,如蜂鸟E203RocketChip等,但它们所涉及的知识层级较深,初学者很难迅速上手。而CSDN上也没有找到类似的RISC-V处理器的项目,因此笔者决定从零开始,由基础指令集做起,实现一款基于RISC-V指令集的微处理器。

RISC-V指令集

实现一款处理器,首先也是最重要的就是要确定处理器的指令集架构。

RISC-V指令集可以分为以下几个子集:

  • RV32I:基本整数集,包括整数计算指令,LOAD/STORE,以及控制指令。RV32I拥有32位寻址空间,32个32位寄存器。
  • RV32E:指令与RV32I相同,但是寄存器数量变为16个,用于嵌入式环境。
  • RV64I:整数指令,拥有64位寻址空间,32个64位寄存器。
  • RV128I:整数指令,拥有128位寻址空间,32个128位寄存器。

上述子集是RISC-V的基本指令集。在实际设计中,我们可以根据需要加入如下的扩展指令集:

  • M:标准乘法和除法扩展,增加了乘法和除法的指令,并把结果保存在整数寄存器。
  • A:标准原子指令扩展,增加了原子的读,修改,以及写存储器的指令。
  • F:标准单精度浮点扩展,增加了浮点寄存器,单精度计算指令,以及单精度的LOAD/STORE指令。
  • D:标准双精度浮点扩展,同样增加了浮点寄存器,且增加了双精度计算指令,双精度的LOAD/STORE指令。

上述均为RISC-V基金会认证的扩展指令集,此外还有V/P/T等处于草稿修改阶段的扩展指令集,这里就不再赘述了。

RV32I

在本次设计中,我们要实现的是基于最基本的整数指令集——RV32I的微处理器。就让我们从RV32I的具体指令格式看起。

下图展示了RV32I的基本指令格式。为了简化译码过程,源寄存器(rs1 和 rs2)和目标寄存器(rd)在RISC-V ISA 的所有指令格式中的位置保持一致。立即数被压缩在指令中最左边的可用位,并已经分配好,从而降低硬件复杂度。特别的,对于所有的立即数,指令的 31 位总是符号位,这样可以加速符号扩展电路。

下面我们将对各类型的指令进行具体的解释。

R-Type

R-Type的指令为寄存器-寄存器指令,其格式如下图所示。R-Type指令的特点是2个源操作数和目标操作数对象都是寄存器,在实际执行过程中需要经历寄存器的写回。

Instruction Description Format Comment
ADD ADD rd, rs1, rs2 rd = rs1 + rs2,忽略溢出,保留低32bit
SUB SUB rd, rs1, rs2 rd = rs1 - rs2,忽略溢出,保留低32bit
AND AND rd, rs1, rs2 rd = rs1 & rs2,按位与
OR OR rd, rs1, rs2 rd = rs1 | rs2,按位或
XOR XOR rd, rs1, rs2 rd = rs1 ^ rs2, 按位异或
SLT set less than SLT rd, rs1, rs2 if (rs1 < rs2) rd = 1 else rd = 0
SLTU set less than unsigned SLTU rd, rs1, rs2 if((unsigned)rs1 < (unsigned)rs2) rd = 1 else rd = 0
SLL shift left logical SLL rd, rs1, rs2 rd = rs1 << rs2 [4 : 0],逻辑左移,低位补零,rs2的lower 5 bits作为偏移量
SRL shift right logical SRL rd, rs1, rs2 rd = rs1 >> rs2 [4 : 0],逻辑右移,高位补零,rs2的lower 5 bits作为偏移量
SRA shift rignt arithmetric SRA rd, rs1, rs2 rd = rs1 >> rs2 [4 : 0],算数右移,高位补符号位,rs2的lower 5 bits作为偏移量
NOP no operation NOP 不进行任何操作,相当于ADDI x0, x0, 0

I-Type

I-Type的指令为寄存器-立即数指令,其指令格式如下图所示。R-Type指令中rs2和funct7的位置在I-Type指令中被imm替代,指令仅靠funct3来确定具体指令类型。

imm是一个12位的立即数,在与32位的寄存器进行逻辑运算时必须进行符号位扩展。同样地,I-Type指令也要经历寄存器的写回。

Instruction Description Format Comment
ADDI add immediate ADD rd, rs1, imm rd = rs1 + (sign-extended) imm,忽略溢出,保留低32bit
ANDI and immediate AND rd, rs1, imm rd = rs1 & (sign-extended) imm,按位与
ORI or immediate OR rd, rs1, imm rd = rs1 | (sign-extended) imm,按位或
XORI xor immediate XOR rd, rs1, imm rd = rs1 ^ (sign-extended) imm, 按位异或
SLTI set less than immediate SLT rd, rs1, imm if (rs1 < (sign-extended) imm) rd = 1 else rd = 0
SLTIU set less than unsigned immediate SLTU rd, rs1, imm if((unsigned)rs1 < (unsigned)imm) rd = 1 else rd = 0

对于移位指令,使用立即数的低5位作为偏移量,高7位也作为判断具体指令的操作码,如下图所示。

Instruction Description Format Comment
SLLI shift left logical SLL rd, rs1, imm rd = rs1 << shamt,逻辑左移,低位补零
SRLI shift right logical SRL rd, rs1, imm rd = rs1 >> shamt,逻辑右移,高位补零
SRAI shift rignt arithmetric SRA rd, rs1, imm rd = rs1 >> shamt,算数右移,高位补符号位

J-Type

J-Type指令为无条件跳转指令,主要功能是更改PC的指向地址,让处理器在下一个时钟上升沿在指定的地址中取指令。

JAL的指令格式如下图所示。对于JAL,使用一个20位的有符号立即数作为偏移量,目标地址为pc + offset,并把原pc + 4的地址存入rd。


JALR的指令格式如下图所示。对于JALR,其使用的指令格式是I-Type的指令格式,使用一个12位的有符号立即数作为偏移量,目标地址为pc + offset后把LSB置为0后的结果,并把原pc + 4的地址存入rd。

由此,我们可以写出下表的指令。

Instruction Description Format Comment
JAL jump and link JAL rd, offset pc += (sign-extended) offset, rd = pc + 4
JALR jump and link register JALR rd, rs1, offset pc = [rs + (sign-extended) offset] &~ 1, rd = pc + 4
JR jump register JR rs1 pc = rs1

B-Type

B-Type指令为条件分支指令,仅在满足条件的情况下进行跳转,跳转的偏移量由一个12位的立即数给出。其指令格式如下图所示。

Instruction Description Format Comment
BEQ branch equal BEQ rs1, rs2, offset if (rs1 == rs2) pc += (sign-extended) offset
BNE branch not equal BNE rs1, rs2, offset if (rs1 != rs2) pc += (sign-extended) offset
BLT branch less than BLT rs1, rs2, offset if (rs1 < rs2) pc += (sign-extended) offset
BGE branch bigger than or equal BGE rs1, rs2, offset if (rs1 >= rs2) pc += (sign-extended) offset
BGEU branch bigger than or equal unsigned BGEU rs1, rs2, offset if((unsigned) rs1 >= (unsigned) rs2) pc += (sign-extended) offset

Load & Store

在RV32I中,只有Load & Store指令拥有访问内存的权限。RV32I提供32-byte的寻址空间。

下图展示了Load & Store指令的具体格式。可以注意到,Load指令使用的是I-Type指令的格式,而Store指令使用的是S-Type指令的格式。Load和Store指令的偏移量均由一个12位的立即数给出,但是它们在指令中的位置不同,这是由指令的功能决定的:Load指令需要将内存中的数据转移到寄存器组,因此需要提供目标寄存器;而Store指令需要将寄存器组中的数据转移到内存,因此需要rs1提供内存中将要写入数据的地址,rs2提供需要转移的数据。

Load指令和Store指令的目标地址由rs1 + 符号位扩展的偏移量给出。当指令为LH/LB时,从内存的指定地址中取低16位/低8位,进行符号位扩展后存入rd。而当指令为LW时,直接从内存中取4字节的数据存入rd。

Instruction Description Format Comment
LW load word LW rd, rs1, offset rd = mem[rs1 + (sign-extended) offset] [31:0]
LH load half LH rd, rs1, offset rd = (sign-extended) mem[rs1 + (sign-extend) offset)] [15:0]
LB load byte LB rd, rs1, offset rd = (sign-extended) mem[rs1 + (sign-extend) offset)] [7:0]
LBU load byte unsigned LBU rd, rs1, offset rd = (zero-extended) mem[rs1 + (sign-extend) offset)] [7:0]
SW store word SW rs1, rs2, offset mem[rs1 + (sign-extend) offset)] = rs2

总结

至此,RV32I中基本指令的说明告一段落。

然而,这些说明并不完整——RV32I中还有FENCE指令、Environment Call and Breakpoints指令、HINT指令等尚未提及,这些指令对于本次的设计来说过于复杂,由于本设计完成的处理器仅包括基本的运算及存储功能,因此在这里就将对这些指令的描述略去了。感兴趣的读者可以通过这个链接下载RISC-V的中文手册,或自行下载英文原版手册,对其进行深入阅读。

后记

RISC-V作为一个新兴的RISC架构,在具体的实现中博采众长,真正做到了对其他早期RISC架构的“取其精华,去其糟粕”。例如,RISC-V取消了MIPS-32 ISA中的延迟分支,单纯依靠现代已经相当发达的硬件预测器预测分支结果,实现了架构和具体实现的分离,使得指令集和芯片具体实现的分离成为可能。

芯片商可以采用统一的、免费的开放指令集,但各个厂商可以有各自的内部模块实现,并可以申请专利予以保护。这样既可以构建同一个软件生态系统,又保持了芯片企业之间的独立性。

对于笔者而言,RISC-V和MIPS的区别不仅在于指令中各元素位置的变化,更在于其精心设计的、称得上优雅的具体指令集架构和强大的可扩展性。RV32I中在rs1和rd之间插入一个3 bit的funct,在I-Type的指令中使用12位而非16位的立即数,想必也是从可扩展性的角度考虑得来的结果。

笔者同样作为一个RISC-V的初学者,对于指令集的理解难免有纰漏或错误的地方,欢迎大家对笔者的文章进行批评指正,也欢迎大家与笔者进行交流。

从零开始实现一个基于RISC-V的流水线处理器 (1) :RISC-V指令集架构详解相关推荐

  1. opencv交通标志识别_教你从零开始做一个基于深度学习的交通标志识别系统

    教你从零开始做一个基于深度学习的交通标志识别系统 基于Yolo v3的交通标志识别系统及源码 自动驾驶之--交通标志识别 在本文章你可以学习到如何训练自己采集的数据集,生成模型,并用yolo v3算法 ...

  2. php解析bt,PHP基于闭包思想实现的BT(torrent)文件解析工具实例详解

    PHP基于闭包思想实现的BT(torrent)文件解析工具实例详解 发布于 2017-09-08 20:05:36 | 124 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP( ...

  3. python实现单例模式的几种方式_基于Python中单例模式的几种实现方式及优化详解...

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...

  4. vue划入划出事件_基于vue中对鼠标划过事件的处理方式详解

    鼠标事件进行监听 需求中,在一个table(组件)表中,对于其中一列(该列为图片列),当鼠标划过该列的某个单元格子(图片)时,需要展示出该单元格子对应的遮罩层 翻阅了一些博客,发现好多都提到了mous ...

  5. 气缸标识上vr什么意思_发动机结构代号中L、V、W都是啥意思?图文详解让你不再迷糊...

    发动机结构代号中L.V.W都是啥意思?图文详解让你不再迷糊大家经常能看到L4.V6.W8这样的发动机结构代号,小编今天就用超高清的结构图告诉你这些代号都是什么鬼? 01 直列式(L)发动机直列式发动机 ...

  6. DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析)、使用方法(NLP领域/CV领域)、案例应用之详细攻略

    DL之Transformer:Transformer的简介(优缺点/架构详解,基于Transformer的系列架构对比分析).使用方法(NLP领域/CV领域).案例应用之详细攻略 目录 Transfo ...

  7. mysql简易购物车系统_基于PHP+Mysql简单实现了图书购物车系统的实例详解

    基于PHP+Mysql简单实现了图书购物车系统的实例详解,购物车,这是,页面,简单,图书 基于PHP+Mysql简单实现了图书购物车系统的实例详解 易采站长站,站长之家为您整理了基于PHP+Mysql ...

  8. 自然语言处理NLP星空智能对话机器人系列:第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解

    自然语言处理NLP星空智能对话机器人系列: 第21章:基于Bayesian Theory的MRC文本理解基础经典模型算法详解 1,Bayesian prior在模型训练时候对Weight控制.训练速度 ...

  9. WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例

    最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间的努力,凭着自己对微服务架构的理解,从无到有,基于.NET打造了一个演示微服务架 ...

最新文章

  1. java word根据模板导出_简历不知道如何写起,推荐几个简历模板
  2. Vivado 中IP报严重警告Could not find module的解决办法
  3. Stage4--Python面向对象
  4. [转] C# TextBox、DataGrideView中的数据绑定
  5. Oracle Long类型转换为Clob类型
  6. 并不是每个女生都能穿出这种效果......
  7. 下滑加载更多js_vue.js怎么实现滑动到底部加载更多数据效果?
  8. 功率谱 魏凤英统计程序_单通道语音增强之统计信号模型
  9. express基本原理
  10. Python人脸检测与人脸数据集的生成
  11. 信息系统项目管理十大管理过程整理
  12. AAAI 2022 论文列表
  13. Rust中的所有权和借用的关系图
  14. C/C++常用的文件函数注释格式
  15. ANSYS workbench 根据坐标施加载荷- external data载荷映射
  16. 【linux命令】我常用的Linux命令
  17. 【转】2007最牛X网站收集,有些网站蛮有意思
  18. 京东终身技术顾问李大学:互联网+大数据实战演练
  19. 基于Origin的一种SCI论文中多图合并的简单方法----核心合并图表
  20. Vue的简单入门操作(笔记)与前后端crud

热门文章

  1. 【Python】【教程】Python 教程
  2. python statsmodels安装(亲测可用)
  3. 403服务器显示什么意思,404、503、403、301状态码是什么意思?
  4. Unity3D游戏开发之在uGUI中使用不规则精灵制作按钮
  5. python 求向量模长(一范二范)
  6. MySQL——使用mysqldump命令备份
  7. python 自动登录股票,python2自动读取股票数据示例
  8. 汉诺塔非递归算法分析与实现
  9. c语言打印红色爱心(程序员的浪漫)
  10. ubuntu安装NVIDIA显卡驱动(简单有效)