Files
2025-yatcpu/lab1/测试文件报告.tex
2025-11-18 00:55:46 +08:00

204 lines
8.4 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\section{测试文件}
\label{sec:testing}
CPUTest.scala 测试了整个 CPU 运行三个程序的正确性。本节选择其中两个程序的运行进行详细分析,查看 csrc 文件夹下对应 C 文件的内容,概述该程序做了什么,执行结果如何在 Chisel 测试中被检查;在测试波形图上简单分析其执行,并说明波形图最后几个周期检查执行结果时的波形。
\subsection{整体测试框架}
CPUTest.scala 定义了三个主要的测试类FibonacciTest、QuicksortTest 和 ByteAccessTest。每个测试都基于 ChiselTest 框架,通过 TestTopModule 作为顶层模块来驱动 CPU 执行相应的程序。测试框架的核心结构如下:
\begin{lstlisting}[caption={CPUTest.scala 测试框架结构}, style=ScalaChiselStyle]
class TestTopModule(exeFilename: String) extends Module {
val io = IO(new Bundle {
val mem_debug_read_address = Input(UInt(Parameters.AddrWidth))
val regs_debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_debug_read_data = Output(UInt(Parameters.DataWidth))
val mem_debug_read_data = Output(UInt(Parameters.DataWidth))
})
// 实例化内存、指令ROM、CPU等模块
// 提供调试接口用于验证执行结果
}
\end{lstlisting}
测试框架通过调试接口读取内存和寄存器的值,与预期结果进行比较,从而验证 CPU 执行程序的正确性。
\subsection{斐波那契数列计算测试}
\subsubsection{程序功能分析}
fibonacci.c 程序实现了一个递归计算斐波那契数列的功能。程序代码如下:
\begin{lstlisting}[language=C, caption={fibonacci.c 程序代码}, style=CStyle]
int fib(int a) {
if (a == 1 || a == 2) return 1;
return fib(a - 1) + fib(a - 2);
}
int main() {
*(int *)(4) = fib(10);
}
\end{lstlisting}
该程序通过递归算法计算斐波那契数列的第 10 项fib(10)),并将结果存储到内存地址 0x4 处。斐波那契数列的递归定义为:
\begin{itemize}
\item fib(1) = 1
\item fib(2) = 1
\item fib(n) = fib(n-1) + fib(n-2) (n > 2)
\end{itemize}
因此fib(10) 的计算结果为 55。
\subsubsection{测试结果检查}
在 FibonacciTest 中,测试代码通过以下方式检查结果:
\begin{lstlisting}[caption={斐波那契测试的结果检查}, style=ScalaChiselStyle]
c.io.mem_debug_read_address.poke(4.U)
c.clock.step()
c.io.mem_debug_read_data.expect(55.U)
\end{lstlisting}
测试首先执行 50,000 个时钟周期50 × 1000确保递归计算完成。然后通过内存调试接口读取地址 0x4 的值,验证是否为预期的 55。
\subsubsection{波形图分析}
基于 VCD 文件分析,斐波那契程序执行过程中的关键信号包括:
\begin{itemize}
\item \texttt{cpu\_io\_instruction\_address}:程序计数器值,显示指令执行流程
\item \texttt{mem\_io\_bundle\_write\_enable}:内存写使能信号,标识数据写入操作
\item \texttt{mem\_io\_bundle\_address}:内存访问地址
\item \texttt{mem\_io\_bundle\_write\_data}:要写入内存的数据
\item \texttt{io\_mem\_debug\_read\_data}:调试接口读取的内存数据
\end{itemize}
在程序执行的最后阶段,可以观察到:
\begin{enumerate}
\item \texttt{mem\_io\_bundle\_write\_enable} 信号置高,表示正在进行内存写入
\item \texttt{mem\_io\_bundle\_address} 显示为 0x00000004写入地址为 4
\item \texttt{mem\_io\_bundle\_write\_data} 显示为 0x00000037十进制 55即 fib(10) 的计算结果
\item 调试接口 \texttt{io\_mem\_debug\_read\_data} 最终稳定显示 0x00000037
\end{enumerate}
\subsection{快速排序算法测试}
\subsubsection{程序功能分析}
quicksort.c 程序实现了快速排序算法,对 10 个整数进行排序:
\begin{lstlisting}[language=C, caption={quicksort.c 程序代码}, style=CStyle]
void quicksort(int *arr, int l, int r) {
if (l >= r) return;
int pivot = arr[l];
int i = l, j = r;
while (i < j) {
while(arr[j] >= pivot && i < j) --j;
arr[i] = arr[j];
while(arr[i] < pivot && i < j) ++i;
arr[j] = arr[i];
}
arr[i] = pivot;
quicksort(arr, l, i - 1);
quicksort(arr, i + 1, r);
}
int main() {
int nums[10];
// 初始化数组:[6, 2, 4, 5, 3, 1, 0, 9, 7, 8]
nums[0] = 6; nums[1] = 2; nums[2] = 4; nums[3] = 5;
nums[4] = 3; nums[5] = 1; nums[6] = 0; nums[7] = 9;
nums[8] = 7; nums[9] = 8;
quicksort(nums, 0, 9);
// 将排序结果写入内存地址 4, 8, 12, ..., 40
for (int i = 1; i <= 10; ++i) {
*(int *)(i * 4) = nums[i - 1];
}
}
\end{lstlisting}
程序将初始数组 [6, 2, 4, 5, 3, 1, 0, 9, 7, 8] 排序为 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],然后将结果依次写入内存地址 4, 8, 12, ..., 40。
\subsubsection{测试结果检查}
在 QuicksortTest 中,测试代码验证排序结果:
\begin{lstlisting}[caption={快速排序测试的结果检查}, style=ScalaChiselStyle]
for (i <- 1 to 10) {
c.io.mem_debug_read_address.poke((4 * i).U)
c.clock.step()
c.io.mem_debug_read_data.expect((i - 1).U)
}
\end{lstlisting}
测试循环读取内存地址 4, 8, 12, ..., 40 的值,期望得到 0, 1, 2, ..., 9验证排序的正确性。
\subsubsection{波形图分析}
快速排序程序执行过程中的关键信号变化:
\begin{itemize}
\item 多次内存写入操作,\texttt{mem\_io\_bundle\_write\_enable} 信号周期性置高
\item \texttt{mem\_io\_bundle\_address} 依次显示 0x00000004, 0x00000008, ..., 0x00000028
\item \texttt{mem\_io\_bundle\_write\_data} 依次显示 0x00000000, 0x00000001, ..., 0x00000009
\item 调试接口验证阶段,\texttt{io\_mem\_debug\_read\_data} 依次显示正确的排序值
\end{itemize}
\subsection{字节访问测试}
\subsubsection{程序功能分析}
ByteAccessTest 测试 CPU 对单个字节的存储和加载功能,验证字节级内存访问的正确性。该测试使用 sb.asmbin 程序,主要测试 Store Byte (sb) 和 Load Byte (lb) 指令。
\subsubsection{测试结果检查}
测试通过寄存器调试接口验证字节操作的正确性:
\begin{lstlisting}[caption={字节访问测试的结果检查}, style=ScalaChiselStyle]
c.io.regs_debug_read_address.poke(5.U)
c.io.regs_debug_read_data.expect(0xDEADBEEFL.U)
c.io.regs_debug_read_address.poke(6.U)
c.io.regs_debug_read_data.expect(0xEF.U)
c.io.regs_debug_read_address.poke(1.U)
c.io.regs_debug_read_data.expect(0x15EF.U)
\end{lstlisting}
测试验证了字节存储和加载操作对寄存器值的影响,确保字节级内存访问的正确实现。
\subsection{波形图截取建议}
基于 VCD 文件分析,建议截取以下关键波形图:
\begin{enumerate}
\item \textbf{斐波那契程序执行结果写入阶段}
\begin{itemize}
\item 信号:\texttt{mem\_io\_bundle\_write\_enable}, \texttt{mem\_io\_bundle\_address}, \texttt{mem\_io\_bundle\_write\_data}
\item 时间点程序最后几个周期fib(10) 结果写入内存地址 0x4
\item 特征:写使能置高,地址为 0x00000004数据为 0x00000037
\end{itemize}
\item \textbf{快速排序程序内存写入序列}
\begin{itemize}
\item 信号:\texttt{mem\_io\_bundle\_write\_enable}, \texttt{mem\_io\_bundle\_address}, \texttt{mem\_io\_bundle\_write\_data}
\item 时间点:排序完成后,结果依次写入内存的阶段
\item 特征:连续的写操作,地址递增,数据为排序后的序列 0-9
\end{itemize}
\item \textbf{调试接口读取阶段}
\begin{itemize}
\item 信号:\texttt{io\_mem\_debug\_read\_address}, \texttt{io\_mem\_debug\_read\_data}
\item 时间点:测试的最后阶段,验证执行结果
\item 特征:调试地址变化,对应数据正确显示
\end{itemize}
\end{enumerate}
\subsection{测试总结}
CPUTest.scala 通过三个不同复杂度的测试程序全面验证了单周期 CPU 的功能:
\begin{itemize}
\item \textbf{斐波那契测试}验证了 CPU 的递归函数调用能力,包括栈操作、参数传递和返回值处理
\item \textbf{快速排序测试}验证了 CPU 的数组处理、循环控制和复杂算法执行能力
\item \textbf{字节访问测试}验证了 CPU 对不同类型内存访问指令的支持
\end{itemize}
所有测试都通过内存和寄存器调试接口验证执行结果,确保 CPU 能够正确执行各种程序。波形图分析显示了程序执行过程中的关键信号变化,验证了数据通路的正确性和控制信号的时序准确性。