\documentclass[12pt]{ctexart}
\usepackage[utf8]{inputenc}
\usepackage[margin=2.5cm]{geometry}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=black,
    citecolor=green,
    urlcolor=blue,
    filecolor=magenta,
    pdftitle={实验二：RISC-V CPU 中断处理机制设计与实现},
    pdfauthor={朱梓涵},
    pdfsubject={RISC-V CPU 设计与实现报告},
    pdfkeywords={RISC-V, CPU, Chisel, 中断, CLINT, CSR, 实验报告}
}
\usepackage{fancyhdr}
\usepackage{enumitem}

% --- 页眉页脚设置 ---
\setlength{\headheight}{15pt}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{\MakeUppercase{实验二：RISC-V CPU 中断处理机制设计与实现}}
\fancyfoot[C]{\thepage}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}

% --- 标题信息 ---
\title{\vspace{-2cm}\textbf{实验二：RISC-V CPU 中断处理机制设计与实现}}
\author{朱梓涵 \\ 学号：24325356}
\date{\today}

% --- 代码高亮风格定义 (Solarized-light) ---
\definecolor{sol-base03}{HTML}{002b36}
\definecolor{sol-base02}{HTML}{073642}
\definecolor{sol-base01}{HTML}{586e75}
\definecolor{sol-base00}{HTML}{657b83}
\definecolor{sol-base0}{HTML}{839496}
\definecolor{sol-base1}{HTML}{93a1a1}
\definecolor{sol-base2}{HTML}{eee8d5}
\definecolor{sol-base3}{HTML}{fdf6e3}
\definecolor{sol-yellow}{HTML}{b58900}
\definecolor{sol-orange}{HTML}{cb4b16}
\definecolor{sol-red}{HTML}{dc322f}
\definecolor{sol-magenta}{HTML}{d33682}
\definecolor{sol-violet}{HTML}{6c71c4}
\definecolor{sol-blue}{HTML}{268bd2}
\definecolor{sol-cyan}{HTML}{2aa198}
\definecolor{sol-green}{HTML}{859900}
\lstdefinestyle{ScalaChiselStyle}{commentstyle=\color{sol-base01}\itshape,keywordstyle=\color{sol-green}\bfseries,stringstyle=\color{sol-cyan},basicstyle=\ttfamily\small,breakatwhitespace=false,breaklines=true,captionpos=b,keepspaces=true,numbers=none,showspaces=false,showstringspaces=false,showtabs=false,tabsize=2,frame=single,rulecolor=\color{black},morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt},extendedchars=false,literate={:}{{\color{sol-base02}:}}1}
\lstdefinestyle{CStyle}{commentstyle=\color{sol-base01}\itshape,keywordstyle=\color{sol-orange}\bfseries,stringstyle=\color{sol-cyan},basicstyle=\ttfamily\small,breakatwhitespace=false,breaklines=true,captionpos=b,keepspaces=true,numbers=none,showspaces=false,showstringspaces=false,showtabs=false,tabsize=2,frame=single,rulecolor=\color{black},extendedchars=false}
\lstset{style=ScalaChiselStyle}

% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}

% --- 文档开始 ---
\begin{document}

\maketitle
\thispagestyle{empty}

\section{实验目的}
本实验旨在为已实现的单周期 RISC-V CPU 增加中断与异常处理功能，深入理解现代处理器如何响应并处理非顺序控制流事件。实验目标包括：
\begin{enumerate}[label=\arabic*.]
    \item 设计并实现控制状态寄存器模块，支持 CSR 指令的读写操作。
    \item 设计并实现核本地中断控制器，使其能够正确处理外部硬件中断和内部软件中断以及中断返回指令。
    \item 理解中断处理流程中 \texttt{mstatus}, \texttt{mepc}, \texttt{mcause}, \texttt{mtvec} 等关键寄存器的作用与变化。
    \item 学习通过 Chisel 测试用例和波形图分析，验证复杂的中断处理逻辑的正确性。
\end{enumerate}

\section{实验环境}
\begin{itemize}
    \item \textbf{操作系统}: Windows 11
    \item \textbf{开发工具}: IntelliJ IDEA
    \item \textbf{构建工具}: SBT
    \item \textbf{仿真与测试}: Verilator, GTKWave, MSYS2
\end{itemize}

\section{模块实现与分析}
本次实验的核心是新增 \texttt{CSR} 和 \texttt{CLINT} 模块，并对 \texttt{Execute} 模块进行扩展以支持 CSR 指令。

\subsection{CSR 模块}
CSR 模块是 CPU 的状态管理中心，负责存储和更新如 \texttt{mstatus}, \texttt{mepc} 等关键状态寄存器。
\begin{itemize}
    \item \textbf{实现要点}：
    \begin{enumerate}
        \item \textbf{独立寄存器与查找表}：将重要的 CSR（如 \texttt{mstatus}）实现为独立的物理寄存器，并通过一个查找表 \texttt{regLUT} 响应读请求，设计清晰且高效。
        \item \textbf{写操作优先级}：写入逻辑必须处理来自 CLINT（中断/异常事件）和 Execute（CSR指令）的并发写请求。设计中，CLINT 的写入拥有最高优先级，确保了中断处理的原子性。
        \item \textbf{数据旁路}：为解决数据冒险，设计了旁路机制。CSR 模块会预计算出下一拍寄存器的值并立即提供给 CLINT，使其能在当前周期就基于最新的 CPU 状态做出正确决策。
    \end{enumerate}
\end{itemize}

\subsubsection{代码实现}
\begin{lstlisting}[caption={CSR 模块的写入优先级与旁路逻辑}, label={lst:csr_logic}]
  val mstatus_next = Mux(io.reg_write_enable_id && 
    io.reg_write_address_id === CSRRegister.MSTATUS, 
    io.reg_write_data_ex, mstatus)
  val mepc_next = Mux(io.reg_write_enable_id && 
    io.reg_write_address_id === CSRRegister.MEPC, 
    io.reg_write_data_ex, mepc)
  
  io.clint_access_bundle.mstatus := mstatus_next
  io.clint_access_bundle.mepc := mepc_next

  when(io.clint_access_bundle.direct_write_enable) {
    mstatus := io.clint_access_bundle.mstatus_write_data
    mepc := io.clint_access_bundle.mepc_write_data
    mcause := io.clint_access_bundle.mcause_write_data
  }.elsewhen(io.reg_write_enable_id) {
    when(io.reg_write_address_id === CSRRegister.MSTATUS) {
      mstatus := io.reg_write_data_ex
    }
  }
\end{lstlisting}

\subsection{CLINT 模块}
CLINT 是中断处理的决策中心，负责监视 CPU 状态，判断中断与异常事件，并生成控制信号来改变 CPU 的执行流和状态。
\begin{itemize}
    \item \textbf{实现要点}：
    \begin{enumerate}
        \item \textbf{事件检测}：通过组合逻辑判断外部中断信号 (\texttt{interrupt\_flag}) 和特定指令（\texttt{mret}, \texttt{ecall}, \texttt{ebreak}）的发生。
        \item \textbf{状态更新计算}：根据发生的事件类型，精确计算 \texttt{mepc}, \texttt{mcause}, \texttt{mstatus} 这三个 CSR 寄存器需要更新成的新值。
        \item \textbf{PC 重定向}：当陷阱 (trap) 发生或 \texttt{mret} 执行时，置位 \texttt{interrupt\_assert} 标志，并提供新的 PC 地址（中断时为 \texttt{mtvec}，返回时为 \texttt{mepc}）。
        \item \textbf{处理优先级}：通过一个 \texttt{when-elsewhen-otherwise} 结构明确了事件处理的优先级：外部硬件中断 > \texttt{mret} > \texttt{ecall} > \texttt{ebreak}。
    \end{enumerate}
\end{itemize}

\subsubsection{代码实现}
\begin{lstlisting}[caption={CLINT 模块处理硬件中断的核心逻辑}, label={lst:clint_logic}]
  val interrupt_enable = io.csr_bundle.mstatus(3)
  val instruction_address = Mux(
    io.jump_flag,
    io.jump_address,
    io.instruction_address + 4.U
  )
  val mstatus = io.csr_bundle.mstatus
  val mie = mstatus(3)
  
  when(io.interrupt_flag =/= InterruptCode.None && interrupt_enable) {
    io.interrupt_assert := true.B
    io.csr_bundle.direct_write_enable := true.B
    io.interrupt_handler_address := io.csr_bundle.mtvec
    io.csr_bundle.mepc_write_data := instruction_address
    io.csr_bundle.mcause_write_data := "h80000007".U
    val new_mpie = mie << 7
    io.csr_bundle.mstatus_write_data := 
      (mstatus & (~(1.U << 3)).asUInt) | new_mpie | (3.U << 11)
  }.elsewhen(io.instruction === InstructionsRet.mret) {
  }
\end{lstlisting}

\section{测试与结果分析}

\subsection{CLINTCSRTest: 硬件中断测试分析}

\subsubsection{测试机制简述}
该测试旨在验证 CPU 对外部硬件中断的响应是否正确。测试用例通过 \texttt{chiseltest} 框架，模拟外部定时器中断信号，并验证 CLINT 模块在不同场景下的中断处理行为。

\textbf{输入信号：}
\begin{itemize}
    \item \texttt{interrupt\_flag}: 外部中断标志，测试中使用值为 \texttt{0x1} 的定时器中断
    \item \texttt{instruction}: 当前执行的指令
    \item \texttt{instruction\_address}: 当前指令地址，表示被中断时的 PC 值
    \item \texttt{jump\_flag}: 指示当前指令是否为跳转指令
    \item \texttt{jump\_address}: 跳转目标地址
    \item \texttt{csr\_bundle.mtvec}: 预设的中断向量表基地址 \texttt{0x1144}
    \item \texttt{csr\_bundle.mstatus}: 初始值 \texttt{0x1888}，MIE=1, MPIE=1，使能中断
\end{itemize}

\textbf{测试的 CLINT 功能：}
\begin{enumerate}
    \item \textbf{中断检测}：检测外部中断信号 (\texttt{interrupt\_flag}) 并判断是否应该响应（检查 \texttt{mstatus.MIE} 位）
    \item \textbf{上下文保存}：将中断发生时的关键状态保存到 CSR 寄存器：
        \begin{itemize}
            \item \texttt{MEPC} $\leftarrow$ PC + 4（非跳转）或跳转目标地址（跳转）
            \item \texttt{MCAUSE} $\leftarrow$ 中断原因编码（\texttt{0x80000007} 表示定时器中断）
            \item \texttt{MSTATUS} $\leftarrow$ 更新状态（MIE $\leftarrow$ 0, MPIE $\leftarrow$ 原 MIE 值）
        \end{itemize}
    \item \textbf{中断跳转}：跳转到中断处理程序（\texttt{mtvec} 中存储的地址 \texttt{0x1144}）
    \item \textbf{中断返回}：执行 \texttt{mret} 指令时恢复现场（PC $\leftarrow$ \texttt{MEPC}，MIE $\leftarrow$ MPIE）
    \item \textbf{跳转与非跳转指令的差异}：验证在跳转指令执行期间发生中断时，\texttt{MEPC} 保存的是跳转目标地址而非 PC + 4
\end{enumerate}

\subsubsection{波形图分析：非跳转指令下的硬件中断处理}

本次测试选用 \texttt{CLINTCSRTest.scala} 中的硬件中断测试（\texttt{handle external interrupt}）。测试通过手动向 CPU 输入一个外部硬件中断标志 \texttt{io\_interrupt\_flag}，并观察 CLINT 是否正确生成中断、是否能在非跳转指令下按照 RISC-V 标准流程完成一次完整的中断处理。

\textbf{测试输入信号及作用：}

\begin{table}[htbp]
\centering
\begin{tabular}{|l|p{8cm}|}
\hline
\textbf{信号} & \textbf{作用} \\
\hline
\texttt{io\_interrupt\_flag = 1} & 触发一次硬件中断（定时器中断） \\
\hline
\texttt{io\_instruction = 0x13} & 当前执行指令（NOP，0x00000013） \\
\hline
\texttt{io\_instruction\_address = 0x1900} & 当前 PC 值 \\
\hline
\texttt{io\_jump\_flag = 0} & 非跳转指令标志 \\
\hline
\texttt{mtvec}、\texttt{mstatus} 初始写入 & 配置中断入口（0x1144）及打开 MIE \\
\hline
\end{tabular}
\caption{硬件中断测试输入信号}
\end{table}

此测试用来验证 CLINT 是否能完成以下功能：
\begin{itemize}
    \item 在非跳转指令下正确响应硬件中断
    \item 正确生成中断断点（\texttt{mepc = PC + 4}）
    \item 正确写入中断原因（\texttt{mcause = 0x80000007}）
    \item 自动清除 MIE 并保存到 MPIE（\texttt{mstatus} 更新）
    \item 正确跳转到中断处理入口（\texttt{mtvec}）
\end{itemize}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=\textwidth]{1.png}
    \caption{硬件中断处理过程波形图 - 非跳转指令场景（8ps $\sim$ 12ps）}
    \label{fig:external_interrupt_waveform}
\end{figure}

\textbf{波形图关键信号说明：}
\begin{itemize}
    \item \texttt{io\_interrupt\_flag[31:0]}: 外部中断标志输入
    \item \texttt{io\_instruction[31:0]}: 当前执行的指令
    \item \texttt{io\_instruction\_address[31:0]}: 当前指令地址（PC）
    \item \texttt{io\_jump\_flag}: 跳转指令标志
    \item \texttt{io\_jump\_address[31:0]}: 跳转目标地址
    \item \texttt{io\_interrupt\_assert}: CLINT 输出的中断响应信号
    \item \texttt{io\_interrupt\_handler\_address[31:0]}: 中断跳转目标地址
    \item \texttt{mtvec[31:0]}: 中断向量表基地址
    \item \texttt{mepc[31:0]}: 中断返回地址
    \item \texttt{mcause[31:0]}: 中断原因寄存器
    \item \texttt{mstatus[31:0]}: 机器状态寄存器
\end{itemize}

如图所示，本测试一次完整的硬件中断处理过程（波形截图区间约为 8ps $\sim$ 12ps）。以下挑选关键信号说明中断发生与处理的整个过程：

\paragraph{(1) 初始化阶段（约 6ps）}

在中断发生前，测试代码已通过 CSR 写指令完成初始化：
\begin{itemize}
    \item \texttt{mtvec = 0x00001144}：中断处理程序入口地址已配置
    \item \texttt{mstatus = 0x00001888}：全局中断已使能
    \begin{itemize}
        \item 二进制表示为 \texttt{...0001\_1000\_1000\_1000}
        \item bit[3] MIE = 1（全局中断使能）
        \item bit[7] MPIE = 1（中断前的 MIE 备份）
    \end{itemize}
\end{itemize}

\paragraph{(2) 中断发生时刻（约 9ps）}

此时 CPU 正在执行一条普通的 NOP 指令，外部中断请求到来：
\begin{itemize}
    \item \texttt{io\_instruction\_address = 0x00001900}：当前 PC
    \item \texttt{io\_instruction = 0x00000013}：NOP 指令
    \item \texttt{io\_jump\_flag = 0}：非跳转指令
    \item \texttt{io\_interrupt\_flag}：从 \texttt{0x00000000} $\rightarrow$ \texttt{0x00000001}（Timer0 中断）
\end{itemize}

\paragraph{(3) 同周期中断响应（约 9ps）}

CLINT 模块检测到 \texttt{interrupt\_flag = 1} 且 \texttt{mstatus.MIE = 1} 后，立即通过组合逻辑响应中断：
\begin{itemize}
    \item \texttt{io\_interrupt\_assert = 1}：触发中断信号
    \item \texttt{io\_interrupt\_handler\_address = 0x00001144}：指示 CPU 跳转到 \texttt{mtvec}
    \item 波形图上可观察到 \texttt{io\_interrupt\_assert} 出现一个脉冲
    \item \texttt{io\_interrupt\_handler\_address} 短暂输出 \texttt{0x1144} 后恢复为 \texttt{0}
\end{itemize}

这表示 CPU 将在下一时钟周期跳转到中断处理程序入口。

\paragraph{(4) CSR 自动更新（约 10ps）}

在时钟上升沿，CSR 模块根据 CLINT 的 \texttt{direct\_write\_enable} 信号自动更新关键寄存器：
\begin{itemize}
    \item \texttt{mepc}：从 \texttt{0x00000000} $\rightarrow$ \texttt{0x00001904}
    \begin{itemize}
        \item 保存的是 PC + 4（\texttt{0x1900 + 4 = 0x1904}）
        \item 这是被中断指令的下一条指令地址，中断返回后将从此处继续执行
    \end{itemize}

    \item \texttt{mcause}：从 \texttt{0x00000000} $\rightarrow$ \texttt{0x80000007}
    \begin{itemize}
        \item bit[31] = 1：表示这是异步硬件中断（而非同步异常）
        \item 低位 = 7：对应 Timer 中断编码
    \end{itemize}

    \item \texttt{mstatus}：从 \texttt{0x00001888} $\rightarrow$ \texttt{0x00001880}
    \begin{itemize}
        \item \texttt{0x1888} = \texttt{...0001\_1000\_1000\_1000}（MIE=1, MPIE=1）
        \item \texttt{0x1880} = \texttt{...0001\_1000\_1000\_0000}（MIE=0, MPIE=1）
        \item MIE 被清 0：关闭全局中断，防止中断嵌套
        \item MPIE 保存了先前的 MIE 值（=1）
    \end{itemize}
\end{itemize}

这些变化完全符合 RISC-V 特权架构手册中定义的中断进入流程。

\paragraph{(5) 中断标志清除（约 12ps 后）}

波形图显示 \texttt{io\_interrupt\_flag} 在约 12ps 后从 \texttt{1} 恢复为 \texttt{0}，这是测试代码模拟中断处理程序清除外设中断标志的行为。

\vspace{1em}
\noindent\textbf{波形分析总结：}

通过以上波形图分析，可以验证 CLINT 模块在非跳转指令场景下正确实现了以下功能：
\begin{itemize}
    \item \texttt{mepc} 正确保存了 PC + 4（\texttt{0x1904}），确保中断返回后从下一条指令继续执行
    \item \texttt{mcause} 正确记录了中断原因（\texttt{0x80000007}），bit[31]=1 标识为异步中断
    \item \texttt{mstatus} 自动完成 MIE 清零和 MPIE 备份，实现中断嵌套保护机制
    \item 从中断检测到 CSR 更新的整个过程由硬件自动完成，无需软件干预
\end{itemize}

测试还包括跳转指令场景的验证：当 \texttt{jump\_flag=1}, \texttt{jump\_address=0x1990} 时发生中断，\texttt{mepc} 应保存跳转目标 \texttt{0x1990} 而非 \texttt{PC+4}，且 \texttt{mcause=0x8000000B}。这确保了 CLINT 能正确处理各种执行场景下的中断。


\subsection{CPUTest: SimpleTrapTest 分析}

\subsubsection{测试目的}

本测试通过执行 \texttt{csrc/simpletest.c} 中的测试程序，验证 CPU 是否能够按照 RISC-V 标准正确处理中断，包括中断触发、保存现场、跳转到中断处理程序、执行处理逻辑以及返回主程序等完整流程。

\subsubsection{测试程序的中断验证机制}

\texttt{simpletest.c} 通过以下过程验证 CPU 的中断处理正确性：

\begin{lstlisting}[style=CStyle, caption={simpletest.c 测试程序源码}]
extern void enable_interrupt();

void trap_handler(void *epc, unsigned int cause){
    *((int*)0x4) = 0x2022;
}

int main(){
    *((int*)0x4) = 0xDEADBEEF;
    enable_interrupt();
    for(;;);
}
\end{lstlisting}

\paragraph{主程序初始化阶段}

程序首先向内存地址 \texttt{0x4} 写入标记值 \texttt{0xDEADBEEF}，用于表示"尚未处理中断"的初始状态。随后调用 \texttt{enable\_interrupt()} 函数配置中断环境：
\begin{itemize}
    \item 将 \texttt{trap\_handler} 的地址写入 \texttt{mtvec} 寄存器
    \item 设置 \texttt{mstatus.MIE = 1}，使能全局中断
\end{itemize}

\paragraph{等待中断触发}

程序进入无限循环 \texttt{for(;;)}，持续等待中断到来。测试框架 \texttt{TestTopModule} 在仿真过程中通过 \texttt{io.interrupt\_flag.poke(0x1)} 向 CPU 注入外部中断请求。

\paragraph{中断处理程序执行}

当中断触发后，CPU 自动跳转到 \texttt{trap\_handler} 函数。该函数执行唯一的操作：将内存地址 \texttt{0x4} 的值修改为 \texttt{0x2022}。这一修改作为中断处理程序成功执行的关键证据。

\paragraph{中断返回与验证}

\texttt{trap\_handler} 执行完毕后，通过 \texttt{mret} 指令返回主程序。测试代码随后读取内存地址 \texttt{0x4} 和相关 CSR 寄存器，验证：
\begin{itemize}
    \item 内存值已从 \texttt{0xDEADBEEF} 变为 \texttt{0x2022}
    \item \texttt{mstatus} 恢复为 \texttt{0x1888}（中断返回后状态）
    \item \texttt{mcause} 保持 \texttt{0x80000007}（记录中断原因）
\end{itemize}

\vspace{0.5em}
\noindent 该验证机制的核心在于：若无限循环能够被中断打断，且内存值发生预期变化，则证明 CPU 确实跳转到了 \texttt{trap\_handler}，中断处理程序正确执行，且 \texttt{mret} 返回机制正常工作。这种通过可观测副作用验证复杂流程的方法，是嵌入式系统测试的典型手段。

\subsubsection{波形图分析}

本实验从波形图中截取了两段关键片段，分别展示中断触发与进入处理、以及中断处理程序修改内存的核心过程。

\paragraph{(1) 中断触发与进入中断处理}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=\textwidth]{2-1.png}
    \caption{SimpleTrapTest 中断触发与进入处理过程波形图（约 2000ps）}
    \label{fig:simpletrap_interrupt}
\end{figure}

如图所示，展示了中断触发至 CPU 进入中断处理程序的完整时序。波形图中的关键信号及其变化如下：

\begin{itemize}
    \item \texttt{io\_interrupt\_flag}: 在约 2000ps 从 \texttt{0} $\rightarrow$ \texttt{0x00000001}，表示外部中断请求到来，随后恢复为 \texttt{0}

    \item \texttt{io\_interrupt\_assert}: 随即产生一个脉冲，说明 CLINT 已检测到中断并产生中断响应信号

    \item \texttt{mepc}: 更新为 \texttt{0x000011C4}，即被中断时刻 PC 的下一条指令地址，保存了中断返回点

    \item \texttt{mcause}: 被写入 \texttt{0x00000007}，记录中断原因为定时器中断（外部中断编码）

    \item \texttt{mstatus}: 从 \texttt{0x00001888} $\rightarrow$ \texttt{0x00001880}，MIE 位（bit[3]）被自动清零，MPIE 位（bit[7]）保存了先前的 MIE 值，符合 RISC-V 中断进入时的标准行为

    \item \texttt{io\_pc\_debug\_read}: 从原执行地址跳转到 \texttt{0x00001050} 附近，该地址为 \texttt{mtvec} 指向的 \texttt{trap\_handler} 函数入口，随后 PC 逐条递增执行中断处理程序指令
\end{itemize}

这一段波形完整展示了中断触发、CSR 自动保存、PC 跳转到 \texttt{trap\_handler} 的全过程。

\paragraph{(2) 中断处理程序修改内存值}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=\textwidth]{2-2.png}
    \caption{SimpleTrapTest 中断处理程序修改内存标志（约 2330ps $\sim$ 2390ps）}
    \label{fig:simpletrap_memory}
\end{figure}

如图所示，展示了验证程序成功执行的最关键时刻。该时段内 CPU 正在执行 \texttt{trap\_handler} 函数体，波形图清晰记录了以下信号变化：

\begin{itemize}
    \item \texttt{io\_bundle\_write\_enable = 1}: CPU 正在执行内存写操作

    \item \texttt{io\_bundle\_address = 0x00000004}: 写入的目标地址正是 \texttt{simpletest.c} 中指定的内存地址 \texttt{0x4}

    \item \texttt{io\_bundle\_write\_data = 0x00002022}: 写入的数据为 \texttt{0x2022}，即 \texttt{trap\_handler} 函数中期望写入的新值

    \item \texttt{mstatus}: 保持 \texttt{0x00001880}，说明此时仍处于中断处理状态，MIE 位为 0

    \item \texttt{mcause}: 保持 \texttt{0x80000007}，中断原因记录未变

    \item \texttt{mepc}: 保持 \texttt{0x000011C4}，中断返回地址保持不变

    \item \texttt{io\_pc\_debug\_read}: 在 \texttt{trap\_handler} 函数内部的指令地址间递增，表明 CPU 正在顺序执行中断处理程序
\end{itemize}

这一瞬间表明 CPU 已成功进入 \texttt{trap\_handler}，并执行了中断处理中最核心的操作——将内存地址 \texttt{0x4} 的值从 \texttt{0xDEADBEEF} 替换为 \texttt{0x2022}。这是 SimpleTrapTest 验证的直接依据，也是实验要求中明确指出的"程序成功执行"的关键信号。

\paragraph{波形分析总结}

通过以上两段波形图分析，可以验证：
\begin{itemize}
    \item CPU 能够在外部中断到来时正确进入中断处理流程
    \item CSR 寄存器（\texttt{mepc}、\texttt{mcause}、\texttt{mstatus}）均按 RISC-V 标准顺序自动更新
    \item PC 正确跳转到 \texttt{mtvec} 指向的 \texttt{trap\_handler} 函数
    \item 中断处理函数成功执行，完成了将内存地址 \texttt{0x4} 的值从 \texttt{0xDEADBEEF} 修改为 \texttt{0x2022} 的操作
    \item 测试代码后续验证了 \texttt{mret} 返回后 \texttt{mstatus} 恢复为 \texttt{0x1888}，中断返回机制正常工作
\end{itemize}

综上所述，本次测试成功验证了 CPU 中断处理机制的完整性与正确性。

\subsection{CPU 与操作系统协作处理定时器中断的机制}

假设本实验设计的 CPU 上运行着一个简单的操作系统（如嵌入式实时操作系统），当定时器中断发生时，硬件（CPU 与 CLINT）和软件（操作系统内核）将协同完成中断处理的全过程。

\subsubsection{操作系统初始化阶段}

操作系统在启动过程中，执行特权指令（如 \texttt{csrrw}）来初始化中断处理机制：
\begin{itemize}
    \item 向 \texttt{mtvec} 寄存器写入中断分发程序 (interrupt dispatcher) 的入口地址
    \item 配置定时器硬件，设置定时周期和中断使能位
    \item 设置 \texttt{mstatus} 寄存器的 MIE 位为 1，使能全局中断
\end{itemize}

\subsubsection{硬件自动响应}

定时器硬件在倒计时结束后，向 CPU 发送中断信号。CPU 的 CLINT 模块检测到该信号且 \texttt{mstatus.MIE = 1} 时，硬件自动执行以下原子操作：
\begin{enumerate}
    \item 将 \texttt{mstatus.MIE} 位的值备份到 \texttt{mstatus.MPIE} 位，然后将 \texttt{mstatus.MIE} 清零，防止中断嵌套
    \item 将当前 PC 的下一条指令地址存入 \texttt{mepc} 寄存器
    \item 根据中断源，在 \texttt{mcause} 寄存器中写入原因码（定时器中断为 \texttt{0x80000007}）
    \item 读取 \texttt{mtvec} 寄存器的值，将 PC 强制设置为该地址，跳转到中断分发程序
\end{enumerate}

\subsubsection{操作系统软件处理}

CPU 跳转到操作系统预设的中断分发程序，该程序执行以下操作：
\begin{enumerate}
    \item \textbf{保存上下文}：将所有通用寄存器（\texttt{x1}$\sim$\texttt{x31}）压栈，保存到内核栈中
    \item \textbf{识别中断源}：读取 \texttt{mcause} 寄存器，判断中断类型
    \item \textbf{分发处理}：根据中断类型调用相应的中断服务例程。对于定时器中断，调用定时器中断服务例程
    \item \textbf{执行中断服务例程}：定时器中断服务例程执行核心任务：
        \begin{itemize}
            \item 更新系统时钟计数器
            \item 检查并唤醒睡眠超时的任务
            \item 执行任务调度算法，决定是否需要任务切换
            \item 重新配置定时器，设置下一次中断
        \end{itemize}
    \item \textbf{恢复上下文}：从内核栈中恢复所有通用寄存器
    \item \textbf{执行 \texttt{mret}}：返回被中断的程序
\end{enumerate}

\subsubsection{硬件恢复}

执行 \texttt{mret} 指令时，CPU 硬件自动执行以下操作：
\begin{enumerate}
    \item 将 \texttt{mstatus.MPIE} 的值恢复到 \texttt{mstatus.MIE}，重新使能全局中断
    \item 将 \texttt{mepc} 中保存的地址加载到 PC，返回被中断的程序
\end{enumerate}

至此，CPU 无缝返回到被中断的用户程序继续执行。

\section{实验结论}
本次实验，我成功地为单周期 CPU 添加了完整的中断处理功能。通过设计 CSR 和 CLINT 模块，我深入学习了 RISC-V 的特权架构和中断处理流程，对 \texttt{mstatus}, \texttt{mepc}, \texttt{mcause} 等核心 CSR 的作用有了实践层面的深刻理解。解决 Windows 环境配置难题和调试复杂中断逻辑的过程，极大地锻炼了我分析问题和解决问题的能力。通过将理论知识与硬件实现、软件测试相结合，我不仅验证了 CPU 设计的正确性，也对操作系统与硬件的交互机制有了更具体的认识，为未来更深入的系统级学习打下了坚实的基础。

\end{document}
