当前位置: 首页 > news >正文

tinyriscv学习记录之五

二十六、clint.v的学习

阅读代码,熟悉的感觉又出现了:反复咀嚼,难以下咽。和阅读div.v的代码时候一样,看代码找不到突破口的话,那么突破口就是不熟悉试商法的原理,我想在clint.v也是一样。如果清楚中断处理的过程,那么clint.v的代码也就能看明白。所以,还是先搞懂中断处理的流程,弄清需要中断需要做哪些事。

二十七、先知道csr寄存器

在RISC-V 这种架构里,中断/异常处理和 CSR 寄存器分不开的。

原因很简单:中断处理至少要解决 4 件事,而这 4 件事恰好都要靠 CSR 来完成:

  • 记录从哪里回来mepc
  • 记录为什么进中断mcause
  • 记录/修改中断使能状态mstatus
  • 决定中断处理程序入口地址mtvec

也就是说,CPU 一旦进入中断,不能只是“跳走”这么简单,还必须:

  1. 保存现场
  2. 记录原因
  3. 关闭或管理中断使能
  4. 跳到统一的处理入口
  5. 处理完再按保存的信息返回

而这些信息的标准存放位置,就是 CSR。

二十八、重要的CSR寄存器

CSR 名称全称功能
mtvecMachine Trap-Vector Base Address保存中断/异常入口地址,进入 trap 后跳到这里
mepcMachine Exception Program Counter保存异常/中断发生时的返回地址,mret时跳回这里
mstatusMachine Status Register控制和保存中断使能状态,进入 trap 时关闭中断,返回时恢复
mcauseMachine Cause Register记录本次异常/中断的原因

二十九、clint.v的中断处理过程就是:

先识别 trap 类型,暂停流水线,分几个时钟周期依次写mepc/mstatus/mcause保存现场,之后再让ex跳到mtvec;执行mret时则恢复mstatus,并让ex跳回mepc

三十、clint.v代码分成4步

1. 先判断“是不是要处理 trap”

clint先根据当前输入判断int_state

  • ecall / ebreak→ 同步异常S_INT_SYNC_ASSERT
  • int_flag_i != INT_NONEglobal_int_en_i == True→ 异步中断S_INT_ASYNC_ASSERT
  • mret→ 中断返回S_INT_MRET
  • 否则 →S_INT_IDLE

也就是说,第一步只是分类:

  • 现在是同步异常
  • 异步中断
  • 还是从中断返回

2. 一旦开始处理,就先暂停流水线

assign hold_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE)) ? `HoldEnable : `HoldDisable;

意思是:

  • 只要检测到中断/异常
  • 或者 CSR 处理流程还没结束
  • 就拉高hold_flag_o

作用:

  • 防止流水线继续往前跑
  • clint腾出几个时钟周期,依次写mepc/mstatus/mcause

所以clint不是一发现中断就马上跳走,而是先冻结现场

3. 进入中断时,分几拍保存现场

这部分由csr_state控制。

情况 A:同步异常或异步中断

csr_state == S_CSR_IDLE时,如果发现要进中断:

第 1 拍:准备异常原因和返回地址

  • 对同步异常:

    • cause设成对应异常码,比如

      • ecall11
      • ebreak3
  • 对异步中断:

    • cause <= 32'h80000004
  • 同时算好inst_addr,也就是将来写进mepc的返回地址

这里为什么要算inst_addr? 因为中断发生时,当前流水线可能正遇到:

  • 普通顺序执行
  • 跳转指令
  • 多周期除法

所以作者要修正“真正该保存哪个 PC”。


第 2 拍:写mepc

状态转到:S_CSR_MEPC

这时输出:

  • we_o = WriteEnable
  • waddr_o = CSR_MEPC
  • data_o = inst_addr

作用:

  • 把将来返回时要继续执行的位置保存到mepc

第 3 拍:写mstatus

状态转到:S_CSR_MSTATUS

这时写mstatus,把全局中断关掉:

data_o <= {csr_mstatus[31:4], 1'b0, csr_mstatus[2:0]};

意思是:

  • 清掉中断使能位
  • 防止处理当前 trap 时又被新的中断打断

第 4 拍:写mcause

状态转到:S_CSR_MCAUSE

这时输出:

  • waddr_o = CSR_MCAUSE
  • data_o = cause

作用:

  • 记录这次 trap 的原因

    • ecall
    • ebreak
    • 还是异步中断

第 5 拍:正式通知 EX 跳转到中断入口

还是在S_CSR_MCAUSE这个阶段,clint会同时发:

  • int_assert_o = INT_ASSERT
  • int_addr_o = csr_mtvec

意思是:

  • 现在现场已经保存完了
  • 可以让ex去把 PC 改到mtvec
  • 开始执行中断/异常处理程序

这点很关键:

不是刚检测到中断就跳,而是先写完关键 CSR,再跳到mtvec

这样 trap 语义才完整。

4. 中断返回 mret 的过程

如果当前指令是 mret,int_state = S_INT_MRET。

这时不会走 mepc -> mstatus -> mcause 这一套进入中断流程, 而是进入:S_CSR_MSTATUS_MRET

返回时做两件事:
第 1 件:恢复 mstatus

data_o <= {csr_mstatus[31:4], csr_mstatus[7], csr_mstatus[2:0]};
意思是:

把中断前保存/对应的使能状态恢复回来
第 2 件:通知 EX 跳回 mepc
同一阶段输出:

int_assert_o = INT_ASSERT
int_addr_o = csr_mepc
意思是:

不再跳去 mtvec
而是跳回之前保存的返回地址 mepc
这样中断处理程序执行完后,CPU 就能回到原程序继续运行。

三十、csr_state的状态推进顺序为什么是这样的?

状态流转是:

S_CSR_IDLE -> S_CSR_MEPC -> S_CSR_MSTATUS -> S_CSR_MCAUSE -> S_CSR_IDLE

对应的 CSR 操作顺序是:

  1. mepc
    保存中断/异常发生时的返回地址
  2. mstatus
    关闭全局中断,防止处理中再被打断
  3. mcause
    记录本次 trap 的原因
  4. 然后才通知跳转到mtvec

也就是说,实际顺序是:

先保存返回地址 -> 再关中断 -> 再记录原因 -> 最后跳去中断入口

三十一、顺序是:先保存返回地址 -> 再关中断 -> 再记录原因 -> 最后跳去中断入口。操作系统中是先关中断,为什么这里不是呢?不能先关中断再保存返回地址,再记录原因?

先关中断这种思路的重点是:

先把门关上,再整理现场

适合这种情况:

  • 硬件能自动抓住异常现场
  • 或设计上最怕 trap 期间再次被打断
  • 或有更底层机制保证返回地址不会丢

然而,

“先保存返回地址,再关中断”之所以在clint.v里更自然,是因为:

  • mepc是最关键的现场,关系到能不能正确返回
  • mepc还需要根据当前流水线状态修正计算,不是现成值
  • 这个实现已经用hold_flag_o先稳住了流程,所以不必把“立刻关中断”放在第一位
  • 因此作者就按先保现场、再改状态、再记原因的顺序来写
http://www.gsyq.cn/news/1608132.html

相关文章:

  • 5个技巧快速上手MediaCrawler:多平台数据采集终极指南
  • 为什么90%的R语言学习者都半途而废?
  • Pikachu靶场文件包含漏洞实战:从原理到渗透测试全解析
  • GPS/北斗模块实战入门:从选型到嵌入式系统集成
  • LeetCode刷题 day25
  • Wfuzz模糊测试工具:Web渗透测试中的瑞士军刀
  • Solidworks二次开发实战:解析选中圆形边的几何中心点
  • 2026AI在线抠图工具整理:免费无水印、商用合规专业平台实操指南
  • 从内核到用户态:Rust 系统编程的安全边界与最佳实践
  • 选长春修锁服务,应参考哪些通用标准和适配条件?
  • 嵌入式高手都在偷偷用的“第10条”:用 #pragma GCC poison 把危险标识符变成毒药,谁碰谁编译失败
  • 如何快速掌握Topit:Mac窗口置顶的终极完整指南
  • 如何快速掌握数据采集:pywencai面向开发者的完整指南
  • 怎样快速配置Nucleus Co-Op:新手必看的完整分屏多人游戏教程
  • 【Springboot毕设全套源码+文档】基于springboot+vue的敬老院管理系统的设计与实现(丰富项目+远程调试+讲解+定制)
  • 多账号矩阵发布视频图文,自动改标题智能识别浏览器工具
  • 深入解析MPC5643L评估板硬件设计:电源、时钟与调试接口实战指南
  • 不用微信和 U 盘,怎样在局域网内快速传大文件
  • 使用AKShare解决金融数据获取难题的完整方案:从数据瓶颈到分析效率提升300%
  • Prompt工程是刀法,Loop工程是阵法——AI Coding两种哲学的实战选择指南
  • cellranger 实战指南:为绵羊单细胞转录组定制专属参考基因组
  • 【Unity陷阱】OnDestroy中生成GameObject:为何会触发‘Some objects were not cleaned up’?
  • 信息安全毕业设计实战指南:网络入侵检测与Web安全选题解析
  • PP-HumanSeg ONNX模型在Windows C++环境下的实时视频流人像分割部署实战
  • SuperPNG终极指南:如何在Photoshop中生成高质量PNG图像
  • Balena Etcher:新手也能轻松掌握的镜像烧录工具,告别命令行操作
  • 【无标题】Linux centos7
  • LLM评估陷阱:为什么BLEU高分不等于用户满意
  • 【Netty源码解读和权威指南】第88篇:Netty DNS解析——自定义域名解析的底层实现
  • CentOS 7 双路径部署 Collabora Online:YUM 直装与 Docker 容器化实践