Skip to content
Permalink
Browse files

Add report, remove materials with copyright [ci skip]

Signed-off-by: Harry Chen <i@harrychen.xyz>
  • Loading branch information...
Harry-Chen committed Aug 19, 2019
1 parent b560123 commit 9d757abdba8ad1f632c4d3df12b98f02595e9038
@@ -17,7 +17,7 @@ See `AUTHORS` for information about the authors of this project.
* `src`: RTL code of NonTrivialMIPS CPU
* `vivado`: Vivado project and block design of NSCSCC SoC (now using GS232 IP)
* `testbench`: Testbenches of NonTrivialMIPS CPU / NSCSCC Soc
* `material`: references
* `report`: Design reports (LaTeX srouce code and rendered PDF)

## Build Project

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN -1.11 MB material/boom-spec.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,24 @@
\chapter{声明与致谢}

\section{版权声明}

本项目涉及的代码均在 GitHub 开放,相应的仓库列举如下(名称即为链接):

\begin{description}
\item[\href{https://github.com/trivialmips/TrivialMIPS}{\color{blue} TrivialMIPS}] 初版的 CPU 设计(运行在清华大学 ThinPad 实验板上)
\item[\href{https://github.com/trivialmips/nontrivial-mips}{\color{blue} NonTrivialMIPS}] 最终提交的 CPU 设计(运行在龙芯实验板上)
\item[\href{https://github.com/trivialmips/TrivialMIPS_Software}{\color{blue} Software}] C++ 编写的裸机(Baremetal)程序,包括 TrivialBootloader 等
\item[\href{https://github.com/trivialmips/u-boot-trivialmips}{\color{blue} U-Boot}] 移植的 U-Boot 引导程序
\item[\href{https://github.com/trivialmips/u-boot-trivialmips}{\color{blue} uCore}] 移植的 uCore 操作系统
\item[\href{https://github.com/trivialmips/linux-nontrivial-mips}{\color{blue} Linux}] 移植的 Linux 内核
\item[\href{https://github.com/trivialmips/openssl}{\color{blue} OpenSSL}] 适配硬件 AES 加速功能的 OpenSSL 程序
\item[\href{https://github.com/trivialmips/trivial-dashboard}{\color{blue} TrivialDashboard}] 使用 Qt 撰写的 Dashboard 演示程序
\end{description}

这些项目均遵循它们特定的开源许可证,某些目录中可能包含受版权保护的内容,使用它们意味着您知晓并愿意承担任何可能的法律责任。

本报告著作权归作者所有。您被允许在不作任何修改的情况下重新分发此文档;未经许可,您不得以任何方式复制、引用或演绎其中的任何内容。

\section{致谢}

本项目开发过程中得到了来自清华大学计算机系张宇翔同学的大力支持,我们在此表示衷心的感谢。此外,我们的指导教师陈康老师、刘卫东老师给我们提出了许多宝贵的建议,唐适之同学、王邈同学、刘家昌同学也向我们提供了帮助,在此一并向他们表示感谢。
@@ -0,0 +1,39 @@
\chapter{自动化测试}

为了保证实现的正确性,本项目进行了自动化的集成、测试与部署。所有的流程都通过Docker进行,确保是可完整复现的。

\section{硬件测试}
\label{section:test_hardware}

本项目使用的主要硬件设计语言SystemVerilog是一门强大的验证语言,我们用它编写testbench来测试硬件模块。主要的测试用例分为有:

\begin{description}
\item[CPU测试] 本部分用于测试CPU实现指令的正确性。我们对CPU的各条指令都编写了相应的测试程序,同时还对各类可能的冲突现象、异常、TLB的行为编写了对应的测试。测试的过程是通过一个testbench虚拟出外部的总线和RAM并且接入CPU,并对CPU中的访存动作,包括WB阶段对寄存器和的写请求和MEM阶段的内存写请求进行监视。每个测试用例对上述动作都会给出响应期待的结果,同时在运行testbench时会将监测到的真实的写请求和期望的结果进行对比进而确认程序执行的正确性。整个CPU的测试过程是自动化的,通过指定格式的汇编代码即可生成对应的存储文件(\texttt{.mem}文件)、答案文件(\texttt{.ans}文件);我们编写了用于执行上述动作的 SystemVerilog task,可以直接使用 Vivado 对所有用例依次执行测试,得到比较结果,无需人工介入观察信号,如果发现真实的运行和期望不符会进行报告。所有的测试用例以及解释可见表\ref{table:cpu_testbenches}。除此之外,我们还在CPU仿真部分引入了Verilator这一基于C++的编译型仿真工具,用于简单的测试,其性能相比解释型工具有数量级上的增强。
\item[Cache 测试] 我们生成不同特征的访存序列(顺序/随机),并捕获真实应用程序的访存序列,将其作为激励传递给 Cache 组件,观察其行为是否与预期一致,本部分用于测试 Cache 的正确性。此部分还使用了一个 AXI RAM 的行为模型,用于替代 Xilinx AXI Block RAM Generator IP 核,并能模拟测试中人工插入的延迟。

\end{description}

同时,我们还为龙芯功能测试、性能测试编写 tcl 脚本并修改 testbench,以在 CI 环境中能够进行自动化测试和结果提取。最后,还可以自动生成上述测试的 bitstream 文件,供直接上板测试。

对于主分支的每一次提交,都需要进行持续集成(CI),步骤包括进行IP核的生成与预综合、上述的测试,以及 bitstream 的生成。由于完整仿真速度较慢,通常只运行CPU测试部分。

\begin{table}[!htbp]
\centering
\caption{CPU测试用例(位于 \texttt{testbench/cpu/testcases} 目录中)}
\label{table:cpu_testbenches}
\begin{threeparttable}
\begin{tabular}{|l|l|}
\hline
\multicolumn{1}{|c|}{\textbf{文件名}} & \multicolumn{1}{c|}{\textbf{测试内容}} \\ \hline
except/* & 异常相关测试 \\ \hline
instr/* & 指令功能测试 \\ \hline
branch/* & 分支测试 \\ \hline
hazard/* & 各类边界情况测试 \\ \hline
across\_tlb/* & TLB测试 \\ \hline
performance/* & 性能测试 \\ \hline \end{tabular}
\end{threeparttable}
\end{table}

\section{软件测试}

在软件方面,本项目计划对编写的所有汇编/C/C++代码,移植的Bootloader、操作系统,以及需要运行的功能测试、性能测试,均编写基于GitLab CI的持续集成脚本,保证每个版本都能进行正确的、可重现的编译。
@@ -0,0 +1,94 @@
\chapter{引导程序(Bootloader)}

\section{第一阶段:TrivialBootloader}

作为板上系统的一部分,BootROM 中包含了系统每次上电或重置时都会首先执行的代码,起始物理地址为 \texttt{0x1FC00000}。由于这部分程序是固化在FPGA中的,为了节约有限的板载存储,Bootrom中的代码不能太大。因此,有必要撰写一个较小的Bootloader来进行初步的系统初始化和加载工作,将其命名为TrivialBootloader。

\subsection{汇编部分}

作为程序入口,在跳转到高级语言编写的代码之前,需要先使用汇编语言设置一些基本参数,如栈基址(\texttt{sp})寄存器和异常处理入口等。具体地,汇编部分具有如下功能:

\begin{itemize}
\item 系统的全局初始化,设置\texttt{sp, gp}寄存器,跳转到实际代码入口
\item C++代码退出后的清理与提示
\item 启用异常处理并设置异常向量
\end{itemize}

其中实际代码入口为 \texttt{\_main} 符号,\texttt{sp, gp}寄存器被分别设置到\texttt{\_stack, \_gp} 符号。而异常处理会跳转到 \texttt{\_exception\_handler} 符号。这些符号需要在链接时被填充。

\subsection{高级语言部分}

高级语言部分也分为两个C与C++两个子部分。C编写的部分主要用于提供 \texttt{\_main} 函数和 \texttt{\_exception\_handler}函数。前者具有打印欢迎信息、清零 BSS 段、执行 \texttt{main} 函数、打印返回值等功能,后者负责处理异常,从CP0中收集异常原因、异常地址等信息,以友好的方式打印出来。

C++部分是Bootloader的主体,也也是真正的 \texttt{main} 函数实现位置,其具有的功能包括:

\begin{description}
\item[内存检测] 通过不同块大小随机读写检测内存硬件与实现是否存在问题
\item[ELF启动] 支持从非易失存储(Flash)中读取合法的ELF文件头,正确地将其复制到内存的相应位置并跳转
\item[直接启动] 支持直接跳转到内存(\texttt{0x8000000})、片上内存(\texttt{0x8800000})入口点启动,便于系统移植时的调试工作
\item[串口旁加载] 支持从串口直接向内存中加载数据和指令,并跳转到指定的位置启动
\item[内存转储] 支持将指定的内存区域的数据转储到串口输出
\item[异常处理] 正确处理各种操作异常、非法情况(如没有选择启动模式、内存检测失败、要复制到内存的数据覆盖了Bootloader本身的代码),在发生异常时通过串口、LED等多种途径给出友好可读的提示
\end{description}

考虑到指令和数据 Cache 的存在可能会引发数据不一致,TrivialBootloader 在拷贝代码前将通过 CP0 \texttt{Config0} 寄存器中相应位关闭 \texttt{kseg0} 段的全部缓存,并在跳转到外部代码前再打开缓存。通过这一简单的处理,能够保证在执行前代码已经被全部写入到相应存储器中。

作为功能举例,在引导Flash中操作系统的 ELF 文件时,Bootloader输出为(没有启用内存检查):
\begin{minted}{text}
*****TrivialMIPS Bare Metal System*****
Compilation time: 19:37:09 Jul 25 2019
=====Entering TrivialBootloader=====
Bootloader used memory: from 0x88000000 to 0x88010000
Mode: Boot
Device: SPI Flash
Valid ELF file found, will now copy to RAM.
Copying 24 bytes from offset 0x19480 to address 0x80019400
Copying 2159744 bytes from offset 0x80 to address 0x80000000
Booting from address 0x80000000...
=====Exiting TrivialBootloader=====
\end{minted}

\subsection{链接脚本}

由于Bootloader可能被放置在不同位置,此时其本身可用的内存空间(作为栈)以及加载基址是不同的。因此,我们编写了如下的链接脚本。可以看到,我们将内存划分为高低两片,根据代码生成的位置选择不同的区域放置栈代码段和数据段。此外,可用内存范围、BSS段范围、需要检查的内存范围等都是由链接器提供的符号。其可以通过编译时定义不同的常量进行预处理,从而为高级语言提供关于平台的信息,灵活地适应多种要求。

附录 \ref{sec:linker-script} 中包含了当前使用的链接脚本。

\section{第二阶段:U-Boot}

\subsection{背景}
U-Boot是一个启动引导程序,常见于嵌入式系统中,用于引导Linux等操作系统。通过运行U-Boot引导程序,可以支持从Flash、U盘、网络等来源加载uCore、Linux系统镜像到内存并进行引导。由于U-Boot本身有较强的命令行功能和交互能力,它也可以作为一个硬件测试与演示的工具。在本系统的设计中,U-Boot将作为二级引导程序,放置在Flash中,被TrivialBootloader所加载。

\subsection{硬件需求}

U-Boot对CPU的功能要求较低,它不使用MIPS的中断和TLB机制,因此硬件可以不需要实现这些机制。对于其它的异常,仅仅在程序运行不正常时才会发生,如果假定程序能正常运行,对异常处理也没有要求。

作为功能丰富的引导程序,其将用到 SPI Flash、网络等外设。其中,网络控制器的正常工作是至关重要的,否则片上系统将失去从外部加载系统的功能。

\subsection{编译方法}

U-Boot可以直接使用\ref{section:software_platform}节中给出的编译器套件进行编译和调试。具体地,只需要从 \url{https://github.com/Harry-Chen/u-boot-trivialmips} 下载源代码,并运行下列命令:

\begin{minted}{bash}
make CROSS_COMPILE=mipsel-linux-gnu- nontrivialmips_thinpad_defconfig
make CROSS_COMPILE=mipsel-linux-gnu-
mipsel-linux-gnu-strip u-boot
\end{minted}

执行完后,即可生成最终的 ELF 可执行文件 \texttt{u-boot},将其写入配置 Flash 的 bitstream 之后的位置,并正确配置 TrivialBootloader 中的 Flash 镜像起始地址,即可被自动加载。

\subsection{移植内容}

U-Boot 与 Linux 内核源码的组织架构类似,也都采用了\texttt{DTS}(设备树源码)来描述设备,因此移植方法也比较类似。主要的移植工作主要分为两部分,一部分是添加CPU相关的SoC支持,一部分是添加板级支持。

由于之前的类似项目已经有了完成度较高的工作\footnote{\url{https://github.com/z4yx/u-boot-naivemips/}},本项目在其基础上进一步进行修改。主要的工作有:

\begin{itemize}
\item 更新到 U-Boot v2019.7 版本
\item 启用串口控制器驱动(包括系统启动早期和后期两个部分)
\item 添加定时器读取功能,准确反映运行时间
\item 编写 DTS 格式设备描述以准确反映SoC片上设备资源,加载相应驱动(包括网络、Flash等)
\item 利用\texttt{bootmenu}命令,增加启动菜单,提供引导至 uCore/Linux 操作系统、通过 DHCP/TFTP 协议网络引导、进入 U-Boot 控制台等选项
\item 调整 U-Boot 编译选项,将 Flash 管理、网络配置等工具内嵌于镜像中
\end{itemize}

0 comments on commit 9d757ab

Please sign in to comment.
You can’t perform that action at this time.