RISC-V处理器的设计与实现(一)—— 基本指令集

news2024/11/25 7:13:19

本人小白一枚,在学习FPGA的过程中偶然刷到了tinyriscv这个开源项目,并且自己对计算机体系结构的知识也很感兴趣,所以想参考这个开源项目做一个基于RISC-V指令集的CPU,下面是tinyriscv这个开源项目的地址,本项目很多思路和设计都参考了tinyriscv开源项目:

从零开始写RISC-V处理器 | liangkangnan的博客

tinyriscv: 一个从零开始写的极简、非常易懂的RISC-V处理器核。

在设计RISC-V处理器之前,我们首先要做的事就是指令集的选取,指令集是一个CPU的基石,要实现CPU 计算和控制功能,就必须定义好一系列与硬件电路相匹配的指令系统。下面是RISC-V官方给出的指令集架构:

因为是第一次做,所以我们选择简单一点的32位基本指令集,也就是RV32I 基本指令集,扩展指令我们到后面再去实现。

RV32I 基本指令集有6种格式,分别是:

目的类型
用于寄存器-寄存器操作R 类型指令
用于短立即数和访存 load 操作I 型指令
用于访存 store 操作S 型指令
用于条件跳转操作SB 类型指令
用于长立即数U 型指令
用于无条件跳转UJ 型指令

RV32I 基本指令集有47条指令,如下图:

本项目打算先实现前37条(黄色高亮部分)基础指令,下面介绍了一下这些指令的用法,这里给大家先推荐一个好用的工具叫Ripes,可以到上面运行riscv汇编指令,并且可以把对应的指令转成二进制机器码,方便我们后面的仿真:

Releases · mortbopet/Ripes · GitHub

下面我们开始指令的介绍。

1. LUI 

语法:lui rd, imm,作用是将立即数imm逻辑左移12位,结果写入rd寄存器(立即数是无符号数)。

我们在ripes运行如下例子来看看结果:

lui x1,1
lui x2,255

如下是运行结果,可以看到寄存器内的数值都是立即数左移12位的结果(16进制): 

2. AUIPC 

语法:auipc rd, imm,作用是将立即数imm逻辑左移12位,然后加上当前指令PC的值,结果写入rd寄存器(立即数是无符号数)。

我们可以通过将立即数的值设置为0来计算PC的值:

auipc x1,0
auipc x2,0
auipc x3,0
auipc x4,4

运行结果如下: 

 

3. JAL(无条件跳转指令)

语法:jal rd, imm,作用是将PC的值加上4,结果写入rd寄存器,rd默认为x1,同时将PC的值设置为当前jal指令地址加上符号位拓展的imm。 

我们可以通过这个指令来跳到指定的指令执行: 

auipc x2,0
auipc x3,0
auipc x4,4
jal x1,-12

 可以看到上述指令会一直循环执行。

4. JALR(无条件跳转指令,寄存器相对寻址)

语法:jalr rd, rs1,imm,作用是将PC的值加上4,结果写入rd寄存器,rd默认为x1,同时将当前PC值设置为寄存器rs1的值加上符号位拓展的imm。

功能和JAL指令一样,不过计算跳转地址的方式不一样,JAL指令跳转地址为PC+imm,而JALR指令跳转地址为寄存器rs1内容+imm: 

addi x1,x0,8
auipc x2,0
auipc x3,0
auipc x4,4
jalr x5,x1,4

因为第4条指令的地址为12,寄存器x1的内容8+立即数4等于12,所以可以看到程序跳转到第四条指令执行:

5. BEQ(分支跳转指令,相等时跳转)

语法:beq rs1, rs2, imm,作用是如果rs1的值等于rs2的值,则将PC设置为符号当前指令beq地址+符号位拓展的立即数imm。 

addi x1,x0,1
addi x2,x0,2
add x1,x1,x1
beq x1,x2,-4

 执行结果如下,可以看到第三条add指令执行了两次:

 

6. BNE(分支跳转指令,不等时跳转)

语法:bne rs1, rs2, imm,作用是如果rs1的值不等于rs2的值,则将PC设置为符号当前指令bne地址+符号位拓展的立即数imm。 

addi x1,x0,1
addi x2,x0,8
add x1,x1,x1
bne x1,x2,-4

 执行结果如下,可以看到第三条add指令执行了三次:

7. BLT(分支跳转指令,小于时跳转)

语法:blt rs1, rs2, imm,作用是如果rs1的值小于rs2的值,则将PC设置为符号当前指令blt地址+符号位拓展的立即数imm。

addi x1,x0,1
addi x2,x0,8
add x1,x1,x1
blt x1,x2,-4

 执行结果如下,可以看到第三条add指令执行了三次:

8. BGE(分支跳转指令,大于等于时跳转)

语法:bge rs1, rs2, imm,作用是如果rs1的值大于或等于rs2的值,则将PC设置为符号当前指令bge地址+符号位拓展的立即数imm。

addi x1,x0,10
addi x2,x0,8
addi x1,x1,-1
bge x1,x2,-4

执行结果如下,可以看到第三条addi指令执行了三次:

9. BLTU(分支跳转指令,无符号数比较,小于时跳转)

语法:bltu rs1, rs2, imm,作用是如果rs1的值小于rs2的值(rs1和rs2为无符号数),则将PC设置为符号当前指令bltu地址+符号位拓展的imm。 

10. BGEU(分支跳转指令,无符号数比较,大于或等于时跳转)

语法:bgeu rs1, rs2, imm,作用是如果rs1的值大于或等于rs2的值(rs1和rs2为无符号数),则将PC设置为符号当前指令bgeu地址+符号位拓展的imm。  

BLTU、BGEU和BLT、BGE的区别在于一个是无符号数比较,一个是有符号数比较。

如下两个示例,执行结果是不一样的:

addi x1,x0,-1
addi x2,x0,8
addi x1,x1,-1
bge x1,x2,-4
addi x1,x0,-1
addi x2,x0,8
addi x1,x1,-1
bgeu x1,x2,-4

11. LB(访存指令,一字节)

语法:lb rd, imm, rs1,作用是从处读rs1加上imm的地址取一个字节的内容,并将该内容经符号位扩展后写入rd寄存器。

addi x1,x0,-1
lb x3,1,x1

执行结果如下,可以看到memory内第一个字节的数据被符号位扩展后送入寄存器x3:

 

12. LH(访存指令,两字节)

语法:lh rd, imm, rs1,作用是从处读rs1加上imm的地址取两个字节的内容,并将该内容经符号位扩展后写入rd寄存器。

addi x1,x0,0
lh x3,4,x1

执行结果如下,可以看到memory内地址4的两个字节数据被符号位拓展后送入x3:

13. LW(访存指令,四字节)

语法:lw rd, imm, rs1,作用是从处读rs1加上imm的地址取四个字节的内容,并将该内容写入rd寄存器(因为四字节位数和寄存器位数相同,所以无需符号位拓展)。

addi x1,x0,0
lw x3,4,x1

 执行结果如下,可以看到memory内地址4的四个字节数据被送入x3:

 

14. LBU(访存指令,一字节,无需符号位拓展)

语法:lbu rd, imm, rs1,作用是从处读rs1加上imm的地址取一个字节的内容,并将该内容经高位补0后写入rd寄存器。

15. LHU(访存指令,两字节,无需符号位拓展)

语法:lhu rd, imm, rs1,作用是从处读rs1加上imm的地址取两个字节的内容,并将该内容经高位补0后写入rd寄存器。

16. SB(访存指令,一字节)

语法:sb rs2, imm, rs1,作用是将rs2的低八位写入rs1加上imm的地址处。

addi x1,x0,-1
sb x1,0,x0

执行结果如下: 

17. SH(访存指令,两字节)

语法:sh rs2, imm, rs1,作用是将rs2的低16位写入rs1加上imm的地址处。 

addi x1,x0,-1
sh x1,0,x0

执行结果如下: 

 

18. SW(访存指令,四字节) 

语法:sw rs2, imm, rs1,作用是将rs2写入rs1加上imm的地址处。 

addi x1,x0,-1
sw x1,0,x0

19. ADDI

语法:addi rd, rs1, imm,作用是将符号扩展的立即数imm的值加上rs1的值,结果写入rd寄存器,忽略算术溢出。

addi x1,x0,-1
addi x2,x1,2

执行结果如下: 

20. SLTI(小于置1)

语法:slti rd, rs1, imm,作用是将符号扩展的立即数imm的值与rs1的值比较(有符号数比较),如果rs1 < imm,则向rd寄存器写1,否则写0。

addi x1,x0,-1
slti x2,x1,2

执行结果如下:  

21. SLTIU(小于置1,无符号比较)

语法:sltiu rd, rs1, imm,作用是将高位补0的立即数imm的值与rs1的值比较(无符号数比较),如果rs1 < imm,则向rd寄存器写1,否则写0。

addi x1,x0,-1
sltiu x2,x1,2

执行结果如下,可以看到x2结果变为了0:  

22. XORI(异或)

语法:xori rd, rs1, imm,作用是将rs1与符号位扩展的imm按位异或,结果写入rd寄存器。

23. ORI

语法:ori rd, rs1, imm,作用是将rs1与符号位扩展的imm按位或,结果写入rd寄存器。

24. ANDI

语法:andi rd, rs1, imm,作用是将rs1与符号位扩展的imm按位与,结果写入rd寄存器。

25. SLLI(逻辑左移)

语法:slli rd, rs1, shamt,作用是将rs1左移shamt位,空出的位补0,结果写入rd寄存器。

26. SRLI(逻辑右移)

语法:srli rd, rs1, shamt,作用是将rs1右移shamt位,空出的位补0,结果写入rd寄存器。

27. SRAI(算术右移)

语法:srai rd, rs1, shamt,作用是将rs1右移shamt位,空出的位用rs1的最高位补充,结果写入rd寄存器。

28. ADD

语法:add rd, rs1, rs2,作用是将rs1寄存器的值加上rs2寄存器的值,然后将结果写入rd寄存器里,忽略算术溢出。

29. SUB

语法:sub rd, rs1, rs2,作用是将rs1寄存器的值减去rs2寄存器的值,然后将结果写入rd寄存器里,忽略算术溢出。

30. SLL

语法:sll rd, rs1, rs2,作用是将rs1左移rs2位(低5位有效),空出的位补0,结果写入rd寄存器。

31. SLT

语法:slt rd, rs1, rs2,作用是将rs1的值与rs2的值比较(有符号数比较),如果rs1的值更小,则向rd寄存器写1,否则写0。

32. SLTU

语法:sltu rd, rs1, rs2,作用是将rs1的值与rs2的值比较(无符号数比较),如果rs1的值更小,则向rd寄存器写1,否则写0。

33. XOR

语法:xor rd, rs1, rs2,作用是将rs1与rs2按位异或,结果写入rd寄存器。

34. SRL

语法:srl rd, rs1, rs2,作用是将rs1右移rs2位(低5位有效),空出的位补0,结果写入rd寄存器。

35. SRA

语法:sra rd, rs1, rs2,作用是将rs1右移rs2位(低5位有效),空出的位用rs1的最高位补充,结果写入rd寄存器。

36. OR

语法:or rd, rs1, rs2,作用是将rs1与rs2按位或,结果写入rd寄存器。

37. AND

语法:and rd, rs1, rs2,作用是将rs1与rs2按位与,结果写入rd寄存器。

以上就是目前所用到的指令了,之后如果添加新的指令会在这里更新。

之后我会还会出新文章更新具体设计部分的内容,大家看了如果觉得有帮助请点个小小的赞吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/684908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专属 Python 开发的完美终端工具

概要 Rich 是一个 Python 库&#xff0c;用于在终端中提供富文本格式和精美的格式。 Rich 是一个非常强大的 Python 库&#xff0c;不仅在终端中提供丰富的文本和漂亮的格式&#xff0c;还可以显示表情符号、表格、进度条、标记&#xff0c;甚至语法突出显示的代码。 Rich 是一…

nginx的优化

目录 一 隐藏版本号在网页上面有nginx的版本号会让别人攻击你的服务器 二 nginx的优化之日志分割 三 nginx的优化之页面压缩 四 连接超时 五 nginx的并发设置 七总结:nginx的优化 一 隐藏版本号在网页上面有nginx的版本号会让别人攻击你的服务器 如图所示 第一种方法是关…

什么是 DOM?DOM树如何生成的?

什么是 DOM 文档对象模型(Document Object Model)。它提供了对文档结构化的描述,并将HTML页面与脚本、程序语言联系起来。 在渲染引擎中&#xff0c;DOM有以下几个层面的作用&#xff1a; 从页面来看&#xff0c;DOM就是生成页面的基本数据结构从JS脚本来看&#xff0c;DOM提…

前端 js 操作 Cookie 详细介绍与案例

1 前言 1.1 详细介绍 名称和值&#xff1a;Cookie由一个名称和对应的值组成。名称是一个字符串&#xff0c;用于标识Cookie&#xff0c;而值则是与名称相关联的数据。域名&#xff1a;每个Cookie都与特定的域名相关联。Cookie只会被发送到与其关联的域名下的请求中。路径&…

MybatisPlus多数据源原理与问题简析

文章目录 1. 使用1.1. 引包1.2 增加配置1.3 使用DS注解 2. 源码2.1 Configuration文件, 加载配置与bean注入2.1.1 配置类 2.2 注册DataSource2.2.1 获取所有的DataSource2.2.1.1 构建DataSource 2.2.2 对数据源分组 2.3 切换数据源2.3.1 DynamicDataSourceContextHolder2.3.2 D…

【LLMs 入门实战 】第一式:Vicuna 模型学习与实战

UC伯克利学者联手CMU、斯坦福等&#xff0c;再次推出一个全新模型70亿/130亿参数的Vicuna&#xff0c;俗称「小羊驼」&#xff0c;小羊驼号称能达到GPT-4的90%性能。 欢迎使用小羊驼&#x1f999;环境搭建权重下载下载 Vicuna Weight下载 LLAMA Weight构建真正的 working weigh…

InceptionNext实战:使用InceptionNext实现图像分类任务(一)

文章目录 摘要安装包安装timm安装 grad-cam 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文翻译&#xff1a;https://wanghao.blog.csdn.net/article/details/131347001?spm1001.2014.3001.5502 官方源码&#xff1a;https://github.com/sail-sg/incept…

Spring Boot详细应用示例:构建一个简单的图书管理系统

文章目录 摘要正文1. 创建Spring Boot项目2. 配置数据库3. 创建实体类4. 创建数据访问层5. 创建业务逻辑层6. 创建控制器层7. 创建前端页面8. 添加身份验证9. 测试运行 小结 摘要 本文将介绍如何使用Spring Boot框架构建一个简单而完整的图书管理系统。通过这个示例&#xff0…

学术小技巧:如何使用easyscholar来提高论文查找效率

0 摘要 easyScholar是一款很好用的科研插件&#xff0c;可以显示会议期刊登记&#xff0c;支持轻量翻译&#xff0c;一键下载等等功能。 1 效果预览 可以直接显示SCI分区&#xff0c;目前中科院SCI分区基础版是免费的&#xff0c;升级版要收费。 目前支持的网站有&#xff1…

【C++】红黑树的插入实现

目录 红黑树的概念红黑树的性质 红黑树节点的定义红黑树的插入操作当p(父节点)在g(祖父节点)左子树grandfather->_left parent当p(父节点)在g(祖父节点)右子树grandfather->_right parent &#x1f4d6; 前言 本篇文章中红黑树的插入用到左单旋和右单旋在AVL树的插入中…

【Python】python进阶篇之面向对象编程

面向对象编程 封装、继承、多态 封装&#xff1a;提高程序安全性 将数据&#xff08;属性&#xff09;和行为&#xff08;方法&#xff09;包装到类中。在方法内部对属性进行操作&#xff0c;在类的外部调用方法。无需关心方法内部的具体实现细节&#xff0c;从而隔离代码复杂…

生成器模式(Builder)

定义 生成器是一种创建型设计模式&#xff0c;使你能够分步骤创建复杂对象。该模式允许你使用相同的创建 代码生成不同类型和形式的对象。 前言 1. 问题 假设有这样一个复杂对象&#xff0c;在对其进行构造时需要对诸多成员变量和嵌套对象进行繁复的初始化工作。这些初始化…

体验Vue神奇的响应式原理:让你的应用更快、更流畅

文章目录 I. 引言介绍Vue.js的响应式原理及其重要性概述本文的内容 II. 数据劫持解释什么是数据劫持Vue如何实现数据劫持示例说明 II. 依赖收集解释什么是依赖收集Vue如何实现依赖收集示例说明 IV. 派发更新解释什么是派发更新Vue如何实现派发更新示例说明 V. 响应式原理运作流…

数据仓库建设指导说明

文章目录 1、概念2、数仓特点3、数仓架构3.1、数据集市3.2、Inmon 架构3.3、Kimball 架构3.3.1、表分区3.3.1.1、事实表3.3.1.2、维度表3.3.1.2.1、维表设计步骤3.3.1.2.2、维度设计的建议3.3.1.2.3、主键设计3.3.1.2.4、缓慢变化维 SCD3.3.1.2.5、维表的整合与拆分3.3.1.2.5.1…

Verdi 之配置及波形打开

目录 写在前边 1.verdi的配置 2. 波形的产生及打开 写在前边 本部分内容主要对Verdi的学习进行总结&#xff0c;大概分三篇文章进行叙述。 1.verdi的配置 1.首先打开.bashrc文件进行环境配置 2.Verdi 配置如下&#xff1a; verdi_HOME: 配置Verdi的home目录&#xff0…

如何制作数字人的模型

首先我们先来了解一下什么是数字人&#xff0c;根据 中国人工智能产业发展联盟发布的《2020年虚拟数字人发展白皮书》指出&#xff0c;数字人意 指具有数字化外形的虚拟人物&#xff0c;除了拥有人的外观、人的行为之外&#xff0c;还拥有人的思想&#xff0c;具有识别外界环境…

【深入浅出RocketMQ原理及实战】「底层原理挖掘系列」透彻剖析贯穿RocketMQ的消息顺序消费和并发消费机制体系的原理分析

透彻剖析贯穿RocketMQ的消息顺序消费和并发消费机制体系的原理分析 DefaultMQPushConsumerImpl拉取消息consumeMessageService的并发消费和顺序消费并发消费顺序消费concurrently 创建 ConsumeRequestconcurrently ConsumeRequest#run 消费主体逻辑消费结束之后清除数据 orderl…

黑马程序员前端 Vue3 小兔鲜电商项目——(十)订单页

文章目录 路由配置和基础数据渲染模板代码配置路由封装接口渲染数据 切换地址-打开弹框交互切换地址-地址切换交互生成订单支付页组件封装订单接口绑定事件 路由配置和基础数据渲染 模板代码 新建 src\views\Checkout\index.vue 文件&#xff0c;添加以下代码&#xff1a; &…

容器管理中关于CGroup的那些事

前言 在一个docker宿主机上可以启动多个容器&#xff0c;默认情况下&#xff0c;docker并没有限制其中运行的容器使用硬件资源。 但如果在实际环境中&#xff0c;容器的负载过高&#xff0c;会占用宿主机大量的资源。这里的资源主要指的CPU&#xff0c;内存&#xff0c;和IO带…

Python Pandas 筛选数据以及字符串替换

str.replace使用示例 假设有一个DataFrame df&#xff0c;其中有一个列名为text&#xff0c;包含一些文本字符串&#xff1a; import pandas as pd data {text: [hello world, foo bar, hello there]} df pd.DataFrame(data) 我们可以使用str.replace方法来替换字符串。比…