制作一个RISC-V的操作系统十-Trap和Exception(流 mtvec mepc mcause mtval mstatus trap完整流程)

本文详细解释了RISC-V架构中的关键寄存器mtvec、mepc、mcause、mtval在异常处理中的作用,以及trap的tophalf(硬件完成)和bottomhalf(软件完成)过程。讨论了陷阱初始化、权限设置和代码实现,以及向量化模式在中断管理中的应用。
摘要由CSDN通过智能技术生成

控制流:程序控制的执行流
trap分为中断和异常
在这里插入图片描述

mtvec

base:存储trap入口函数的基地址右移两位的即四字节对齐的地址
WARL:可以写任何值,但读出来的值需要是合法才行
在这里插入图片描述

mepc

异常执行完后恢复到原来执行流,
MXLEN:就是CPU处理长度
在这里插入图片描述

mcause

WLRL:读写该部分都必须是合法值
在这里插入图片描述

在这里插入图片描述

mtval

对mcause做的一个补充
在RISC-V架构中,mtval 是 Machine Trap Value 寄存器(机器陷阱值寄存器)的缩写,它是RISC-V架构定义的一部分,用于异常处理机制。

当发生硬件引发的异常,如load访问错误、store访问错误、非法指令等时,mtval 寄存器会被设置为相关的错误值。具体来说:

  • 对于 load 或 AMO (原子操作) 访问错误,mtval 保存的是导致错误的地址。
  • 对于 store 访问错误,mtval 同样保存的是试图进行非法存储操作的地址。
  • 对于指令相关异常(如非法指令),mtval 存储的是触发异常的指令的地址。

程序员或操作系统可以通过检查 mtval 寄存器的内容来确定导致异常的具体原因,这对于调试和异常处理程序非常重要。在RISC-V架构的特权模式下,不同的异常等级(如Machine、Supervisor、User等)会有对应的陷阱值寄存器,例如在Supervisor模式下,类似的寄存器可能是scausesbadaddr
在这里插入图片描述

mstatus

xPIE保持执行trap时前保持当前的xIE,trap执行后再恢复到xIE去
xPP保持陷入当前权限x之前的权限级别值,陷入到M权限之前的权限可以说M U S 所以用两个比特位表示这三种状态。陷入到S之前的权限可以是 U S 所以用一个比特位表示,陷入到U只能是U,那没有必要保存,因为执行完trap后恢复到的和执行trap时一样。
WPRI:读这个寄存器的时候忽略该部分的值,写这个寄存器的时候要保留该部分原来的值(不要变)
在这里插入图片描述

trap 初始化

设置mtvec地址为自己设置的异常处理程序的入口地址

在RISC-V架构中,mtvec 是 Machine Trap Vector Base Address Register(机器陷阱向量基地址寄存器)的缩写。此寄存器在RISC-V处理器中扮演着核心的角色,它负责决定在发生硬件异常或中断时,处理器应跳转到何处执行相应的处理代码。

mtvec 寄存器的结构通常包括两部分:

  1. Base Address(基地址):存储了一个物理地址,当发生异常或中断时,处理器会跳转到这个地址处执行异常处理程序的第一条指令。

  2. Mode(模式):

    • Direct Mode(直接模式):在这种模式下,基地址字段直接指向异常处理程序的入口地址。
    • Vectored Mode(向量化模式):这种模式下,基地址字段指向一个固定的向量表,向量表中的每一个条目对应一种特定的异常类型。当异常发生时,处理器根据异常类型从向量表中索引出相应的处理程序地址。

在这里插入图片描述

trap的top half(硬件完成)

  1. MIE复制到MPIE中,MIE清0
  2. 设置mepc,pc设置为mtvec(异常:异常程序处理完后需要重新执行异常指令 中断:执行完处理中断执行下一条指令)
  3. 设置mcause和mtval
  4. 设置MPP,权限进入M(无论啥trap都会先切换到machine模型)
    . 在这里插入图片描述

trap的bottom half(软件完成)

  1. 切换上下文
  2. 调用对应的处理函数
  3. 恢复上下文
  4. mret
    在这里插入图片描述

从trap返回

  1. 恢复权限
  2. 中断恢复,设置MPP
  3. pc恢复,设置MPIE
    在这里插入图片描述

MPP设置为U和MPIE设置为1的原因

在这里插入图片描述

代码实现

https://github.com/FULLK/risllkos/tree/main/Fullkenerl5

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我会尽力回答你的问题。首先,需要明确一下,SystemC是一种C++库,用于建立硬件仿真模型。 要实现一个二级水线risc-v系统模型,我们需要考虑以下几个方面: 1. 指令集:risc-v指令集是一种开源的指令集架构,我们可以在SystemC中实现这个指令集的模拟器。 2. 水线结构:二级水线中有两个独立的水线阶段,需要在模型中实现。 3. 寄存器:需要实现risc-v的寄存器文件,包括整数寄存器和浮点寄存器。 4. 内存:需要实现risc-v的内存模型,包括指令内存和数据内存。 基于以上考虑,我们可以开始编写二级水线risc-v系统模型。下面是一个简化的代码示例: ```c++ #include <systemc.h> SC_MODULE(RISCV) { // 模拟器需要的成员变量 int32_t pc; // 程序计数器 int32_t regfile[32]; // 寄存器文件 uint8_t memory[65536]; // 内存 // 子模块实例 SC_CTOR(RISCV) { // 初始化成员变量 pc = 0; memset(regfile, 0, sizeof(regfile)); memset(memory, 0, sizeof(memory)); // 实例化子模块 fetch = new Fetch("fetch"); decode = new Decode("decode"); execute = new Execute("execute"); memory_access = new MemoryAccess("memory_access"); write_back = new WriteBack("write_back"); // 连接信号和槽 fetch->out(pc); decode->in(pc); decode->out(ex_pc, rs1_data, rs2_data, rd); execute->in(ex_pc, rs1_data, rs2_data, rd); execute->out(mem_pc, alu_result, rd); memory_access->in(mem_pc, alu_result, rd); memory_access->out(wb_pc, mem_result, rd); write_back->in(wb_pc, mem_result, rd); } // 子模块指针 Fetch *fetch; Decode *decode; Execute *execute; MemoryAccess *memory_access; WriteBack *write_back; // 子模块 SC_MODULE(Fetch) { sc_out<int32_t> out; void run() { while (true) { out.write(pc); wait(); } } SC_CTOR(Fetch) { SC_THREAD(run); } }; SC_MODULE(Decode) { sc_in<int32_t> in; sc_out<int32_t> out_ex_pc; sc_out<int32_t> out_rs1_data; sc_out<int32_t> out_rs2_data; sc_out<int32_t> out_rd; void run() { while (true) { int32_t instruction = memory[in.read()]; int32_t opcode = instruction & 0x7F; int32_t rd = (instruction >> 7) & 0x1F; int32_t rs1 = (instruction >> 15) & 0x1F; int32_t rs2 = (instruction >> 20) & 0x1F; int32_t funct3 = (instruction >> 12) & 0x7; int32_t rs1_data = regfile[rs1]; int32_t rs2_data = regfile[rs2]; int32_t ex_pc = in.read() + 4; out_ex_pc.write(ex_pc); out_rs1_data.write(rs1_data); out_rs2_data.write(rs2_data); out_rd.write(rd); wait(); } } SC_CTOR(Decode) { SC_THREAD(run); } }; SC_MODULE(Execute) { sc_in<int32_t> in_ex_pc; sc_in<int32_t> in_rs1_data; sc_in<int32_t> in_rs2_data; sc_in<int32_t> in_rd; sc_out<int32_t> out_mem_pc; sc_out<int32_t> out_alu_result; sc_out<int32_t> out_rd; void run() { while (true) { int32_t alu_result = 0; out_mem_pc.write(in_ex_pc.read()); out_alu_result.write(alu_result); out_rd.write(in_rd.read()); wait(); } } SC_CTOR(Execute) { SC_THREAD(run); } }; SC_MODULE(MemoryAccess) { sc_in<int32_t> in_mem_pc; sc_in<int32_t> in_alu_result; sc_in<int32_t> in_rd; sc_out<int32_t> out_wb_pc; sc_out<int32_t> out_mem_result; sc_out<int32_t> out_rd; void run() { while (true) { int32_t mem_result = 0; out_wb_pc.write(in_mem_pc.read()); out_mem_result.write(mem_result); out_rd.write(in_rd.read()); wait(); } } SC_CTOR(MemoryAccess) { SC_THREAD(run); } }; SC_MODULE(WriteBack) { sc_in<int32_t> in_wb_pc; sc_in<int32_t> in_mem_result; sc_in<int32_t> in_rd; void run() { while (true) { regfile[in_rd.read()] = in_mem_result.read(); wait(); } } SC_CTOR(WriteBack) { SC_THREAD(run); } }; }; ``` 以上代码只是一个简化版,实际上还需要考虑很多细节。不过,这个模型能够帮助你了解如何使用SystemC实现一个二级水线risc-v系统模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

看星猩的柴狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值