从零开始学RISC-V之CSR访问

2023-11-10 14:30
文章标签 访问 从零开始 risc csr

本文主要是介绍从零开始学RISC-V之CSR访问,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • 背景介绍
      • 开始Coding
        • 指令译码
        • 算术运算
        • 测试程序
      • 仿真结果及分析

背景介绍

CSR,即Control and Status Register,控制与状态寄存器,属于CPU自带的一类寄存器(注意这里需要跟前文所述的通用数据寄存器区别开来,后文对这种寄存器称之为数据寄存器,以示区分)。在机器模式(Machine Mode,本项目只支持该模式)下这些存储器主要包括以下六类:

  • 处理器信息相关:例如处理器的厂商信息,架构信息,核心数等等,是一个芯片自身的I固有信息。
  • 中断配置相关:例如中断开关以及中断入口等信息。
  • 中断响应相关:例如中断原因,中断返回地址等信息。
  • 存储器保护相关:设置不同地址空间的存储器的访问属性,例如可读可写可执行等等。
  • 性能统计相关和调试接口相关

CSR的访问与当前指令,或者说程序处于何种模式密切相关,不同模式下所能访问的CSR数量都不同。如果强行访问一个本不应该在该模式下访问的CSR则会触发非法指令的异常。所以在设计CSR访问逻辑时,需要知道该CSR允许在哪(些)种模式下可以访问,而这需要仔细研读RISC-V SPEC相关的部分。除此之外,一条CSR指令并不会比一条ADD指令更复杂。同样可以套用前面总结的设计模板。

开始Coding

与先前所实现的指令类似,实现CSR指令,需要以下几个EXU子模块的协同配合:

  • exu_decode:指令解码模块,负责解析具体的访存指令。
  • exu_regfile:寄存器文件模块,源操作数需要从此模块读出,读存储器的结果需要写回到此模块。
  • exu_alu:指令执行模块,具体指访存地址的生成,以及其他控制信号。
  • exu_wbck:结果写回模块,负责结果写回

基于上述划分标准,以下将详细介绍各个模块的设计细节。

指令译码

首先,我们需要从riscv-spec上找到CSR指令所对应的编码格式,如下图所示:

CSR-编码
官方risc-v spec一共定义了6种CSR指令,其中3个不需要立即数,而另外3个则需要。这些立即数只有5bit,且是0扩展的。所有的CSR都需要将原值写回到数据寄存器。上述六种CSR指令配合特殊的源操作数索引和目的操作数索引(等于0或者不等于0),就可以变化成众多的CSR伪指令。从上图我们可以看出,对于CSR指令:

  • func7部分,即CODE[31:20],视为某个具体CSR的索引值,据此可确定当前CSR到底要访问哪一个寄存器,这其中:
    • CODE[31:30],表征当前CSR寄存器是否可读写。
    • CODE[29:28],表征当前CSR允许访问的最低用户权限(模式)。
    • CODE[27:20],真正的CSR索引值。
  • 可能需要使用源寄存器1,或者立即数。
  • 一定会用到目的寄存器,但是其idx值未知。
  • func3部分,即CODE[14:12],据此判定CSR指令的具体类型。
  • opcode部分,即CODE[6:0],必须为1110011

在译码模块中,添加如下两行,解析具体的CSR指令:
在这里插入图片描述

以及对应的rsen/rsidx/rdidx,以rs1en为例:
在这里插入图片描述

有3条CSR指令需要用到立即数,这个立即数是个0扩展的,原值为5bit的数据。
在这里插入图片描述

算术运算

CSR指令只是将特定的值更新到指定的CSR寄存器中,除此之外不需要进行其他算术运算操作。因此,此处只需要生成特定的dff_ena以及数据信号。由于本项目当前不涉及非法指令异常,因此默认不会有非法的CSR访问操作。

//
// csr related part start.
wire csr_op = i_csrrw_op| i_csrrs_op | i_csrrc_op | i_csrrwi_op| i_csrrsi_op| i_csrrci_op;
// 当前csr指令是否包含写
wire csr_write_en = csr_op;
// 当前csr操作是否包含读
wire csr_read_en =  csr_op;
// 生成写的数据
wire [31:0] csr_write_dat = ({32{i_csrrw_op }} & i_alu_rs1) | ({32{i_csrrs_op }} & i_alu_rs1)| ({32{i_csrrc_op }} & i_alu_rs1)| ({32{i_csrrwi_op}} & i_alu_imm)| ({32{i_csrrsi_op}} & i_alu_imm)| ({32{i_csrrci_op}} & i_alu_imm);
// 生成csr访问地址
wire [11:0] csridx = i_csridx;以下是mstatus实现部分
wire [31:0] mstatus;
wire [31:0] mstatus_nxt;
assign mstatus_nxt = csr_write_dat;
// mstatus的位域定义,来源于spec,此处做简化处理。
//assign mstatus_nxt[0]     = 1'b0; //UIE
//assign mstatus_nxt[1]     = 1'b0; //SIE
//assign mstatus_nxt[2]     = 1'b0; //WPRI
//assign mstatus_nxt[3]     = 1'b0; //MIE
//assign mstatus_nxt[4]     = 1'b0; //UPIE
//assign mstatus_nxt[5]     = 1'b0; //SPIE
//assign mstatus_nxt[6]     = 1'b0; //WPRI
//assign mstatus_nxt[7]     = 1'b0; //MPIE
//assign mstatus_nxt[8]     = 1'b0; //SPP
//assign mstatus_nxt[10:9]  = 2'b0; //WPRI
//assign mstatus_nxt[12:11] = 2'b0; //MPP
//assign mstatus_nxt[14:13] = 2'b0; //FS
//assign mstatus_nxt[16:15] = 2'b0; //XS
//assign mstatus_nxt[17]    = 1'b0; //MPRV
//assign mstatus_nxt[18]    = 1'b0; //SUM
//assign mstatus_nxt[19]    = 1'b0; //MXR
//assign mstatus_nxt[20]    = 1'b0; //TVM
//assign mstatus_nxt[21]    = 1'b0; //TW
//assign mstatus_nxt[22]    = 1'b0; //TSR
//assign mstatus_nxt[30:23] = 8'b0; //WPRI
//assign mstatus_nxt[31]    = 1'b0; //SD// 根据索引值判定当前CSR指令是否是访问mstatus
wire csr_mstatus_sel = (csridx == 12'h300);
// 当前csr指令是否需要更新mstatus
wire mstatus_ena = csr_write_en & csr_mstatus_sel;
xf100_gnrl_dfflr #(32) mstatus_dfflr (clk, rst_n, mstatus_ena, mstatus_nxt, mstatus);
//将status的旧值读出来,备用(可能要写回)
wire [31:0] csr_read_dat = ({32{csr_mstatus_sel}} & mstatus);

如果CSR指令需要写回,则写回的值需要送到写回接口上。

assign o_alu_wdat = i_lw_op ? o_alu_mem_din : csr_op ? csr_read_dat : alu_adder_res;
测试程序

我们从rv32ui-p-add.dump中找到了所需要的测试程序,其反汇编代码如下所示:

在这里插入图片描述

红框中的代码,是根据源数据寄存器a0中的值,更新MSTATUS对应的位域。具体的,如果a0中的第N位是1,则将MSTATUS中对应的第N位设置为1. 此处的效果等价于将a0的值写入MSTATUS

make run

仿真结果及分析

仿真环境不需要更新,直接在之前的基础上运行即可。会看到如下波形:
在这里插入图片描述

上图的解读如下:

  1. PC=0x80000168,识别到一个CSR指令,该指令需要使用源数据寄存器a0,此时上一条指令已经将其更新为8。
  2. CSR指令需要更新MSTATUS寄存器。
  3. 在下一周期,MSTATUS寄存器成功被更新为新值,表明功能达到预期。
  4. 由于目的数据寄存器的索引值是0,因此不需要写回。rf_wen为低。。
下一步,我们将探索仿真一个真实的应用程序,看看?

这篇关于从零开始学RISC-V之CSR访问的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/383277

相关文章

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域,结合了生物学、计算机科学和统计学。随着高通量测序技术的发展,海量的生物数据需要通过编程来进行处理和分析。因此,掌握生信编程技能,成为每一个生物信息学研究者的必备能力。 生信代码入门,旨在帮助初学者从零开始学习生物信息学中的编程基础。通过学习常用

BIRT--商业智能和报表工具,从零开始

1.简介 BIRT (Business Intelligence and Reporting Tools), 是为 Web 应用程序开发的基于 Eclipse 的开源报表系统,特别之处在于它是以 Java 和 JavaEE 为基础。BIRT 有两个主要组件:基于 Eclipse 的报表设计器,以及部署到应用服务器上的运行时组件。 2.下载 官网下载网址:http://download.ec

OpenStack中加固VNC访问安全

OpenStack中加固VNC访问安全 目录 OpenStack中加固VNC访问安全1.问题发现2.流程分析3.潜在后果4.解决方案④配置IPtables⑤VNC添加访问密码 5.参考链接 1.问题发现 很多同学使用noVNC之后都没有退出终端的习惯,往往都是用完了就直接关闭网页窗口。说这样隐患很大,如果内网里面有一些script kiddie随时都能将我们线上的虚拟

RISC-V (十二)系统调用

系统模式:用户态和内核态         当前的代码都是实现在machine模式下。 系统模式的切换         epc寄存器的值存放的是ecall指本身的地址 。 用ecall指令 系统调用的执行流程         mret这条指令会利用status的mpp值恢复到之前的特权级别。  蓝色的线表示涉及到权限切换。  系统调用的传参

Qt: 详细理解delete与deleteLater (避免访问悬空指针导致程序异常终止)

前言 珍爱生命,远离悬空指针。 正文 delete 立即删除:调用 delete 后,对象会立即被销毁,其内存会立即被释放。调用顺序:对象的析构函数会被立即调用,销毁该对象及其子对象。无事件处理:如果在对象销毁过程中还涉及到信号和槽、事件处理等,直接 delete 可能会导致问题,尤其是在对象正在处理事件时。适用场景:适用于在确定对象已经不再被使用的情况下,并且不涉及异步处理或事件循环中的

Windows下安装Elasticsearch,启动报错,解决方法,访问

对于Windows用户,我们推荐使用MSI安装包进行安装。这个安装包使用图形用户界面来引导你进行安装。 首先,从这里https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.1.msi下载Elasticsearch 6.1.1的MSI安装包。 然后双击下载好的安装包文件启动图形化安装程序,在第一个界面,选

RISC-V (十)任务同步和锁

并发与同步 并发:指多个控制流同时执行。         多处理器多任务。一般在多处理器架构下内存是共享的。           单处理器多任务,通过调度器,一会调度这个任务,一会调度下个任务。  共享一个处                                理器一个内存。                 单处理器任务+中断: 同步: 是为了保证在并发执行的环境中各个控制流可