系列文章目录

(一)从零开始设计RISC-V处理器——指令系统
(二)从零开始设计RISC-V处理器——单周期处理器的设计
(三)从零开始设计RISC-V处理器——单周期处理器的仿真
(四)从零开始设计RISC-V处理器——ALU的优化
(五)从零开始设计RISC-V处理器——五级流水线之数据通路的设计
(六)从零开始设计RISC-V处理器——五级流水线之控制器的设计
(七)从零开始设计RISC-V处理器——五级流水线之数据冒险
(八)从零开始设计RISC-V处理器——五级流水线之控制冒险
(九)从零开始设计RISC-V处理器——五级流水线之分支计算前移
(十)从零开始设计RISC-V处理器——五级流水线之静态预测


本人本科生一枚,之前学习了计算机体系结构(RISC-V版)这本书,对CPU的设计产生了浓厚的兴趣,于是决定在寒假期间,自己动手设计一个基于RISC-V指令集的CPU,顺便写一些文章,记录自己的学习成果,如果文章中有不合理之处,希望大家能批评指正。

(目前单周期处理器代码已更新完成,点击链接直达:基于RISC-V指令集的单周期处理器的设计)

今天是第一天,首先进行指令的选取。

如下表所示,计划实现以下37条指令。

对指令的理解:
1.LUI:将20位立即数的值左移12位(低12位补零)成为一个32位数,将其写回rd。这一指令主要是为了在寄存器中存入比较大的立即数,比如,要想在寄存器X1中存入一个数,可以用addi指令实现(addi x1,x0,100),但这个数的范围有限(-2048~2047),因为addi指令的立即数部分只有12位,能表示最大的无符号数位0xfff(十进制4095),对应的有符号数的范围则为-2048到2047。当立即数超出这个范围,则需要用lui指令。

如lui x1,0xffff ,二进制指令:00001111111111111111000010110111

汇编器执行结果如下:

2.AUIPC:将20位立即数的值左移12位(低12位补零)成为一个32位数,再加上该指令的pc值,再将结果写回rd。这条指令与lui类似,可能是为了实现PC在较大范围内跳转(仅仅是猜测,因为这条指令我还没有接触过)。

如auipc x2,0xfff,二进制指令:00000000111111111111000100010111

当前PC为4,汇编器执行结果如下:

3.JAL:PC+4 的结果送 rd 但不送入PC,然后计算下条指令地
址。转移地址采用相对寻址,基准地址为当前指令地址
(即 PC),偏移量为立即数 imm20 经符扩展后的值的 2 倍。
在实际的汇编程序编写中,跳转的目标往往使用汇编程序中的 label,汇编器会自动根据 label 所在的地址计算出相对的偏移量赋予指令编码。

如:
jal x3,label1 二进制:00000000100000000000000111101111
addi x4,x0,4
label1:
addi x5,x0,5
当前PC为 8,跳过给X4赋值这条指令,并且将12赋给X3寄存器,汇编器执行结果如下:

(补充:仔细分析上面jal指令的二进制会发现,立即数部分是4,4*2=8,PC+8=12,跳过中间的一条指令,这样看起来似乎没什么问题。

但是再看jal的立即数部分,总共是20位,拼接起来是[20:1],这里为什么不是[19:0]?

观察其他的指令格式,如果立即数是12位,那么会表示为[11:0],但JAL,BEQ,BNE,BLT,BGE,BLTU,BGEU却例外。

于是引发了以下思考(个人观点,未经查证,以后深入学习之后再回来补充):假设立即数其实是21位的,即[20:0],只不过始终保持最低位为0,所以在指令中仅仅体现[20:1],这样一来,21位的立即数一定是2的倍数,将立即数乘以2之后,一定是4的倍数,这样就可以保证跳转后的PC一定是4的倍数。所以,对于一个label,假设当前指令为第0行,label为第几行,立即数[20:1]则为多少,这样,立即数最低位补0再乘以2,与当前PC相加,则为正确的跳转地址。

以上的假设便能够合理地解释立即数为[20:1]的原因。

基于以上假设再来看上面jal指令的二进制,发现并不是这样,在以上的假设中,立即数应该是2,但汇编器转化出来的立即数是4,所以要么是我的假设出了问题,要么是汇编器出了问题。

站在汇编器的角度,立即数就是20位的,不存在最低位补个0的说法,所以汇编器在计算立即数的时候,自然而然地就已经将立即数设置成2的倍数了。对于BEQ,BNE,BLT,BGE,BLTU,BGEU指令也是一样。

在这里我更愿意相信我的假设,也许并不一定正确,但这看起来似乎更合理。以上仅为个人拙见,日后深入学习后可能才会发现其中的奥妙。)

4.JALR:jalr 指令使用 12 位立即数(有符号数)作为偏移量,与操作数寄存器 rs1中的值相加,然后将结果的最低有效位置0。jalr指令将其下一条指令的 PC(即当前指令PC+4)的值写入其结果寄存器 rd。

如:
addi x4,x0,4
jalr x8,x4,8 二进制:00000000100000100000111111100111
addi x5,x0,5
addi x6,x0,6
addi x7,x0,7
jalr指令所在的PC为4,4+8=12,则跳向PC=12的指令,同时将8存入X8寄存器。汇编器执行结果如下:

5.BEQ:beq指令只有在操作数寄存器rs1中的数值与操作数寄存器rs2的数值相等时,才会跳转,跳转地址为offset的有符号扩展和最低位补0(即乘以2)的偏移量加上BEQ指令的地址。

如:
addi x1,x0,1
label1:
add x1,x1,x1
addi x2,x0,2
beq x1,x2,label1 二进制:11111110001000001000110011100011

汇编器执行结果如下:

6.BNE:bne指令只有在操作数寄存器rs1中的数值与操作数寄存器rs2的数值不相等时,才会跳转,跳转地址为offset的有符号扩展和最低位补0(即乘以2)的偏移量加上BNE指令的地址。

如:
addi x1,x0,1
label1:
add x1,x1,x1
addi x2,x0,4
bne x1,x2,label1 二进制:11111110001000001001110011100011

汇编器执行结果如下:

7.BTL:blt指令只有在操作数寄存器rs1中的数值小于操作数寄存器rs2的数值时(有符号数),才会跳转,跳转地址为offset的有符号扩展和最低位补0(即乘以2)的偏移量加上BLT指令的地址。

如:
addi x1,x0,-1
label1:
add x1,x1,x1
addi x2,x0,-2
blt x1,x2,label1 二进制:11111110001000001100110011100011

汇编器执行结果如下:

8.BGE:bge指令只有在操作数寄存器rs1中的数值大于或等于操作数寄存器rs2的数值时(有符号数),才会跳转,跳转地址为offset的有符号扩展和最低位补0(即乘以2)的偏移量加上BGE指令的地址。
(注意bge指令的条件是大于等于,而blt的条件是小于)

如:
addi x1,x0,-1
label1:
add x1,x1,x1
addi x2,x0,-2
bge x1,x2,label1 二进制:11111110001000001101110011100011

汇编器执行结果如下:

9.BLTU:bltu指令只有在操作数寄存器rs1中的数值小于操作数寄存器rs2的数值时(无符号数),才会跳转,跳转地址为offset的有符号扩展和最低位补0的偏移量加上BLTU指令的地址。

如:
addi x1,x0,-1
label1:
add x1,x1,x1
addi x2,x0,2
bltu x1,x2,label1 二进制:11111110001000001110110011100011

这里一定是不跳转的,X1的值为-2,但是将其看作是一个无符号的数,就是一个非常大的正数。汇编器执行结果如下:

有符号表示:

无符号表示:

10.BGEU:bgeu指令只有在操作数寄存器rs1中的数值大于或等于操作数寄存器rs2的数值时(无符号数),才会跳转,跳转地址为offset的有符号扩展和最低位补0的偏移量加上BGEU指令的地址。

如:
addi x1,x0,-1
label1:
add x1,x1,x1
addi x2,x0,-2
bgeu x1,x2,label1 二进制:11111110001000001111110011100011

这里一定是跳转一次的,因为刚开始时X1=X2,跳转一次后不会再跳转。
汇编器执行如果如下:

有符号表示:

无符号表示:

11.SB:sb指令 将操作数寄存器rs2中的低8位数据,写回存储器

如:
addi x1,x0,0xf1
addi x2,x0,0xf2
addi x3,x0,0xf3
addi x4,x0,0xf4
sb x1,0,x0
sb x2,1,x0
sb x3,2,x0
sb x4,3,x0

汇编器执行结果如下:

12.SH:sh指令 将操作数寄存器rs2中的低16位数据,写回存储器。

如:
lui x1,0xf0f11
addi x1,x1,0x7ff
sh x1,12,x0

汇编器执行结果如下:

寄存器X1:

数据存储器:

13.SW:sw指令 将操作数寄存器rs2中的32位数据,写回存储器。

如:
lui x1,0xf0f11
addi x1,x1,0x7ff
sw x1,12,x0

汇编器执行结果如下:

14.LB:lb指令从存储器中读回一个8位的数据,进行符号位扩展后写回寄存器rd。

如:
lui x1,0x3ef12
addi x1,x1,0x7ff
sw x1,12,x0
lb x2,12,x0
lb x3,13,x0
lb x4,14,x0
lb x5,15,x0

现在X1寄存器存入一个0x3ef127ff,然后将这32位数存入数据存储器,再从数据存储器中依次读一个字节并进行符号扩展后存入寄存器。汇编器执行结果如下:

X1寄存器:

数据存储器:

符号扩展写入寄存器:

15.LH:lh指令从存储器中读回一个16位的数据,进行符号位扩展后写回寄存器rd。

如:
lui x1,0x3ef12
addi x1,x1,0x7ff
sw x1,12,x0
lh x2,12,x0
lh x3,13,x0
lh x4,14,x0
lh x5,15,x0

汇编器执行结果如下:

数据存储器:

符号扩展写入寄存器:

(思考:这里的X5中的83是什么,调出来数据存储器的数据可以看到,由于这里的地址是非对其访问,读两个字节就需要访问两个存储块。因此,为了提升指令的运行效率,使用load和store指令时,尽量采用边界对齐的地址访问)

16.LW:lw指令从存储器中读回一个32位的数据,写回寄存器rd。

如:
lui x1,0xf0f11
addi x1,x1,0x7ff
sw x1,0,x0
lw x2,0,x0

汇编器的执行结果如下:

数据存储器:

寄存器:

17.LBU:lbu指令从存储器中读回一个8位的数据,进行高位补零扩展后写回
寄存器rd。

如:
lui x1,0x3ef12
addi x1,x1,0x7ff
sw x1,12,x0
lbu x2,12,x0
lbu x3,13,x0
lbu x4,14,x0
lbu x5,15,x0

汇编器的执行结果如下:

数据存储器:

零扩展写入寄存器:

18.LHU:lhu指令从存储器中读回一个16位的数据,进行高位补零扩展后写回寄存器rd。

如:
lui x1,0x3ef12
addi x1,x1,0x7ff
sw x1,12,x0
lhu x2,12,x0
lhu x3,13,x0
lhu x4,14,x0
lhu x5,15,x0

汇编器执行结果如下:

数据存储器:

零扩展写入寄存器:

19.SLT:slt指令将操作数寄存器rs1中的数值与寄存器rs2当作有符号数进行比较。小于则置一,即如果rs1中的值小于rs2中的值,则输出1,否则输出0,结果写回rd。

如:
addi x1,x0,-1
addi x2,x0,1
slt x3,x1,x2

汇编器执行结果如下:

20.SLTU:sltu指令将操作数寄存器rs1中的数值与寄存器rs2当作无符号数进行比。如果rs1中的值小于rs2中的值,则输出1,否则输出0,结果写回rd。

如:
addi x1,x0,-1
addi x2,x0,1
sltu x3,x1,x2

汇编器执行结果如下:

21.SLTI:slti指令将操作数寄存器rs1中的数值与12位立即数当作有符号数进行比较,如果rs1中的值小于立即数的值,则输出1,否则输出0,结果写回rd。

如:
addi x1,x0,-1
slti x2,x1,1

汇编器执行结果如下:

22.SLTIU:sltiu指令将操作数寄存器rs1中的数值与12位立即数当作无符号数进行比较,如果rs1中的值小于立即数的值,则输出1,否则输出0,结果写回rd。

如:
addi x1,x0,-1
sltiu x2,x1,1

汇编器执行结果如下:

23.SLL:逻辑左移(SLL)根据寄存器(rs2)中的移位量对寄存器(rs1)中的值执行逻辑左移,并存储在(rd)寄存器中。

如:
addi x1,x0,4
addi x2,x0,0xf0
sll x3,x2,x1

汇编器执行结果如下:

24.SRL:逻辑右移(SRL)根据寄存器(rs2)中的移位量对寄存器(rs1)中的值执行逻辑右移,左边空出来的位补0,并存储在(rd)寄存器中。

如:
addi x1,x0,4
addi x2,x0,-0xf0
srl x3,x2,x1

汇编器执行结果如下:

25.SRA:算数右移(SRA)根据寄存器(rs2)中的移位量对寄存器(rs1)中的值执行算数右移,左边空出来的位补符号位,并存储在(rd)寄存器中。

如:
addi x1,x0,4
addi x2,x0,-0xf0
sra x3,x2,x1

汇编器执行结果如下:

26.SLLI:slli指令根据5位立即数的移位量对寄存器(rs1)中的值执行逻辑左移(低位补零),并存储在(rd)寄存器中。
27.SRLI:srli指令根据5位立即数的移位量对寄存器(rs1)中的值执行逻辑右移(高位补零),并存储在(rd)寄存器中。
28.SRAI:srai指令根据5位立即数的移位量对寄存器(rs1)中的值执行算数右移(高位补入符号位),并存储在(rd)寄存器中。

如:
addi x2,x0,-0xf0
slli x3,x2,4
srli x4,x2,4
srai x5,x2,4

汇编器执行结果如下:

29.ADD:add指令将寄存器(rs1)与寄存器(rs2)中的值相加,并写回(rd)寄存器中。
30.SUB:sub指令将寄存器(rs1)与寄存器(rs2)中的值相减,并写回(rd)寄存器中。
31.ADDI:addi指令将操作数寄存器rs1的整数值与12位立即数进行加法操作,
结果写回寄存器rd。

如:
addi x1,x0,-1
add x2,x1,x1
sub x3,x2,x1

汇编器执行结果如下:

32.XOR:xor指令在寄存器(rs1)的内容和寄存器(rs2)的内容之间执行逐位逻辑“异或”运算,并存储在(rd)寄存器中。
33.OR:or指令在寄存器(rs1)的内容和寄存器(rs2)的内容之间执行逐位逻辑“或”运算,并存储在(rd)寄存器中。
34.AND:and指令在寄存器(rs1)的内容和寄存器(rs2)的内容之间执行逐位逻辑“与”运算,并存储在(rd)寄存器中。
35.XORI:xori指令将操作数寄存器rs1中的数值与12位立即数进行异或操作,
结果写回rd。
36.ORI:ori指令将操作数寄存器rs1中的数值与12位立即数进行或操作,
结果写回rd。
37.ANDI:andi指令将操作数寄存器rs1中的数值与12位立即数进行与操作,
结果写回rd。

如:
addi x1,x0,0b11001100
addi x2,x0,0b00111111
xor x3,x1,x2
or x4,x1,x2
and x5,x1,x2
xori x6,x1,0b00111111
ori x7,x1,0b00111111
andi x8,x1,0b00111111

汇编器执行结果如下:

以上就是计划实现的37条指令的用法。下一篇文章开始设计处理器。

从零开始设计RISC-V处理器——指令系统相关推荐

  1. 处理器指令编码可重定义的方法_从零开始设计四位栈处理器(2)——结构与指令集...

    从零设计四位栈处理器(2)--结构与指令集 一句话概括: 在Toxic处理器中,万物皆栈. 熟悉汇编语言的同学会了解,一般的汇编语言,会包含以下几个部分: 寄存器 地址 立即数 操作码 在这期文章中, ...

  2. 从零开始设计RISC-V处理器——单周期处理器的设计

    系列文章目录 (一)从零开始设计RISC-V处理器--指令系统 (二)从零开始设计RISC-V处理器--单周期处理器的设计 (三)从零开始设计RISC-V处理器--单周期处理器的仿真 (四)从零开始设 ...

  3. risc系统服务器,精简的高端 解析四大RISC服务器处理器

    也许您很难相信,作为我们今天仍在广泛使用的诸如"扣肉"之类的最新双核乃至是CPU(Center Prosessing Unit中央处理器),都是基于始创在上世纪60年代的CISC指 ...

  4. 这本读者期待的芯片书《手把手教你设计CPU——RISC-V处理器》终于出版!

    点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 ​ ​点击图片购书​ 参与文末话题讨论,每日赠送异步图书 --异步小编 在摩尔定律减缓的今天,一味比拼硬件性能的技术竞赛变得越发 ...

  5. 说明 RISC 和 CISC 指令系统的区别?

    说明 RISC 和 CISC 指令系统的区别? CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法.早期的CPU全部是CISC架 ...

  6. RISC V (RV32+RV64) 架构 整体介绍

    文章目录 riscv 市场 芯片介绍 软件介绍 开发板介绍 PC介绍 riscv 架构 编程模型(指令集/寄存器/ABI/SBI) 运行状态 指令集 寄存器 riscv32和riscv64两者的区别 ...

  7. 如何从零开始设计与开发一款通用模型预测调度系统 | 干货分享

    机器学习模型从训练导出到生成环境部署,这个过程中涉及大量工作,会面临着各种问题与挑战,比如不断丰富的业务场景,系统需要负载种类繁多的神经网络,预测任务不均匀等,然而企业拥有的计算资源(如GPU个数)是 ...

  8. RISC-V学习资料:《手把手教你设计CPU——RISC-V处理器》

    <手把手教你设计CPU--RISC-V处理器> 单击此处样章试读 作者:胡振波 出版社: 人民邮电出版社 ISBN:9787115480521 版次:1 商品编码:12360850 包装: ...

  9. 计组学习笔记2(RISC v版)

    指令集解释 (规定:R[r]表示通用寄存器r的内容,M[addr]表示存储单元addr的内容,SEXT[imm]表示对imm进行符号扩展,ZEXT[imm]表示对imm进行零扩展) 整数运算类 -U型 ...

  10. 四层板设计--Layer V.S. Plane

    四层板设计--Layer V.S. Plane 转载自:http://blog.21ic.com/user1/6960/archives/2011/83332.html 多层板的层设置当初困扰了我好几 ...

最新文章

  1. 注册表故障恢复 必须使用记录或另一备份以恢复包含系统注册表数据的文件。恢复成功...
  2. java日志与业务分离_java日志分开打印
  3. 长江浪漫水城2008年度营业时间和票价
  4. 神州数码最佳实践之一:向项目管理要效益
  5. Scala:集合类型Collection和迭代器
  6. [转]Java程序员们最常犯的10个错误
  7. 怎么用Canoe CAPL发送诊断
  8. 几款经典的免费小软件 -- 白领的左右手
  9. jy在线制图系统免费源码丨一秒生成广告横图海报图
  10. linux改-文件夹名称,linux修改文件夹名字
  11. Linux系统自动更新时间命令的详细说明
  12. 2021-10-19 SAP 创建会计凭证 BTE替代利润中心
  13. 自然语言处理——谷歌BERT模型深度解析
  14. 多台电脑磁盘(文件共享 磁盘共享)局域网共享
  15. 严格反馈系统matlab仿真
  16. 如何规避期货套利交易的陷阱
  17. ical4j发送会议日历时差问题
  18. 数字中国建设整体布局规划解读
  19. C++高斯分布/正态分布源代码
  20. 酷我下载的wma音乐怎么转换为MP3格式

热门文章

  1. html的header背景图片,关于在HTML插入背景图片的问题
  2. 趣味小游戏——井字棋
  3. 我眼中的“阿里月饼事件”
  4. python修改图片尺寸
  5. 手握百万恶意IP,阿里云要跟黑客拼了 | 云栖大会
  6. 面试官问你的缺点是什么,应该如何回答?
  7. 外贸报价后如何跟进客户?winseeing可快速报价展示样品
  8. ps边框制作教程: ps做框子
  9. HDOJ Problem - 1299
  10. 如何修改图像尺寸?教你两招轻松修改图像宽高像素