实验报告检查

This commit is contained in:
2025-12-21 23:11:21 +08:00
parent 078b2c0b37
commit 52ecd7743b
85 changed files with 8477 additions and 16 deletions

6
.idea/copilot.data.migration.ask.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View File

@@ -88,6 +88,5 @@ class Execute extends Module {
"b111".U -> (io.csr_reg_read_data & io.reg1_data) // csrrci "b111".U -> (io.csr_reg_read_data & io.reg1_data) // csrrci
) )
) )
} }

View File

@@ -1,7 +1,7 @@
\relax \relax
\providecommand\hyper@newdestlabel[2]{} \providecommand\hyper@newdestlabel[2]{}
\providecommand\HyField@AuxAddToFields[1]{} \providecommand*\HyPL@Entry[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{} \HyPL@Entry{0<</S/D>>}
\@writefile{toc}{\contentsline {section}{\numberline {1}实验目的}{1}{section.1}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {1}实验目的}{1}{section.1}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2}实验环境}{1}{section.2}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {2}实验环境}{1}{section.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3}模块实现与分析}{1}{section.3}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {3}模块实现与分析}{1}{section.3}\protected@file@percent }

View File

@@ -1,11 +1,11 @@
# Fdb version 4 # Fdb version 4
["pdflatex"] 1763467669.98259 "e:/jizu/2025-fall-yatcpu-repo/lab2/实验报告/report.tex" "report.pdf" "report" 1763467675.61282 0 ["pdflatex"] 1766327707.54833 "e:/jizu/2025-fall-yatcpu-repo/lab2/实验报告/report.tex" "report.pdf" "report" 1766327712.73648 0
"1.png" 1763464685.80927 44487 a60a40cf256e2865aa693f816b62e22a "" "1.png" 1763464685.80927 44487 a60a40cf256e2865aa693f816b62e22a ""
"2-1.png" 1763466472.73174 49260 023aa4d90519008ce962ff92929a4130 "" "2-1.png" 1763466472.73174 49260 023aa4d90519008ce962ff92929a4130 ""
"2-2.png" 1763466452.06497 49585 bcd0713f6ed3a5dc1a039b990397f42e "" "2-2.png" 1763466452.06497 49585 bcd0713f6ed3a5dc1a039b990397f42e ""
"C:/Users/26586/AppData/Local/MiKTeX/fonts/map/pdftex/pdftex.map" 1761456855.17569 80909 eab91d9745dd2edfd62a31d53cd5fe15 "" "C:/Users/26586/AppData/Local/MiKTeX/fonts/map/pdftex/pdftex.map" 1765351489.73151 80909 eab91d9745dd2edfd62a31d53cd5fe15 ""
"C:/Users/26586/AppData/Local/MiKTeX/fonts/pk/ljfour/jknappen/ec/dpi600/tcrm1200.pk" 1760284205.24029 14064 0435e595d6b2364a10c98a375d33de30 "" "C:/Users/26586/AppData/Local/MiKTeX/fonts/pk/ljfour/jknappen/ec/dpi600/tcrm1200.pk" 1760284205.24029 14064 0435e595d6b2364a10c98a375d33de30 ""
"C:/Users/26586/AppData/Local/MiKTeX/miktex/data/le/pdftex/pdflatex.fmt" 1760284172.44912 13286967 cf204fddfacb93f0867a71203b66337a "" "C:/Users/26586/AppData/Local/MiKTeX/miktex/data/le/pdftex/pdflatex.fmt" 1765351984.22676 13286807 d014ff17da888b7ca0b84b7eef16412c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/UGBK.sfd" 1458473944 185547 3920f4d0519124bae1340c8047ea76bc "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/UGBK.sfd" 1458473944 185547 3920f4d0519124bae1340c8047ea76bc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/Unicode.sfd" 1458473944 107591 5aa427daaa6489b60892769618bdfe76 "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/Unicode.sfd" 1458473944 107591 5aa427daaa6489b60892769618bdfe76 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/jknappen/ec/tcrm1200.tfm" 993062508 1444 95ffe0f19b974d50849790c8225c7ef7 "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/jknappen/ec/tcrm1200.tfm" 993062508 1444 95ffe0f19b974d50849790c8225c7ef7 ""
@@ -235,12 +235,12 @@
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/xcolor/xcolor.sty" 1729265222 55384 b454dec21c2d9f45ec0b793f0995b992 "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/xcolor/xcolor.sty" 1729265222 55384 b454dec21c2d9f45ec0b793f0995b992 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber-utf8.cfg" 1657817710 5700 603e2f09dad175efabc8594730623a0b "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber-utf8.cfg" 1657817710 5700 603e2f09dad175efabc8594730623a0b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber.sty" 1657817710 38160 aafa8d740e4f21b62a4acd4835e54359 "" "C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber.sty" 1657817710 38160 aafa8d740e4f21b62a4acd4835e54359 ""
"C:/WINDOWS/Fonts/msyh.ttc" 1753780693.17946 19704352 fa04b86eb9c632ef04217c3e43d81c4d "" "C:/WINDOWS/Fonts/msyh.ttc" 1757965193.23002 19704352 fa04b86eb9c632ef04217c3e43d81c4d ""
"C:/WINDOWS/Fonts/simhei.ttf" 1711630440 9755440 186b27ff118e04e580eaad8ae78f2420 "" "C:/WINDOWS/Fonts/simhei.ttf" 1711630440 9755440 186b27ff118e04e580eaad8ae78f2420 ""
"C:/WINDOWS/Fonts/simsun.ttc" 1753780693.16377 18070492 1615784d420bffd42e8addd1714f7c6a "" "C:/WINDOWS/Fonts/simsun.ttc" 1757965193.40189 18070492 1615784d420bffd42e8addd1714f7c6a ""
"e:/jizu/2025-fall-yatcpu-repo/lab2/实验报告/report.tex" 1763467658.47142 27324 3fd11d656296e9f88b3f464f178af593 "" "e:/jizu/2025-fall-yatcpu-repo/lab2/实验报告/report.tex" 1766327703.44512 27319 17b051a214306158c6ff98f03ca7f06c ""
"report.aux" 1763467673.746 6111 07033418962ab1af210a6d01479bf5b6 "pdflatex" "report.aux" 1766327711.08199 6111 07033418962ab1af210a6d01479bf5b6 "pdflatex"
"report.out" 1763467673.74958 2623 ab2b263d3fa096b86c98145cb326a6a5 "pdflatex" "report.out" 1766327711.08387 2623 ab2b263d3fa096b86c98145cb326a6a5 "pdflatex"
(generated) (generated)
"report.aux" "report.aux"
"report.log" "report.log"

Binary file not shown.

Binary file not shown.

View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -45,6 +45,7 @@ class Forwarding extends Module {
val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex) val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex)
val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex) val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex)
val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex) val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex)
io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM, io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward)) Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM, io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
@@ -61,3 +62,6 @@ class Forwarding extends Module {
// Lab3(Final) End // Lab3(Final) End
} }

View File

@@ -0,0 +1,365 @@
\documentclass[12pt]{ctexart} % 使用 ctexart 文档类支持中文12pt 字号
\usepackage[utf8]{inputenc} % 输入编码,保持兼容性
\usepackage[margin=2.5cm]{geometry} % 设置页边距
\usepackage{graphicx} % 导入图片
\usepackage{amsmath} % 支持数学公式
\usepackage{listings} % 代码块高亮
\usepackage{xcolor} % 用于代码高亮颜色
\usepackage{hyperref} % 目录、交叉引用可点击生成PDF书签
\hypersetup{
colorlinks=true, % 这是关键,它会让链接文本以颜色显示,而不是边框
linkcolor=black, % 内部链接(如目录、章节引用)的颜色设为黑色
citecolor=green, % 引用文献的颜色(如果用不到可以忽略或设为黑色)
urlcolor=blue, % URL链接的颜色如果用不到可以忽略或设为黑色
filecolor=magenta, % 文件链接的颜色(如果用不到可以忽略或设为黑色)
% 可以添加更多其他 PDF 元数据,让 PDF 文件信息更完整
pdftitle={实验一:单周期 RISC-V CPU 设计与实现},
pdfauthor={朱梓涵},
pdfsubject={RISC-V CPU 设计与实现报告},
pdfkeywords={RISC-V, CPU, Chisel, 单周期, 实验报告}
}
% 目录、交叉引用可点击生成PDF书签
\usepackage{fancyhdr} % 自定义页眉页脚
\usepackage{enumitem} % 列表项自定义
\usepackage{ifthen} % 条件判断(用于图片占位)
% --- 图片缺失占位宏 ---
\newcommand{\includegraphicsorplaceholder}[2][]{%
\IfFileExists{#2}{\includegraphics[#1]{#2}}{\fbox{\parbox[c][0.2\textheight][c]{0.9\textwidth}{\centering Missing image: #2}}}%
}
% --- 页眉页脚设置 ---
\pagestyle{fancy}
\fancyhf{} % 清除所有页眉页脚字段
\fancyhead[L]{\MakeUppercase{实验一:单周期 RISC-V CPU 设计与实现}} % 左侧页眉:大写实验名称
\fancyfoot[C]{\thepage} % 居中页脚:页码
\renewcommand{\headrulewidth}{0.4pt} % 页眉下方的横线粗细
\renewcommand{\footrulewidth}{0.4pt} % 页脚上方的横线粗细
% 解决 fancyhdr 提示的 \headheight 偏小问题
\setlength{\headheight}{15pt}
% --- 标题信息 ---
\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},
% 添加 Chisel 相关关键字
morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt},
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},
}
\lstset{style=ScalaChiselStyle} % 默认代码风格为 Scala/Chisel
% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}
% --- 文档开始 ---
\begin{document}
\maketitle % 生成标题
\thispagestyle{empty} % 标题页无页码
% --- 正文开始 ---
\section{实验目的}
本实验旨在深入理解 RISC-V 指令集架构 (ISA) 与单周期 CPU 的工作原理。实验目标包括:
\begin{enumerate}[label=\arabic*.] % 使用 enumerate 环境创建编号列表
\item 设计并实现一个支持部分 RV32I 指令集的单周期 CPU。
\item 掌握 CPU 经典五阶段(取指、译码、执行、访存、写回)在单周期模型下的数据通路和控制逻辑设计。
\item 学习使用 Chisel 硬件描述语言进行模块化硬件设计。
\item 通过编写单元测试和集成测试,利用 \texttt{chiseltest} 和 GTKWave 波形图验证 CPU 各模块及整体功能的正确性。
\end{enumerate}
\section{实验环境}
\begin{itemize}
\item \textbf{操作系统}: Windows 11
\item \textbf{开发工具}: IntelliJ IDEA
\item \textbf{构建工具}: SBT
\item \textbf{仿真与测试}: Verilator, GTKWave
\end{itemize}
\section{阶段功能划分}
本单周期 RISC-V CPU 依照经典的五级流水线概念进行设计,虽然是单周期实现,但其内部模块划分仍遵循五阶段的逻辑,确保数据通路和控制逻辑清晰。
\begin{itemize}
\item \textbf{取指 (Instruction Fetch, IF)}: 程序计数器 (PC) 提供指令地址,指令存储器根据该地址输出 32 位指令。PC 在每个时钟周期默认加 4若遇跳转或分支成功则更新为目标地址。
\item \textbf{译码 (Instruction Decode, ID)}: 译码单元解析指令,提取操作数(寄存器地址 \texttt{rs1}, \texttt{rs2})、目标寄存器地址 (\texttt{rd}) 和立即数。主控制器根据指令操作码生成后续阶段所需的所有控制信号。
\item \textbf{执行 (Execute, EX)}: 算术逻辑单元 (ALU) 根据译码阶段生成的控制信号,对来自寄存器文件或立即数生成器的操作数进行计算。同时,分支跳转的地址计算和条件判断也在此阶段完成。
\item \textbf{访存 (Memory Access, MEM)}: 根据译码阶段生成的访存控制信号与数据存储器进行交互。Load 指令从此阶段读取数据Store 指令则向此阶段写入数据。
\item \textbf{写回 (Write Back, WB)}: 将执行结果或从数据存储器中读取的数据写回寄存器文件。写回的数据来源由控制信号决定。
\end{itemize}
\section{模块实现与分析}
\subsection{取指}
\begin{itemize}
\item \textbf{功能}: 根据 \texttt{PC} 的当前值从指令存储器中取出指令,并计算下一周期的 \texttt{PC} 值。
\item \textbf{实现要点}: \texttt{PC} 的更新逻辑是核心。它由跳转标志 \texttt{jump\_flag\_id} 控制:若跳转发生,\texttt{PC} 更新为 \texttt{jump\_address\_id};否则,顺序执行,\texttt{PC} 更新为 \texttt{PC + 4}
\end{itemize}
\subsubsection{代码实现}
\begin{lstlisting}[caption={取指模块PC更新逻辑}, label={lst:if_pc}]
// lab1(InstructionFetch)
when(io.jump_flag_id) {
pc := io.jump_address_id
}.otherwise {
pc := pc + 4.U
}
// lab1(InstructionFetch) end
\end{lstlisting}
\subsubsection{波形图}
\begin{figure}[htbp]
\centering
\includegraphicsorplaceholder[width=0.9\textwidth]{b1.png}
\caption{取指模块 (\texttt{InstructionFetch}) 波形图}
\label{fig:if_waveform}
\end{figure}
\subsection{译码}
\begin{itemize}
\item \textbf{功能}: 解析指令,生成立即数,并为后续阶段提供控制信号。
\item \textbf{实现要点}: 控制信号的生成逻辑是关键。例如,\texttt{memory\_read\_enable} 仅在 L-type 指令时有效,\texttt{wb\_reg\_write\_source} 根据指令类型选择写回数据是来自 ALU、数据存储器还是 PC+4。
\end{itemize}
\subsubsection{代码实现}
\begin{lstlisting}[caption={译码模块控制信号生成逻辑}, label={lst:id_control}]
// lab1(InstructionDecode)
io.ex_aluop2_source := Mux(opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.memory_read_enable := opcode === InstructionTypes.L
io.memory_write_enable := opcode === InstructionTypes.S
io.wb_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult
)(
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
// lab1(InstructionDecode) end
\end{lstlisting}
\subsubsection{波形图}
\begin{figure}[htbp]
\centering
\includegraphicsorplaceholder[width=0.9\textwidth]{b2.png}
\caption{译码模块 (\texttt{InstructionDecode}) 波形图}
\label{fig:id_waveform}
\end{figure}
\subsection{执行}
\begin{itemize}
\item \textbf{功能}: 执行 ALU 运算,并处理分支和跳转逻辑。
\item \textbf{实现要点}: ALU 的两个操作数 \texttt{op1}\texttt{op2} 的来源由译码模块生成的 \texttt{aluop*\_source} 信号决定,实现了操作数的灵活选择。
\end{itemize}
\subsubsection{波形图}
\begin{figure}[htbp]
\centering
\includegraphicsorplaceholder[width=0.9\textwidth]{b3.png}
\caption{执行模块 (\texttt{Execute}) 波形图}
\label{fig:ex_waveform}
\end{figure}
\subsubsection{代码实现}
\begin{lstlisting}[caption={执行模块ALU操作数选择逻辑}, label={lst:ex_aluops}]
// lab1(Execute)
alu.io.func := alu_ctrl.io.alu_funct
alu.io.op1 := Mux(
io.aluop1_source === ALUOp1Source.Register,
io.reg1_data,
io.instruction_address
)
alu.io.op2 := Mux(
io.aluop2_source === ALUOp2Source.Register,
io.reg2_data,
io.immediate
)
// lab1(Execute) end
\end{lstlisting}
\subsection{CPU 模块}
\begin{itemize}
\item \textbf{功能}: 实例化取指、译码、执行等所有子模块,并根据数据通路图将它们正确连接起来。
\item \textbf{实现要点}: 确保数据流和控制流在模块间的正确传递是顶层连接的关键。
\end{itemize}
\subsubsection{代码实现}
\begin{lstlisting}[caption={CPU模块部分连接逻辑}, label={lst:cpu_top}]
// lab1(cpu)
ex.io.instruction := inst_fetch.io.instruction
ex.io.instruction_address := inst_fetch.io.instruction_address
ex.io.reg1_data := regs.io.read_data1
ex.io.reg2_data := regs.io.read_data2
ex.io.immediate := id.io.ex_immediate
ex.io.aluop1_source := id.io.ex_aluop1_source
ex.io.aluop2_source := id.io.ex_aluop2_source
// lab1(cpu) end
\end{lstlisting}
\section{测试与结果分析}
\subsection{单元测试InstructionDecoderTest 分析}
\subsubsection{L-Type 指令测试分析}
测试用例首先向译码模块的 \texttt{io.instruction} 端口输入一条 L-Type 指令。随后,测试代码使用 \texttt{.expect()} 方法断言模块的各个输出端口信号值是否与预设的期望值一致。
对于 \texttt{lw} 指令,其核心功能是从内存读取数据并写回寄存器。因此:
\begin{itemize}
\item \texttt{memory\_read\_enable} 必须为 \texttt{true},以启动访存阶段的数据读取。
\item \texttt{reg\_write\_enable} 必须为 \texttt{true},以允许最终结果写入寄存器。
\item \texttt{wb\_reg\_write\_source} 必须是 \texttt{RegWriteSource.Memory},因为写回的数据源于数据存储器。
\item \texttt{ex\_immediate} 必须是指令编码中包含的偏移量(此例中为 32用于地址计算 \texttt{rs1 + imm}
\end{itemize}
这些 \texttt{expect} 值精确地定义了 L-Type 指令在译码阶段应生成的正确行为模式,确保了控制通路的正确性。
\subsubsection{波形图分析}
\begin{figure}[htbp]
\centering
\includegraphicsorplaceholder[width=0.9\textwidth]{b2.png}
\caption{\texttt{L-Type} 指令 \texttt{lw x3, 0(x8)} 的译码波形图}
\label{fig:lw_decode_waveform}
\end{figure}
如图所示,波形图展示了指令 lw x3, 0(x8)(机器码 0x00404183的译码过程。在时钟上升沿之后
\begin{itemize}
\item \verb|id_io_instruction| 端口稳定为 \texttt{0x00404183},对应 I-type 的 Load 指令 \texttt{lw x3, 0(x8)}
\item \verb|id_io_memory_read_enable| 和 \verb|id_io_reg_write_enable| 信号被置为高电平1表示该指令需要从存储器读取数据并写回寄存器。
\item \verb|id_io_wb_reg_write_source| 信号值为 \texttt{01} (二进制),表示写回数据的来源是 Memory。
\item \verb|id_io_ex_immediate| 的值为 \texttt{0x00000000},即偏移量 0。
\end{itemize}
波形验证了译码模块对 I-type Load指令的控制信号输出与 \texttt{InstructionDecoderTest.scala} 中的 \texttt{expect} 语句一致,说明译码单元能够正确识别 Load 指令并产生相应控制信号。
\subsection{整体测试CPUTest (以 \texttt{FibonacciTest} 为例)}
\subsubsection{\texttt{fibonacci.c} 程序分析}
\begin{itemize}
\item \textbf{程序功能}:
该 C 语言程序定义了一个递归函数 \texttt{fib(int a)},用于计算斐波那契数列的第 \texttt{a} 项。其逻辑为:如果 \texttt{a} 等于 1 或 2则返回 1否则返回 \texttt{fib(a-1)}\texttt{fib(a-2)} 之和。\texttt{main} 函数是程序的入口点,它调用 \texttt{fib(10)} 来计算斐波那契数列的第 10 项,并将最终结果(即 55存储到内存地址 \texttt{0x4}
\begin{lstlisting}[language=C, caption={Fibonacci 递归程序 \texttt{fibonacci.c}}, label={lst:fib_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); // 将 fib(10) 的结果写入内存地址 0x4
}
\end{lstlisting}
\item \textbf{Chisel 测试检查方式}:
测试框架首先将 \texttt{fibonacci.asmbin} 文件加载到 CPU 的指令存储器和数据存储器中。然后,它驱动 CPU 执行足够多的时钟周期(通过 \texttt{c.clock.step(1000)} 大循环),以确保递归计算和内存写入操作全部完成。在仿真结束时,测试代码通过读取数据存储器的调试端口:
\begin{lstlisting}[caption={Chisel 测试代码片段}, label={lst:chisel_test}]
c.io.mem_debug_read_address.poke(4.U) // 将调试地址设置为 0x4
c.clock.step() // 步进一个时钟周期
c.io.mem_debug_read_data.expect(55.U) // 期望从地址 0x4 读出的数据为 55
\end{lstlisting}
上述语句首先将调试端口的读取地址 \texttt{mem\_debug\_read\_address} 设置为 \texttt{0x4},然后步进一个时钟周期以便数据稳定,最后断言 \texttt{mem\_debug\_read\_data} 的值是否等于预期的 \texttt{55}。如果相等,则测试通过,验证了 CPU 能够正确执行递归计算并将结果写入指定内存。
\end{itemize}
\subsubsection{波形图分析}
\begin{figure}[htbp]
\centering
\includegraphicsorplaceholder[width=0.9\textwidth]{b41.png}
\caption{Fibonacci 程序执行末期及结果写入内存的波形图}
\label{fig:fibonacci_waveform}
\end{figure}
基于 VCD 文件分析,斐波那契程序执行过程中的关键信号包括:
\begin{itemize}
\item \verb|cpu_io_instruction_address|程序计数器PC显示指令的执行流程
\item \verb|mem_io_bundle_write_enable|:内存写使能信号,用于标识数据写入操作;
\item \verb|mem_io_bundle_address|:内存访问地址;
\item \verb|mem_io_bundle_write_data|:写入内存的数据;
\item \verb|io_mem_debug_read_data|:调试接口读取的内存数据,用于结果验证。
\end{itemize}
所选测试程序为斐波那契数列求解程序,其功能是计算第 10 项的值(即 55并在程序结束时将结果写入数据存储器地址 \texttt{0x00000004}。在 \texttt{CPUTest.scala} 的测试中,系统通过监测访存信号或从调试接口读取该地址的值,验证处理器输出是否正确。
在程序执行的最后阶段,可以在波形中观察到以下现象:
\begin{enumerate}
\item \verb|mem_io_bundle_write_enable| 信号置高,表示 CPU 正在执行 \verb|sw| 指令;
\item \verb|mem_io_bundle_address| 显示为 \verb|0x00000004|,即目标内存地址为 4
\item \verb|mem_io_bundle_write_data| 显示为 \verb|0x00000037|(十进制 55\verb|fib(10)| 的计算结果;
\item 随后,调试接口 \verb|io_mem_debug_read_data| 读出并稳定为相同的值 \verb|0x00000037|。
\end{enumerate}
由此可知CPU 成功将计算结果 55 写入目标地址,测试检查结果正确,验证了数据通路及访存阶段的功能实现。
\section{遇到的问题与改进建议}
\begin{enumerate}[label=\arabic*.]
\item \textbf{问题:立即数生成规则复杂,指导文档未详细展开。}
在实现译码模块时RISC-V 不同指令格式I/S/B/U/J的立即数拼接方式各不相同实验指导对此描述较为简略导致初期实现困难。
\begin{itemize}
\item \textbf{建议}:在实验指导中为每种指令格式提供一个具体的立即数拼接图示或示例代码,能极大帮助理解。
\end{itemize}
\item \textbf{问题:缺少对波形图调试的引导案例。}
初次使用 GTKWave 进行硬件调试时,面对海量的信号线,难以快速定位关键信号。
\begin{itemize}
\item \textbf{建议}:实验文档中可以附加一个简单的调试案例,例如追踪一条 \texttt{add} 指令的数据流,展示如何从取指 PC 开始,逐步添加 `instruction`, `reg\_read\_data`, `alu\_result`, `reg\_write\_data` 等信号,并解释它们在波形图上的时序关系。
\end{itemize}
\end{enumerate}
\section{实验结论}
通过本次实验,我成功设计并实现了一个功能基本完备的 RISC-V 单周期 CPU。在实现过程中我深入理解了数据通路与控制信号在指令执行过程中的协同作用并掌握了模块化的硬件设计思想。通过编写和分析单元测试与集成测试我学会了如何利用波形图对硬件设计进行验证和调试。本次实验极大地加深了我对计算机组成原理中理论知识的实践理解为后续更复杂的处理器设计打下了坚实的基础。
\end{document}

View File

@@ -0,0 +1,44 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\providecommand*\HyPL@Entry[1]{}
\HyPL@Entry{0<</S/D>>}
\@writefile{toc}{\contentsline {section}{\numberline {1}实验目的}{1}{section.1}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2}实验环境}{1}{section.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3}流水线结构与功能划分}{1}{section.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}三级流水线结构}{1}{subsection.3.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}五级流水线结构}{2}{subsection.3.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}缩短分支延迟的五级流水线}{2}{subsection.3.3}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {4}模块实现与分析}{3}{section.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}流水线寄存器PipelineRegister}{3}{subsection.4.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.1}功能}{3}{subsubsection.4.1.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.2}代码实现}{3}{subsubsection.4.1.2}\protected@file@percent }
\newlabel{lst:pipeline_reg}{{1}{3}{流水线寄存器实现}{lstlisting.1}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}流水线寄存器实现}{3}{lstlisting.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.1.3}设计要点}{4}{subsubsection.4.1.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}控制单元Control}{4}{subsection.4.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.1}功能}{4}{subsubsection.4.2.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.2}代码实现(最终版本)}{4}{subsubsection.4.2.2}\protected@file@percent }
\newlabel{lst:control_final}{{2}{4}{控制单元实现(缩短分支延迟版本)}{lstlisting.2}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}控制单元实现(缩短分支延迟版本)}{4}{lstlisting.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.3}设计要点}{5}{subsubsection.4.2.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}转发单元Forwarding}{6}{subsection.4.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.1}功能}{6}{subsubsection.4.3.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.2}代码实现(最终版本)}{6}{subsubsection.4.3.2}\protected@file@percent }
\newlabel{lst:forward_final}{{3}{6}{转发单元实现(缩短分支延迟版本)}{lstlisting.3}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}转发单元实现(缩短分支延迟版本)}{6}{lstlisting.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.3}设计要点}{8}{subsubsection.4.3.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}译码单元InstructionDecode}{8}{subsection.4.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.1}关键代码}{9}{subsubsection.4.4.1}\protected@file@percent }
\newlabel{lst:id_jump}{{4}{9}{ID 段跳转逻辑}{lstlisting.4}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {4}ID 段跳转逻辑}{9}{lstlisting.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.4.2}设计要点}{10}{subsubsection.4.4.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}CSR 指令的冒险分析}{10}{section.5}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}数据冒险}{10}{subsection.5.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2}控制冒险}{11}{subsection.5.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {5.3}结论}{11}{subsection.5.3}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {6}测试结果}{11}{section.6}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7}遇到的问题与改进建议}{12}{section.7}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {7.1}遇到的问题}{12}{subsection.7.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {7.2}改进建议}{12}{subsection.7.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {8}实验结论}{13}{section.8}\protected@file@percent }
\gdef \@abspage@last{13}

Binary file not shown.

View File

@@ -0,0 +1,507 @@
\documentclass[12pt]{ctexart} % 使用 ctexart 文档类支持中文12pt 字号
\usepackage[utf8]{inputenc} % 输入编码,保持兼容性
\usepackage[margin=2.5cm]{geometry} % 设置页边距
\usepackage{graphicx} % 导入图片
\usepackage{amsmath} % 支持数学公式
\usepackage{listings} % 代码块高亮
\usepackage{xcolor} % 用于代码高亮颜色
\usepackage{hyperref} % 目录、交叉引用可点击生成PDF书签
\hypersetup{
colorlinks=true, % 这是关键,它会让链接文本以颜色显示,而不是边框
linkcolor=black, % 内部链接(如目录、章节引用)的颜色设为黑色
citecolor=green, % 引用文献的颜色(如果用不到可以忽略或设为黑色)
urlcolor=blue, % URL链接的颜色如果用不到可以忽略或设为黑色
filecolor=magenta, % 文件链接的颜色(如果用不到可以忽略或设为黑色)
% 可以添加更多其他 PDF 元数据,让 PDF 文件信息更完整
pdftitle={实验三:流水线 CPU 设计与实现},
pdfauthor={朱梓涵},
pdfsubject={流水线 RISC-V CPU 设计与实现报告},
pdfkeywords={RISC-V, CPU, Chisel, 流水线, 实验报告}
}
% 目录、交叉引用可点击生成PDF书签
\usepackage{fancyhdr} % 自定义页眉页脚
\usepackage{enumitem} % 列表项自定义
\usepackage{ifthen} % 条件判断(用于图片占位)
% --- 图片缺失占位宏 ---
\newcommand{\includegraphicsorplaceholder}[2][]{%
\IfFileExists{#2}{\includegraphics[#1]{#2}}{\fbox{\parbox[c][0.2\textheight][c]{0.9\textwidth}{\centering Missing image: #2}}}%
}
% --- 页眉页脚设置 ---
\pagestyle{fancy}
\fancyhf{} % 清除所有页眉页脚字段
\fancyhead[L]{\MakeUppercase{实验三:流水线 CPU 设计与实现}} % 左侧页眉:大写实验名称
\fancyfoot[C]{\thepage} % 居中页脚:页码
\renewcommand{\headrulewidth}{0.4pt} % 页眉下方的横线粗细
\renewcommand{\footrulewidth}{0.4pt} % 页脚上方的横线粗细
% 解决 fancyhdr 提示的 \headheight 偏小问题
\setlength{\headheight}{15pt}
% --- 标题信息 ---
\title{\vspace{-2cm}\textbf{实验三:流水线 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},
% 添加 Chisel 相关关键字
morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt, elsewhen, otherwise, Wire, Bool, RegInit, asSInt, asUInt},
literate={:}{{\color{sol-base02}:}}1
}
\lstset{style=ScalaChiselStyle} % 默认代码风格为 Scala/Chisel
% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}
% --- 文档开始 ---
\begin{document}
\maketitle % 生成标题
\thispagestyle{empty} % 标题页无页码
% --- 正文开始 ---
\section{实验目的}
本实验旨在深入理解流水线技术在 CPU 设计中的应用,通过实现三级和五级流水线 CPU掌握流水线中竞争冒险的处理方法。实验目标包括
\begin{enumerate}[label=\arabic*.] % 使用 enumerate 环境创建编号列表
\item 理解流水线寄存器的作用,并实现支持阻塞和清空功能的流水线寄存器。
\item 设计并实现三级流水线 CPU掌握控制冒险的处理方法。
\item 设计并实现五级流水线 CPU学习使用阻塞和转发技术处理数据冒险。
\item 将分支跳转提前到译码阶段,进一步缩短分支延迟,优化流水线性能。
\item 通过编写测试用例,验证流水线 CPU 各模块及整体功能的正确性。
\end{enumerate}
\section{实验环境}
\begin{itemize}
\item \textbf{操作系统}: Windows 11
\item \textbf{开发工具}: IntelliJ IDEA
\item \textbf{构建工具}: SBT
\item \textbf{仿真与测试}: Verilator, chiseltest
\end{itemize}
\section{流水线结构与功能划分}
\subsection{三级流水线结构}
三级流水线将单周期 CPU 的组合逻辑切分为三个阶段:
\begin{itemize}
\item \textbf{取指 (IF)}: 根据 PC 从指令存储器取出指令。
\item \textbf{译码 (ID)}: 解码指令,生成控制信号,从寄存器组读取操作数。
\item \textbf{执行 (EX)}: 执行 ALU 运算、访存和写回操作。
\end{itemize}
在三级流水线中,主要需要处理控制冒险。当 EX 段执行跳转或分支指令时IF 和 ID 段的两条指令需要被清空。
\subsection{五级流水线结构}
五级流水线在三级流水线的基础上,将 EX 段进一步细分:
\begin{itemize}
\item \textbf{取指 (IF)}: 根据 PC 从指令存储器取出指令。
\item \textbf{译码 (ID)}: 解码指令,生成控制信号,从寄存器组读取操作数。
\item \textbf{执行 (EX)}: 执行 ALU 运算。
\item \textbf{访存 (MEM)}: 访问数据存储器。
\item \textbf{写回 (WB)}: 将结果写回寄存器组。
\end{itemize}
五级流水线引入了更复杂的数据冒险,需要使用阻塞和转发技术进行处理。
\subsection{缩短分支延迟的五级流水线}
在最终版本的五级流水线中,将分支和跳转指令的执行从 EX 段提前到 ID 段:
\begin{itemize}
\item 在 ID 段增加加法器,用于计算跳转目标地址。
\item 在 ID 段进行分支条件判断,使用转发逻辑从 MEM 和 WB 段获取操作数。
\item 如果依赖的数据还未产生,则进行阻塞。
\end{itemize}
这样做可以将分支延迟从两个时钟周期减少到一个时钟周期。
\section{模块实现与分析}
\subsection{流水线寄存器PipelineRegister}
\subsubsection{功能}
流水线寄存器是流水线 CPU 的核心组件,用于在相邻流水段之间缓存数据和控制信号。它支持三种操作:
\begin{itemize}
\item \textbf{清空 (flush)}: 将寄存器值重置为默认值,用于清除错误路径上的指令。
\item \textbf{阻塞 (stall)}: 保持当前寄存器值不变,用于暂停流水线。
\item \textbf{正常更新}: 在时钟上升沿将输入值写入寄存器。
\end{itemize}
\subsubsection{代码实现}
\begin{lstlisting}[caption={流水线寄存器实现}, label={lst:pipeline_reg}]
class PipelineRegister(width: Int = Parameters.DataBits, defaultValue: UInt = 0.U) extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val in = Input(UInt(width.W))
val out = Output(UInt(width.W))
})
// Lab3(PipelineRegister)
val register = RegInit(defaultValue)
when(io.flush) {
register := defaultValue
}.elsewhen(io.stall) {
}.otherwise {
register := io.in
}
io.out := register
// Lab3(PipelineRegister) End
}
\end{lstlisting}
\subsubsection{设计要点}
\begin{itemize}
\item 优先级:\texttt{flush} 信号优先级最高,其次是 \texttt{stall},最后是正常更新。
\item\texttt{flush} 为高时,寄存器被清空为默认值(通常是 NOP 指令或 0
\item\texttt{stall} 为高时,寄存器保持当前值不变。
\item 其他情况下,寄存器在时钟上升沿更新为输入值。
\end{itemize}
\subsection{控制单元Control}
\subsubsection{功能}
控制单元负责检测流水线中的冒险,并生成相应的控制信号:
\begin{itemize}
\item 检测数据冒险,生成阻塞信号。
\item 检测控制冒险,生成清空信号。
\end{itemize}
\subsubsection{代码实现(最终版本)}
\begin{lstlisting}[caption={控制单元实现(缩短分支延迟版本)}, label={lst:control_final}]
class Control extends Module {
val io = IO(new Bundle {
val jump_flag = Input(Bool())
val jump_instruction_id = Input(Bool())
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_ex = Input(Bool())
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_mem = Input(Bool())
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
val pc_stall = Output(Bool())
val if2id_stall = Output(Bool())
})
// Lab3(Final)
val stall = Wire(Bool())
val load_use_hazard = io.memory_read_enable_ex && io.rd_ex =/= 0.U &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_ex_alu = io.jump_instruction_id && io.rd_ex =/= 0.U &&
!io.memory_read_enable_ex &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_mem_load = io.jump_instruction_id && io.memory_read_enable_mem && io.rd_mem =/= 0.U &&
(io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
stall := load_use_hazard || id_jump_needs_ex_alu || id_jump_needs_mem_load
val flush = io.jump_flag && !stall
io.pc_stall := stall
io.if2id_stall := stall
io.if2id_flush := flush
io.id2ex_flush := stall
// Lab3(Final) End
}
\end{lstlisting}
\subsubsection{设计要点}
在缩短分支延迟的版本中,由于分支和跳转指令在 ID 段执行,控制单元需要处理以下几种情况:
\begin{enumerate}
\item \textbf{Load-use 冒险}: 当 ID 段的指令需要使用 EX 段 load 指令的结果时,必须阻塞一个周期,等待数据从 MEM 段产生后通过转发获取。
\item \textbf{跳转指令依赖 EX 段 ALU 结果}: 当 ID 段的跳转/分支指令需要使用 EX 段的 ALU 计算结果时,需要阻塞一个周期。虽然 EX 段的结果会在下个周期进入 MEM 段,可以通过转发提供给 ID 段,但由于跳转判断需要在 ID 段完成,因此必须等待一个周期。
\item \textbf{跳转指令依赖 MEM 段 load 结果}: 当 ID 段的跳转/分支指令需要使用 MEM 段 load 指令的结果时,需要阻塞一个周期,等待数据进入 WB 段后通过转发获取。
\item \textbf{控制冒险}: 当跳转确实发生时(\texttt{jump\_flag} 为真且无阻塞),需要清空 IF2ID 流水线寄存器,丢弃已取出的错误路径指令。
\item \textbf{阻塞时插入气泡}: 当发生阻塞时,需要清空 ID2EX 流水线寄存器,在 EX 段插入一条 NOP 指令(气泡),防止 ID 段的指令被重复执行。
\end{enumerate}
\subsection{转发单元Forwarding}
\subsubsection{功能}
转发单元负责检测数据冒险,并生成转发控制信号,使得 EX 或 ID 段可以直接从流水线寄存器中获取所需数据,而不必等待数据写回寄存器组,从而减少流水线阻塞。
\subsubsection{代码实现(最终版本)}
\begin{lstlisting}[caption={转发单元实现(缩短分支延迟版本)}, label={lst:forward_final}]
object ForwardingType {
val NoForward = 0.U(2.W)
val ForwardFromMEM = 1.U(2.W)
val ForwardFromWB = 2.U(2.W)
}
class Forwarding extends Module {
val io = IO(new Bundle() {
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_mem = Input(Bool())
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_wb = Input(Bool())
val reg1_forward_id = Output(UInt(2.W))
val reg2_forward_id = Output(UInt(2.W))
val reg1_forward_ex = Output(UInt(2.W))
val reg2_forward_ex = Output(UInt(2.W))
})
// Lab3(Final)
val ex_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_ex)
val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex)
val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex)
val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex)
io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
val id_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id)
val id_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_id)
val id_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs1 && (io.rd_wb === io.rs1_id)
val id_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs2 && (io.rd_wb === io.rs2_id)
io.reg1_forward_id := Mux(id_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_id := Mux(id_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
// Lab3(Final) End
}
\end{lstlisting}
\subsubsection{设计要点}
转发单元需要同时处理到 EX 段和到 ID 段的转发:
\begin{enumerate}
\item \textbf{EX 段转发}:
\begin{itemize}
\item 如果 EX 段的源寄存器与 MEM 段的目标寄存器相同,从 MEM 段转发。
\item 如果 EX 段的源寄存器与 WB 段的目标寄存器相同,从 WB 段转发。
\item MEM 段转发优先级高于 WB 段转发(保证获取最新的值)。
\end{itemize}
\item \textbf{ID 段转发}:
\begin{itemize}
\item 由于跳转指令在 ID 段执行,需要将 MEM 和 WB 段的结果转发到 ID 段。
\item 如果 ID 段的源寄存器与 MEM 段的目标寄存器相同,从 MEM 段转发。
\item 如果 ID 段的源寄存器与 WB 段的目标寄存器相同(且不与 MEM 段冲突),从 WB 段转发。
\item MEM 段转发优先级同样高于 WB 段转发。
\end{itemize}
\item \textbf{寄存器 x0 的特殊处理}:
\begin{itemize}
\item RISC-V 中寄存器 x0 恒为 0写入 x0 的结果会被丢弃。
\item 因此,转发逻辑中需要检查目标寄存器是否为 0\texttt{rd =/= 0.U}),避免不必要的转发。
\end{itemize}
\end{enumerate}
\subsection{译码单元InstructionDecode}
在缩短分支延迟的版本中,译码单元需要在 ID 段完成分支和跳转指令的执行。
\subsubsection{关键代码}
\begin{lstlisting}[caption={ID 段跳转逻辑}, label={lst:id_jump}]
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val is_jump_instruction = opcode === Instructions.jal || opcode === Instructions.jalr || opcode === InstructionTypes.B
io.ctrl_jump_instruction := is_jump_instruction
val jump_condition_met =
(opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (reg1_data === reg2_data),
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
InstructionsTypeB.bltu -> (reg1_data < reg2_data),
InstructionsTypeB.bgeu -> (reg1_data >= reg2_data)
)
)
val jump_address = Mux(
opcode === Instructions.jalr,
(reg1_data.asSInt + io.ex_immediate.asSInt).asUInt,
(io.instruction_address.asSInt + io.ex_immediate.asSInt).asUInt
) & (~1.U(Parameters.DataWidth)).asUInt
io.if_jump_flag := jump_condition_met || io.interrupt_assert
io.if_jump_address := Mux(
io.interrupt_assert,
io.interrupt_handler_address,
jump_address
)
\end{lstlisting}
\subsubsection{设计要点}
\begin{itemize}
\item 在 ID 段使用转发逻辑获取寄存器数据,确保使用的是最新的值。
\item 根据指令类型jal/jalr/分支)判断跳转条件是否满足。
\item 在 ID 段计算跳转目标地址,无需等到 EX 段。
\item 跳转地址需要与 \texttt{\textasciitilde 1} 进行与运算确保地址为偶数RISC-V 要求)。
\end{itemize}
\section{CSR 指令的冒险分析}
\subsection{数据冒险}
CSRControl and Status Register指令用于读写控制和状态寄存器。在本实验的实现中CSR 指令可能产生以下数据冒险:
\begin{enumerate}
\item \textbf{RAWRead After Write冒险}:
\begin{itemize}
\item 当后续指令需要读取 CSR 指令写入的通用寄存器时,会发生 RAW 冒险。
\item 例如:\texttt{csrrw x1, mstatus, x2} 后跟 \texttt{add x3, x1, x4}
\item 解决方法与普通指令相同通过转发或阻塞解决。CSR 指令在 WB 段将结果写回通用寄存器,可以通过 MEM-EX 和 WB-EX 转发路径提供数据。
\end{itemize}
\item \textbf{CSR 寄存器的 RAW 冒险}:
\begin{itemize}
\item 当连续的 CSR 指令访问同一个 CSR 寄存器时,后续指令可能读取到过时的值。
\item 例如:\texttt{csrrw x1, mstatus, x2} 后跟 \texttt{csrrs x3, mstatus, x4}
\item 本实验未专门处理 CSR 寄存器间的冒险。在实际实现中,可以通过以下方式处理:
\begin{itemize}
\item 检测 CSR 地址冲突,插入阻塞。
\item 为 CSR 单元添加转发逻辑。
\item 简化方案CSR 指令较少出现连续访问,可以通过编译器重排指令避免。
\end{itemize}
\end{itemize}
\end{enumerate}
\subsection{控制冒险}
CSR 指令本身不产生控制冒险(它们不是跳转或分支指令)。但是,某些 CSR 指令(如 \texttt{mret})会改变程序执行流:
\begin{itemize}
\item \texttt{mret} 指令用于从异常处理返回,会跳转到 \texttt{mepc} 寄存器指定的地址。
\item 这类指令在本实验中被当作特殊的跳转指令处理,会触发流水线清空。
\end{itemize}
\subsection{结论}
\begin{itemize}
\item CSR 指令写入通用寄存器的数据冒险可以通过现有的转发和阻塞机制解决。
\item CSR 寄存器间的 RAW 冒险在本实验中未专门处理,实际应用中需要额外的检测和阻塞逻辑。
\item \texttt{mret} 等特殊 CSR 指令产生的控制冒险可以通过流水线清空解决。
\end{itemize}
\section{测试结果}
本实验通过了所有测试用例,包括:
\begin{itemize}
\item \textbf{流水线寄存器测试}: 验证了流水线寄存器的阻塞和清空功能。
\item \textbf{三级流水线 CPU 测试}: 验证了控制冒险的处理,包括递归计算斐波那契数列、快速排序、单字节加载存储等。
\item \textbf{五级流水线阻塞CPU 测试}: 验证了使用阻塞解决数据冒险的正确性。
\item \textbf{五级流水线转发CPU 测试}: 验证了使用转发减少阻塞的优化效果。
\item \textbf{五级流水线缩短分支延迟CPU 测试}: 验证了将跳转提前到 ID 段的优化。
\end{itemize}
所有测试均在 60 秒内完成,共 20 个测试用例全部通过,验证了流水线 CPU 各阶段实现的正确性。
\section{遇到的问题与改进建议}
\subsection{遇到的问题}
\begin{enumerate}[label=\arabic*.]
\item \textbf{问题:转发逻辑的优先级容易混淆。}
在实现转发单元时,需要处理 MEM 段和 WB 段同时满足转发条件的情况。根据流水线原理,应优先使用 MEM 段的数据(更新),但在编写代码时容易写反优先级。
\begin{itemize}
\item \textbf{解决方法}:仔细分析数据流,绘制流水线状态图,明确各阶段数据的新旧关系。使用嵌套的 \texttt{Mux} 语句时,外层 \texttt{Mux} 判断优先级更高的条件。
\end{itemize}
\item \textbf{问题:跳转指令提前到 ID 段后,冒险情况增多。}
将跳转判断从 EX 段提前到 ID 段后,需要考虑 ID 段的跳转指令与 EX、MEM 段指令的依赖关系,冒险检测逻辑变得更加复杂。
\begin{itemize}
\item \textbf{解决方法}:按照实验指导的提示,列出所有可能的冒险组合表格,逐一分析每种情况,确保覆盖所有冒险场景。
\end{itemize}
\item \textbf{问题:调试困难,波形图信号繁多。}
五级流水线 CPU 信号众多,在 GTKWave 中查看波形时很难快速定位错误信号。
\begin{itemize}
\item \textbf{解决方法}:使用 Chisel 的 \texttt{printf} 调试功能,在关键部件(如寄存器文件、控制单元)添加打印语句,输出关键信号的值。结合简单的测试程序(如 \texttt{sb.S}),逐步排查错误。
\end{itemize}
\end{enumerate}
\subsection{改进建议}
\begin{enumerate}[label=\arabic*.]
\item \textbf{建议:提供更多调试案例和方法指导。}
实验指导中的调试部分较为简略,建议增加具体的调试案例,例如如何追踪一条指令在流水线中的完整执行过程,如何分析波形图定位冒险问题等。
\item \textbf{建议:增加可视化工具。}
流水线状态可视化对理解和调试非常有帮助。建议提供或推荐一些工具,能够将流水线各阶段的指令和数据流以图形化方式展示。
\item \textbf{建议:补充 CSR 指令冒险处理的说明。}
实验指导中未详细讨论 CSR 指令的冒险处理,建议在后续版本中补充相关内容,或明确说明本实验中 CSR 指令的简化假设。
\end{enumerate}
\section{实验结论}
通过本次实验,我成功实现了三级和五级流水线 CPU深入理解了流水线技术和竞争冒险的处理方法。在实现过程中我掌握了
\begin{itemize}
\item 流水线寄存器的设计与实现。
\item 控制冒险的检测与清空机制。
\item 数据冒险的阻塞和转发解决方案。
\item 分支延迟优化技术(将跳转提前到 ID 段)。
\end{itemize}
通过编写和分析测试用例,我学会了如何验证流水线 CPU 的正确性,并掌握了使用打印和波形图进行调试的方法。本次实验使我对计算机组成原理中的流水线技术有了更深入的实践理解,为后续更复杂的处理器设计奠定了坚实的基础。
\end{document}

BIN
lab3/朱梓涵24325356.rar Normal file

Binary file not shown.

View File

@@ -0,0 +1,69 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util._
import riscv.Parameters
object ALUFunctions extends ChiselEnum {
val zero, add, sub, sll, slt, xor, or, and, srl, sra, sltu = Value
}
class ALU extends Module {
val io = IO(new Bundle {
val func = Input(ALUFunctions())
val op1 = Input(UInt(Parameters.DataWidth))
val op2 = Input(UInt(Parameters.DataWidth))
val result = Output(UInt(Parameters.DataWidth))
})
io.result := 0.U
switch(io.func) {
is(ALUFunctions.add) {
io.result := io.op1 + io.op2
}
is(ALUFunctions.sub) {
io.result := io.op1 - io.op2
}
is(ALUFunctions.sll) {
io.result := io.op1 << io.op2(4, 0)
}
is(ALUFunctions.slt) {
io.result := io.op1.asSInt < io.op2.asSInt
}
is(ALUFunctions.xor) {
io.result := io.op1 ^ io.op2
}
is(ALUFunctions.or) {
io.result := io.op1 | io.op2
}
is(ALUFunctions.and) {
io.result := io.op1 & io.op2
}
is(ALUFunctions.srl) {
io.result := io.op1 >> io.op2(4, 0)
}
is(ALUFunctions.sra) {
io.result := (io.op1.asSInt >> io.op2(4, 0)).asUInt
}
is(ALUFunctions.sltu) {
io.result := io.op1 < io.op2
}
}
}

View File

@@ -0,0 +1,87 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.core.threestage.{InstructionTypes, Instructions, InstructionsTypeI, InstructionsTypeR}
class ALUControl extends Module {
val io = IO(new Bundle {
val opcode = Input(UInt(7.W))
val funct3 = Input(UInt(3.W))
val funct7 = Input(UInt(7.W))
val alu_funct = Output(ALUFunctions())
})
io.alu_funct := ALUFunctions.zero
switch(io.opcode) {
is(InstructionTypes.I) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeI.addi -> ALUFunctions.add,
InstructionsTypeI.slli -> ALUFunctions.sll,
InstructionsTypeI.slti -> ALUFunctions.slt,
InstructionsTypeI.sltiu -> ALUFunctions.sltu,
InstructionsTypeI.xori -> ALUFunctions.xor,
InstructionsTypeI.ori -> ALUFunctions.or,
InstructionsTypeI.andi -> ALUFunctions.and,
InstructionsTypeI.sri -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.RM) {
io.alu_funct := MuxLookup(
io.funct3,
ALUFunctions.zero,
IndexedSeq(
InstructionsTypeR.add_sub -> Mux(io.funct7(5), ALUFunctions.sub, ALUFunctions.add),
InstructionsTypeR.sll -> ALUFunctions.sll,
InstructionsTypeR.slt -> ALUFunctions.slt,
InstructionsTypeR.sltu -> ALUFunctions.sltu,
InstructionsTypeR.xor -> ALUFunctions.xor,
InstructionsTypeR.or -> ALUFunctions.or,
InstructionsTypeR.and -> ALUFunctions.and,
InstructionsTypeR.sr -> Mux(io.funct7(5), ALUFunctions.sra, ALUFunctions.srl)
),
)
}
is(InstructionTypes.B) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.L) {
io.alu_funct := ALUFunctions.add
}
is(InstructionTypes.S) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jal) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.jalr) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.lui) {
io.alu_funct := ALUFunctions.add
}
is(Instructions.auipc) {
io.alu_funct := ALUFunctions.add
}
}
}

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import riscv.ImplementationType
import riscv.core.fivestage_final.{CPU => FiveStageCPUFinal}
import riscv.core.fivestage_forward.{CPU => FiveStageCPUForward}
import riscv.core.fivestage_stall.{CPU => FiveStageCPUStall}
import riscv.core.threestage.{CPU => ThreeStageCPU}
class CPU(val implementation: Int = ImplementationType.FiveStageFinal) extends Module {
val io = IO(new CPUBundle)
implementation match {
case ImplementationType.ThreeStage =>
val cpu = Module(new ThreeStageCPU)
cpu.io <> io
case ImplementationType.FiveStageStall =>
val cpu = Module(new FiveStageCPUStall)
cpu.io <> io
case ImplementationType.FiveStageForward =>
val cpu = Module(new FiveStageCPUForward)
cpu.io <> io
case _ =>
val cpu = Module(new FiveStageCPUFinal)
cpu.io <> io
}
}

View File

@@ -0,0 +1,30 @@
// Copyright 2022 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import peripheral.RAMBundle
import riscv.Parameters
class CPUBundle extends Bundle {
val instruction_address = Output(UInt(Parameters.AddrWidth))
val instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val memory_bundle = Flipped(new RAMBundle)
val device_select = Output(UInt(Parameters.SlaveDeviceCountBits.W))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
}

View File

@@ -0,0 +1,99 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
import riscv.core.threestage.CSRDirectAccessBundle
object CSRRegister {
// Refer to Spec. Vol.II Page 8-10
val MSTATUS = 0x300.U(Parameters.CSRRegisterAddrWidth)
val MIE = 0x304.U(Parameters.CSRRegisterAddrWidth)
val MTVEC = 0x305.U(Parameters.CSRRegisterAddrWidth)
val MSCRATCH = 0x340.U(Parameters.CSRRegisterAddrWidth)
val MEPC = 0x341.U(Parameters.CSRRegisterAddrWidth)
val MCAUSE = 0x342.U(Parameters.CSRRegisterAddrWidth)
val CycleL = 0xc00.U(Parameters.CSRRegisterAddrWidth)
val CycleH = 0xc80.U(Parameters.CSRRegisterAddrWidth)
}
class CSR extends Module {
val io = IO(new Bundle {
val reg_read_address_id = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_enable_ex = Input(Bool())
val reg_write_address_ex = Input(UInt(Parameters.CSRRegisterAddrWidth))
val reg_write_data_ex = Input(UInt(Parameters.DataWidth))
val id_reg_read_data = Output(UInt(Parameters.DataWidth))
val clint_access_bundle = Flipped(new CSRDirectAccessBundle)
})
val mstatus = RegInit(UInt(Parameters.DataWidth), 0.U)
val mie = RegInit(UInt(Parameters.DataWidth), 0.U)
val mtvec = RegInit(UInt(Parameters.DataWidth), 0.U)
val mscratch = RegInit(UInt(Parameters.DataWidth), 0.U)
val mepc = RegInit(UInt(Parameters.DataWidth), 0.U)
val mcause = RegInit(UInt(Parameters.DataWidth), 0.U)
val cycles = RegInit(UInt(64.W), 0.U)
val regLUT =
IndexedSeq(
CSRRegister.MSTATUS -> mstatus,
CSRRegister.MIE -> mie,
CSRRegister.MTVEC -> mtvec,
CSRRegister.MSCRATCH -> mscratch,
CSRRegister.MEPC -> mepc,
CSRRegister.MCAUSE -> mcause,
CSRRegister.CycleL -> cycles(31, 0),
CSRRegister.CycleH -> cycles(63, 32),
)
cycles := cycles + 1.U
// If the pipeline and the CLINT are going to read and write the CSR at the same time, let the pipeline write first.
// This is implemented in a single cycle by passing reg_write_data_ex to clint and writing the data from the CLINT to the CSR.
io.id_reg_read_data := MuxLookup(io.reg_read_address_id, 0.U, regLUT)
io.clint_access_bundle.mstatus := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MSTATUS, io.reg_write_data_ex, mstatus)
io.clint_access_bundle.mtvec := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MTVEC, io.reg_write_data_ex, mtvec)
io.clint_access_bundle.mcause := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MCAUSE, io.reg_write_data_ex, mcause)
io.clint_access_bundle.mepc := Mux(io.reg_write_enable_ex && io.reg_write_address_ex === CSRRegister.MEPC, io.reg_write_data_ex, mepc)
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_ex) {
when(io.reg_write_address_ex === CSRRegister.MSTATUS) {
mstatus := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_ex === CSRRegister.MEPC) {
mepc := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_ex === CSRRegister.MCAUSE) {
mcause := io.reg_write_data_ex
}
}
when(io.reg_write_enable_ex) {
when(io.reg_write_address_ex === CSRRegister.MIE) {
mie := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_ex === CSRRegister.MTVEC) {
mtvec := io.reg_write_data_ex
}.elsewhen(io.reg_write_address_ex === CSRRegister.MSCRATCH) {
mscratch := io.reg_write_data_ex
}
}
}

View File

@@ -0,0 +1,39 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import riscv.Parameters
class PipelineRegister(width: Int = Parameters.DataBits, defaultValue: UInt = 0.U) extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val in = Input(UInt(width.W))
val out = Output(UInt(width.W))
})
// Lab3(PipelineRegister)
val register = RegInit(defaultValue)
when(io.flush) {
register := defaultValue
}.elsewhen(io.stall) {
}.otherwise {
register := io.in
}
io.out := register
// Lab3(PipelineRegister) End
}

View File

@@ -0,0 +1,78 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core
import chisel3._
import chisel3.util._
import riscv.Parameters
object Registers extends Enumeration {
type Register = Value
val zero,
ra, sp, gp, tp,
t0, t1, t2, fp,
s1,
a0, a1, a2, a3, a4, a5, a6, a7,
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11,
t3, t4, t5, t6 = Value
}
class RegisterFile extends Module {
val io = IO(new Bundle {
val write_enable = Input(Bool())
val write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val write_data = Input(UInt(Parameters.DataWidth))
val read_address1 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_address2 = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val read_data1 = Output(UInt(Parameters.DataWidth))
val read_data2 = Output(UInt(Parameters.DataWidth))
val debug_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val debug_read_data = Output(UInt(Parameters.DataWidth))
})
val registers = Reg(Vec(Parameters.PhysicalRegisters, UInt(Parameters.DataWidth)))
when(!reset.asBool) {
when(io.write_enable && io.write_address =/= 0.U) {
registers(io.write_address) := io.write_data
}
}
io.read_data1 := MuxCase(
registers(io.read_address1),
IndexedSeq(
(io.read_address1 === 0.U) -> 0.U,
(io.read_address1 === io.write_address && io.write_enable) -> io.write_data
)
)
io.read_data2 := MuxCase(
registers(io.read_address2),
IndexedSeq(
(io.read_address2 === 0.U) -> 0.U,
(io.read_address2 === io.write_address && io.write_enable) -> io.write_data
)
)
io.debug_read_data := MuxCase(
registers(io.debug_read_address),
IndexedSeq(
(io.debug_read_address === 0.U) -> 0.U,
(io.debug_read_address === io.write_address && io.write_enable) -> io.write_data
)
)
}

View File

@@ -0,0 +1,101 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data = Output(UInt(Parameters.DataWidth))
val mepc_write_data = Output(UInt(Parameters.DataWidth))
val mcause_write_data = Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction_id = Input(UInt(Parameters.InstructionWidth))
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val id_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val id_interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
io.instruction_address_if,
)
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
when(io.instruction_id === InstructionsEnv.ecall || io.instruction_id === InstructionsEnv.ebreak) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := MuxLookup(
io.instruction_id,
10.U,
IndexedSeq(
InstructionsEnv.ecall -> 11.U,
InstructionsEnv.ebreak -> 3.U,
)
)
io.csr_bundle.direct_write_enable := true.B
io.id_interrupt_assert := true.B
io.id_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
io.csr_bundle.direct_write_enable := true.B
io.id_interrupt_assert := true.B
io.id_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.instruction_id === InstructionsRet.mret) {
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := true.B
io.id_interrupt_assert := true.B
io.id_interrupt_handler_address := io.csr_bundle.mepc
}.otherwise {
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := false.B
io.id_interrupt_assert := false.B
io.id_interrupt_handler_address := 0.U
}
}

View File

@@ -0,0 +1,169 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
import riscv.core.{CPUBundle, CSR, RegisterFile}
class CPU extends Module {
val io = IO(new CPUBundle)
val ctrl = Module(new Control)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val if2id = Module(new IF2ID)
val id = Module(new InstructionDecode)
val id2ex = Module(new ID2EX)
val ex = Module(new Execute)
val ex2mem = Module(new EX2MEM)
val mem = Module(new MemoryAccess)
val mem2wb = Module(new MEM2WB)
val wb = Module(new WriteBack)
val forwarding = Module(new Forwarding)
val clint = Module(new CLINT)
val csr_regs = Module(new CSR)
ctrl.io.jump_flag := id.io.if_jump_flag
ctrl.io.jump_instruction_id := id.io.ctrl_jump_instruction
ctrl.io.rs1_id := id.io.regs_reg1_read_address
ctrl.io.rs2_id := id.io.regs_reg2_read_address
ctrl.io.memory_read_enable_ex := id2ex.io.output_memory_read_enable
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
ctrl.io.memory_read_enable_mem := ex2mem.io.output_memory_read_enable
ctrl.io.rd_mem := ex2mem.io.output_regs_write_address
regs.io.write_enable := mem2wb.io.output_regs_write_enable
regs.io.write_address := mem2wb.io.output_regs_write_address
regs.io.write_data := wb.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
regs.io.debug_read_address := io.debug_read_address
io.debug_read_data := regs.io.debug_read_data
io.instruction_address := inst_fetch.io.instruction_address
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
inst_fetch.io.jump_flag_id := id.io.if_jump_flag
inst_fetch.io.jump_address_id := id.io.if_jump_address
inst_fetch.io.rom_instruction := io.instruction
inst_fetch.io.instruction_valid := io.instruction_valid
if2id.io.stall := ctrl.io.if2id_stall
if2id.io.flush := ctrl.io.if2id_flush
if2id.io.instruction := inst_fetch.io.id_instruction
if2id.io.instruction_address := inst_fetch.io.instruction_address
if2id.io.interrupt_flag := io.interrupt_flag
id.io.instruction := if2id.io.output_instruction
id.io.instruction_address := if2id.io.output_instruction_address
id.io.reg1_data := regs.io.read_data1
id.io.reg2_data := regs.io.read_data2
id.io.forward_from_mem := mem.io.forward_data
id.io.forward_from_wb := wb.io.regs_write_data
id.io.reg1_forward := forwarding.io.reg1_forward_id
id.io.reg2_forward := forwarding.io.reg2_forward_id
id.io.interrupt_assert := clint.io.id_interrupt_assert
id.io.interrupt_handler_address := clint.io.id_interrupt_handler_address
id2ex.io.flush := ctrl.io.id2ex_flush
id2ex.io.instruction := if2id.io.output_instruction
id2ex.io.instruction_address := if2id.io.output_instruction_address
id2ex.io.reg1_data := regs.io.read_data1
id2ex.io.reg2_data := regs.io.read_data2
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
id2ex.io.regs_write_address := id.io.ex_reg_write_address
id2ex.io.regs_write_source := id.io.ex_reg_write_source
id2ex.io.immediate := id.io.ex_immediate
id2ex.io.aluop1_source := id.io.ex_aluop1_source
id2ex.io.aluop2_source := id.io.ex_aluop2_source
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
id2ex.io.csr_address := id.io.ex_csr_address
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
ex.io.instruction := id2ex.io.output_instruction
ex.io.instruction_address := id2ex.io.output_instruction_address
ex.io.reg1_data := id2ex.io.output_reg1_data
ex.io.reg2_data := id2ex.io.output_reg2_data
ex.io.immediate := id2ex.io.output_immediate
ex.io.aluop1_source := id2ex.io.output_aluop1_source
ex.io.aluop2_source := id2ex.io.output_aluop2_source
ex.io.csr_read_data := id2ex.io.output_csr_read_data
ex.io.forward_from_mem := mem.io.forward_data
ex.io.forward_from_wb := wb.io.regs_write_data
ex.io.reg1_forward := forwarding.io.reg1_forward_ex
ex.io.reg2_forward := forwarding.io.reg2_forward_ex
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
ex2mem.io.reg2_data := ex.io.mem_reg2_data
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
ex2mem.io.alu_result := ex.io.mem_alu_result
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
mem.io.alu_result := ex2mem.io.output_alu_result
mem.io.reg2_data := ex2mem.io.output_reg2_data
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
mem.io.funct3 := ex2mem.io.output_funct3
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
io.memory_bundle <> mem.io.bundle
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
mem2wb.io.alu_result := ex2mem.io.output_alu_result
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
wb.io.instruction_address := mem2wb.io.output_instruction_address
wb.io.alu_result := mem2wb.io.output_alu_result
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
forwarding.io.rs1_id := id.io.regs_reg1_read_address
forwarding.io.rs2_id := id.io.regs_reg2_read_address
forwarding.io.rs1_ex := id2ex.io.output_regs_reg1_read_address
forwarding.io.rs2_ex := id2ex.io.output_regs_reg2_read_address
forwarding.io.rd_mem := ex2mem.io.output_regs_write_address
forwarding.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
forwarding.io.rd_wb := mem2wb.io.output_regs_write_address
forwarding.io.reg_write_enable_wb := mem2wb.io.output_regs_write_enable
clint.io.instruction_address_if := inst_fetch.io.instruction_address
clint.io.instruction_id := if2id.io.output_instruction
clint.io.jump_flag := id.io.clint_jump_flag
clint.io.jump_address := id.io.clint_jump_address
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
}

View File

@@ -0,0 +1,62 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
class Control extends Module {
val io = IO(new Bundle {
val jump_flag = Input(Bool())
val jump_instruction_id = Input(Bool())
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_ex = Input(Bool())
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_mem = Input(Bool())
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
val pc_stall = Output(Bool())
val if2id_stall = Output(Bool())
})
// Lab3(Final)
val stall = Wire(Bool())
val load_use_hazard = io.memory_read_enable_ex && io.rd_ex =/= 0.U &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_ex_alu = io.jump_instruction_id && io.rd_ex =/= 0.U &&
!io.memory_read_enable_ex &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_mem_load = io.jump_instruction_id && io.memory_read_enable_mem && io.rd_mem =/= 0.U &&
(io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
stall := load_use_hazard || id_jump_needs_ex_alu || id_jump_needs_mem_load
val flush = io.jump_flag && !stall
io.pc_stall := stall
io.if2id_stall := stall
io.if2id_flush := flush
io.id2ex_flush := stall
// Lab3(Final) End
}

View File

@@ -0,0 +1,108 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class EX2MEM extends Module {
val io = IO(new Bundle() {
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val funct3 = Input(UInt(3.W))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val alu_result = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_funct3 = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val funct3 = Module(new PipelineRegister(3))
funct3.io.in := io.funct3
funct3.io.stall := stall
funct3.io.flush := flush
io.output_funct3 := funct3.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := flush
io.output_reg2_data := reg2_data.io.out
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,93 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util._
import riscv.Parameters
import riscv.core.{ALU, ALUControl}
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val forward_from_mem = Input(UInt(Parameters.DataWidth))
val forward_from_wb = Input(UInt(Parameters.DataWidth))
val reg1_forward = Input(UInt(2.W))
val reg2_forward = Input(UInt(2.W))
val mem_alu_result = Output(UInt(Parameters.DataWidth))
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
val csr_write_data = Output(UInt(Parameters.DataWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val uimm = io.instruction(19, 15)
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
alu.io.func := alu_ctrl.io.alu_funct
val reg1_data = MuxLookup(
io.reg1_forward,
io.reg1_data,
IndexedSeq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
alu.io.op1 := Mux(
io.aluop1_source === ALUOp1Source.InstructionAddress,
io.instruction_address,
reg1_data
)
val reg2_data = MuxLookup(
io.reg2_forward,
io.reg2_data,
IndexedSeq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
alu.io.op2 := Mux(
io.aluop2_source === ALUOp2Source.Immediate,
io.immediate,
reg2_data
)
io.mem_alu_result := alu.io.result
io.mem_reg2_data := reg2_data
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
InstructionsTypeCSR.csrrw -> reg1_data,
InstructionsTypeCSR.csrrc -> io.csr_read_data.&((~reg1_data).asUInt),
InstructionsTypeCSR.csrrs -> io.csr_read_data.|(reg1_data),
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
InstructionsTypeCSR.csrrci -> io.csr_read_data.&((~Cat(0.U(27.W), uimm)).asUInt),
InstructionsTypeCSR.csrrsi -> io.csr_read_data.|(Cat(0.U(27.W), uimm)),
))
}

View File

@@ -0,0 +1,67 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
object ForwardingType {
val NoForward = 0.U(2.W)
val ForwardFromMEM = 1.U(2.W)
val ForwardFromWB = 2.U(2.W)
}
class Forwarding extends Module {
val io = IO(new Bundle() {
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_mem = Input(Bool())
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_wb = Input(Bool())
val reg1_forward_id = Output(UInt(2.W))
val reg2_forward_id = Output(UInt(2.W))
val reg1_forward_ex = Output(UInt(2.W))
val reg2_forward_ex = Output(UInt(2.W))
})
// Lab3(Final)
val ex_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_ex)
val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex)
val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex)
val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex)
io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
val id_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id)
val id_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_id)
val id_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs1 && (io.rd_wb === io.rs1_id)
val id_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs2 && (io.rd_wb === io.rs2_id)
io.reg1_forward_id := Mux(id_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_id := Mux(id_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
// Lab3(Final) End
}

View File

@@ -0,0 +1,163 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class ID2EX extends Module {
val io = IO(new Bundle {
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_enable = Input(Bool())
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_source = Input(UInt(2.W))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_write_enable = Input(Bool())
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_source = Output(UInt(2.W))
val output_reg1_data = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_immediate = Output(UInt(Parameters.DataWidth))
val output_aluop1_source = Output(UInt(1.W))
val output_aluop2_source = Output(UInt(1.W))
val output_csr_write_enable = Output(Bool())
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg1_read_address.io.in := io.regs_reg1_read_address
regs_reg1_read_address.io.stall := stall
regs_reg1_read_address.io.flush := io.flush
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg2_read_address.io.in := io.regs_reg2_read_address
regs_reg2_read_address.io.stall := stall
regs_reg2_read_address.io.flush := io.flush
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := io.flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := io.flush
io.output_regs_write_address := regs_write_address.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := io.flush
io.output_regs_write_source := regs_write_source.io.out
val reg1_data = Module(new PipelineRegister())
reg1_data.io.in := io.reg1_data
reg1_data.io.stall := stall
reg1_data.io.flush := io.flush
io.output_reg1_data := reg1_data.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := io.flush
io.output_reg2_data := reg2_data.io.out
val immediate = Module(new PipelineRegister())
immediate.io.in := io.immediate
immediate.io.stall := stall
immediate.io.flush := io.flush
io.output_immediate := immediate.io.out
val aluop1_source = Module(new PipelineRegister(1))
aluop1_source.io.in := io.aluop1_source
aluop1_source.io.stall := stall
aluop1_source.io.flush := io.flush
io.output_aluop1_source := aluop1_source.io.out
val aluop2_source = Module(new PipelineRegister(1))
aluop2_source.io.in := io.aluop2_source
aluop2_source.io.stall := stall
aluop2_source.io.flush := io.flush
io.output_aluop2_source := aluop2_source.io.out
val csr_write_enable = Module(new PipelineRegister(1))
csr_write_enable.io.in := io.csr_write_enable
csr_write_enable.io.stall := stall
csr_write_enable.io.flush := io.flush
io.output_csr_write_enable := csr_write_enable.io.out
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
csr_address.io.in := io.csr_address
csr_address.io.stall := stall
csr_address.io.flush := io.flush
io.output_csr_address := csr_address.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := io.flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := io.flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := io.flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,51 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class IF2ID extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
})
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := io.stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := io.stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
interrupt_flag.io.in := io.interrupt_flag
interrupt_flag.io.stall := io.stall
interrupt_flag.io.flush := io.flush
io.output_interrupt_flag := interrupt_flag.io.out
}

View File

@@ -0,0 +1,274 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val forward_from_mem = Input(UInt(Parameters.DataWidth))
val forward_from_wb = Input(UInt(Parameters.DataWidth))
val reg1_forward = Input(UInt(2.W))
val reg2_forward = Input(UInt(2.W))
val interrupt_assert = Input(Bool())
val interrupt_handler_address = Input(UInt(Parameters.AddrWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(UInt(1.W))
val ex_aluop2_source = Output(UInt(1.W))
val ex_memory_read_enable = Output(Bool())
val ex_memory_write_enable = Output(Bool())
val ex_reg_write_source = Output(UInt(2.W))
val ex_reg_write_enable = Output(Bool())
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val ex_csr_write_enable = Output(Bool())
val ctrl_jump_instruction = Output(Bool())
val clint_jump_flag = Output(Bool())
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.AddrWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
// Lab3(Final) ID rs
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
// Lab3(Final) ID rs End
io.ex_immediate := MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
io.ex_aluop2_source := Mux(
opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.ex_memory_read_enable := opcode === InstructionTypes.L
io.ex_memory_write_enable := opcode === InstructionTypes.S
io.ex_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult,
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.csr -> RegWriteSource.CSR,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
// Lab3(Final) ID rd
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
opcode === Instructions.jalr || opcode === Instructions.csr
io.ex_reg_write_enable := rd_used
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
// Lab3(Final) ID rd End
io.ex_csr_address := io.instruction(31, 20)
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
)
// Lab3(Final)
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val is_jump_instruction = opcode === Instructions.jal || opcode === Instructions.jalr || opcode === InstructionTypes.B
io.ctrl_jump_instruction := is_jump_instruction
val jump_condition_met =
(opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (reg1_data === reg2_data),
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
InstructionsTypeB.bltu -> (reg1_data < reg2_data),
InstructionsTypeB.bgeu -> (reg1_data >= reg2_data)
)
)
val jump_address = Mux(
opcode === Instructions.jalr,
(reg1_data.asSInt + io.ex_immediate.asSInt).asUInt,
(io.instruction_address.asSInt + io.ex_immediate.asSInt).asUInt
) & (~1.U(Parameters.DataWidth)).asUInt // Ensure address is even
io.clint_jump_flag := jump_condition_met
io.clint_jump_address := jump_address
io.if_jump_flag := jump_condition_met || io.interrupt_assert
io.if_jump_address := Mux(
io.interrupt_assert,
io.interrupt_handler_address,
jump_address
)
// Lab3(Final) End
}

View File

@@ -0,0 +1,48 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util.MuxCase
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val stall_flag_ctrl = Input(Bool())
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val rom_instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val id_instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
pc := MuxCase(
pc + 4.U,
IndexedSeq(
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
)
)
io.instruction_address := pc
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
}

View File

@@ -0,0 +1,83 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class MEM2WB extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_data = Module(new PipelineRegister())
memory_read_data.io.in := io.memory_read_data
memory_read_data.io.stall := stall
memory_read_data.io.flush := flush
io.output_memory_read_data := memory_read_data.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,109 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
class MemoryAccess extends Module {
val io = IO(new Bundle() {
val alu_result = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val funct3 = Input(UInt(3.W))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
val forward_data = Output(UInt(Parameters.DataWidth))
val bundle = Flipped(new RAMBundle)
})
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
io.bundle.write_enable := io.memory_write_enable
io.bundle.write_data := 0.U
io.bundle.address := io.alu_result
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.wb_memory_read_data := 0.U
when(io.memory_read_enable) {
val data = io.bundle.read_data
io.wb_memory_read_data := MuxLookup(
io.funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable) {
io.bundle.write_data := io.reg2_data
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(io.funct3 === InstructionsTypeS.sb) {
io.bundle.write_strobe(mem_address_index) := true.B
io.bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
}
}
io.forward_data := Mux(io.regs_write_source === RegWriteSource.CSR, io.csr_read_data, io.alu_result)
}

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_final
import chisel3._
import chisel3.util._
import riscv.Parameters
class WriteBack extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_data = Output(UInt(Parameters.DataWidth))
})
io.regs_write_data := MuxLookup(
io.regs_write_source,
io.alu_result,
IndexedSeq(
RegWriteSource.Memory -> io.memory_read_data,
RegWriteSource.CSR -> io.csr_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
)
)
}

View File

@@ -0,0 +1,103 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data = Output(UInt(Parameters.DataWidth))
val mepc_write_data = Output(UInt(Parameters.DataWidth))
val mcause_write_data = Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val ex_interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
)
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
when(io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := MuxLookup(
io.instruction_ex,
10.U,
IndexedSeq(
InstructionsEnv.ecall -> 11.U,
InstructionsEnv.ebreak -> 3.U,
)
)
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.instruction_ex === InstructionsRet.mret) {
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mepc
}.otherwise {
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := false.B
io.ex_interrupt_assert := false.B
io.ex_interrupt_handler_address := 0.U
}
}

View File

@@ -0,0 +1,158 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
import riscv.core.{CPUBundle, CSR, RegisterFile}
class CPU extends Module {
val io = IO(new CPUBundle)
val ctrl = Module(new Control)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val if2id = Module(new IF2ID)
val id = Module(new InstructionDecode)
val id2ex = Module(new ID2EX)
val ex = Module(new Execute)
val ex2mem = Module(new EX2MEM)
val mem = Module(new MemoryAccess)
val mem2wb = Module(new MEM2WB)
val wb = Module(new WriteBack)
val forwarding = Module(new Forwarding)
val clint = Module(new CLINT)
val csr_regs = Module(new CSR)
ctrl.io.jump_flag := ex.io.if_jump_flag
ctrl.io.rs1_id := id.io.regs_reg1_read_address
ctrl.io.rs2_id := id.io.regs_reg2_read_address
ctrl.io.memory_read_enable_ex := id2ex.io.output_memory_read_enable
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
regs.io.write_enable := mem2wb.io.output_regs_write_enable
regs.io.write_address := mem2wb.io.output_regs_write_address
regs.io.write_data := wb.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
regs.io.debug_read_address := io.debug_read_address
io.debug_read_data := regs.io.debug_read_data
io.instruction_address := inst_fetch.io.instruction_address
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
inst_fetch.io.jump_address_id := ex.io.if_jump_address
inst_fetch.io.rom_instruction := io.instruction
inst_fetch.io.instruction_valid := io.instruction_valid
if2id.io.stall := ctrl.io.if2id_stall
if2id.io.flush := ctrl.io.if2id_flush
if2id.io.instruction := inst_fetch.io.id_instruction
if2id.io.instruction_address := inst_fetch.io.instruction_address
if2id.io.interrupt_flag := io.interrupt_flag
id.io.instruction := if2id.io.output_instruction
id2ex.io.flush := ctrl.io.id2ex_flush
id2ex.io.instruction := if2id.io.output_instruction
id2ex.io.instruction_address := if2id.io.output_instruction_address
id2ex.io.reg1_data := regs.io.read_data1
id2ex.io.reg2_data := regs.io.read_data2
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
id2ex.io.regs_write_address := id.io.ex_reg_write_address
id2ex.io.regs_write_source := id.io.ex_reg_write_source
id2ex.io.immediate := id.io.ex_immediate
id2ex.io.aluop1_source := id.io.ex_aluop1_source
id2ex.io.aluop2_source := id.io.ex_aluop2_source
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
id2ex.io.csr_address := id.io.ex_csr_address
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
ex.io.instruction := id2ex.io.output_instruction
ex.io.instruction_address := id2ex.io.output_instruction_address
ex.io.reg1_data := id2ex.io.output_reg1_data
ex.io.reg2_data := id2ex.io.output_reg2_data
ex.io.immediate_id := id2ex.io.output_immediate
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
ex.io.csr_read_data_id := id2ex.io.output_csr_read_data
ex.io.forward_from_mem := mem.io.forward_data
ex.io.forward_from_wb := wb.io.regs_write_data
ex.io.reg1_forward := forwarding.io.reg1_forward_ex
ex.io.reg2_forward := forwarding.io.reg2_forward_ex
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
ex2mem.io.reg2_data := ex.io.mem_reg2_data
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
ex2mem.io.alu_result := ex.io.mem_alu_result
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
mem.io.alu_result := ex2mem.io.output_alu_result
mem.io.reg2_data := ex2mem.io.output_reg2_data
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
mem.io.funct3 := ex2mem.io.output_funct3
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
io.memory_bundle <> mem.io.bundle
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
mem2wb.io.alu_result := ex2mem.io.output_alu_result
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
wb.io.instruction_address := mem2wb.io.output_instruction_address
wb.io.alu_result := mem2wb.io.output_alu_result
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
forwarding.io.rs1_ex := id2ex.io.output_regs_reg1_read_address
forwarding.io.rs2_ex := id2ex.io.output_regs_reg2_read_address
forwarding.io.rd_mem := ex2mem.io.output_regs_write_address
forwarding.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
forwarding.io.rd_wb := mem2wb.io.output_regs_write_address
forwarding.io.reg_write_enable_wb := mem2wb.io.output_regs_write_enable
clint.io.instruction_address_if := inst_fetch.io.instruction_address
clint.io.instruction_address_id := if2id.io.output_instruction_address
clint.io.instruction_ex := id2ex.io.output_instruction
clint.io.jump_flag := ex.io.clint_jump_flag
clint.io.jump_address := ex.io.clint_jump_address
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
}

View File

@@ -0,0 +1,44 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
class Control extends Module {
val io = IO(new Bundle {
val jump_flag = Input(Bool())
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_ex = Input(Bool())
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
val pc_stall = Output(Bool())
val if2id_stall = Output(Bool())
})
// Lab3(Forward)
val load_use_hazard = io.memory_read_enable_ex &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id) &&
io.rd_ex =/= 0.U
val flush = io.jump_flag
io.pc_stall := load_use_hazard && !flush
io.if2id_stall := load_use_hazard && !flush
io.if2id_flush := flush
io.id2ex_flush := flush || load_use_hazard
// Lab3(Forward) End
}

View File

@@ -0,0 +1,108 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class EX2MEM extends Module {
val io = IO(new Bundle() {
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val funct3 = Input(UInt(3.W))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val alu_result = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_funct3 = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val funct3 = Module(new PipelineRegister(3))
funct3.io.in := io.funct3
funct3.io.stall := stall
funct3.io.flush := flush
io.output_funct3 := funct3.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := flush
io.output_reg2_data := reg2_data.io.out
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,121 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util._
import riscv.Parameters
import riscv.core.{ALU, ALUControl}
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate_id = Input(UInt(Parameters.DataWidth))
val aluop1_source_id = Input(UInt(1.W))
val aluop2_source_id = Input(UInt(1.W))
val csr_read_data_id = Input(UInt(Parameters.DataWidth))
val forward_from_mem = Input(UInt(Parameters.DataWidth))
val forward_from_wb = Input(UInt(Parameters.DataWidth))
val reg1_forward = Input(UInt(2.W))
val reg2_forward = Input(UInt(2.W))
val interrupt_assert_clint = Input(Bool())
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
val mem_alu_result = Output(UInt(Parameters.DataWidth))
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
val csr_write_data = Output(UInt(Parameters.DataWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.AddrWidth))
val clint_jump_flag = Output(Bool())
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val uimm = io.instruction(19, 15)
// ALU compute
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
alu.io.func := alu_ctrl.io.alu_funct
// Lab3(Forward)
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
// Lab3(Forward) End
alu.io.op1 := Mux(
io.aluop1_source_id === ALUOp1Source.InstructionAddress,
io.instruction_address,
reg1_data
)
alu.io.op2 := Mux(
io.aluop2_source_id === ALUOp2Source.Immediate,
io.immediate_id,
reg2_data
)
io.mem_alu_result := alu.io.result
io.mem_reg2_data := reg2_data
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
InstructionsTypeCSR.csrrw -> reg1_data,
InstructionsTypeCSR.csrrc -> io.csr_read_data_id.&((~reg1_data).asUInt),
InstructionsTypeCSR.csrrs -> io.csr_read_data_id.|(reg1_data),
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
InstructionsTypeCSR.csrrci -> io.csr_read_data_id.&((~Cat(0.U(27.W), uimm)).asUInt),
InstructionsTypeCSR.csrrsi -> io.csr_read_data_id.|(Cat(0.U(27.W), uimm)),
))
// jump and interrupt
val instruction_jump_flag = (opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (reg1_data === reg2_data),
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
InstructionsTypeB.bltu -> (reg1_data.asUInt < reg2_data.asUInt),
InstructionsTypeB.bgeu -> (reg1_data.asUInt >= reg2_data.asUInt)
)
)
io.clint_jump_flag := instruction_jump_flag
io.clint_jump_address := alu.io.result
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
io.if_jump_address := Mux(io.interrupt_assert_clint,
io.interrupt_handler_address_clint,
alu.io.result
)
}

View File

@@ -0,0 +1,56 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
object ForwardingType {
val NoForward = 0.U(2.W)
val ForwardFromMEM = 1.U(2.W)
val ForwardFromWB = 2.U(2.W)
}
class Forwarding extends Module {
val io = IO(new Bundle() {
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_mem = Input(Bool())
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_wb = Input(Bool())
// Forwarding Type
val reg1_forward_ex = Output(UInt(2.W))
val reg2_forward_ex = Output(UInt(2.W))
})
// Lab3(Forward)
// io.reg1_forward_ex := 0.U
// io.reg2_forward_ex := 0.U
io.reg1_forward_ex := ForwardingType.NoForward
io.reg2_forward_ex := ForwardingType.NoForward
when(io.reg_write_enable_mem && io.rd_mem =/= 0.U && io.rd_mem === io.rs1_ex) {
io.reg1_forward_ex := ForwardingType.ForwardFromMEM
}.elsewhen(io.reg_write_enable_wb && io.rd_wb =/= 0.U && io.rd_wb === io.rs1_ex) {
io.reg1_forward_ex := ForwardingType.ForwardFromWB
}
when(io.reg_write_enable_mem && io.rd_mem =/= 0.U && io.rd_mem === io.rs2_ex) {
io.reg2_forward_ex := ForwardingType.ForwardFromMEM
}.elsewhen(io.reg_write_enable_wb && io.rd_wb =/= 0.U && io.rd_wb === io.rs2_ex) {
io.reg2_forward_ex := ForwardingType.ForwardFromWB
}
// Lab3(Forward) End
}

View File

@@ -0,0 +1,164 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class ID2EX extends Module {
val io = IO(new Bundle {
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_enable = Input(Bool())
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_source = Input(UInt(2.W))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_write_enable = Input(Bool())
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_source = Output(UInt(2.W))
val output_reg1_data = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_immediate = Output(UInt(Parameters.DataWidth))
val output_aluop1_source = Output(UInt(1.W))
val output_aluop2_source = Output(UInt(1.W))
val output_csr_write_enable = Output(Bool())
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg1_read_address.io.in := io.regs_reg1_read_address
regs_reg1_read_address.io.stall := stall
regs_reg1_read_address.io.flush := io.flush
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg2_read_address.io.in := io.regs_reg2_read_address
regs_reg2_read_address.io.stall := stall
regs_reg2_read_address.io.flush := io.flush
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := io.flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := io.flush
io.output_regs_write_address := regs_write_address.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := io.flush
io.output_regs_write_source := regs_write_source.io.out
val reg1_data = Module(new PipelineRegister())
reg1_data.io.in := io.reg1_data
reg1_data.io.stall := stall
reg1_data.io.flush := io.flush
io.output_reg1_data := reg1_data.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := io.flush
io.output_reg2_data := reg2_data.io.out
val immediate = Module(new PipelineRegister())
immediate.io.in := io.immediate
immediate.io.stall := stall
immediate.io.flush := io.flush
io.output_immediate := immediate.io.out
val aluop1_source = Module(new PipelineRegister(1))
aluop1_source.io.in := io.aluop1_source
aluop1_source.io.stall := stall
aluop1_source.io.flush := io.flush
io.output_aluop1_source := aluop1_source.io.out
val aluop2_source = Module(new PipelineRegister(1))
aluop2_source.io.in := io.aluop2_source
aluop2_source.io.stall := stall
aluop2_source.io.flush := io.flush
io.output_aluop2_source := aluop2_source.io.out
val csr_write_enable = Module(new PipelineRegister(1))
csr_write_enable.io.in := io.csr_write_enable
csr_write_enable.io.stall := stall
csr_write_enable.io.flush := io.flush
io.output_csr_write_enable := csr_write_enable.io.out
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
csr_address.io.in := io.csr_address
csr_address.io.stall := stall
csr_address.io.flush := io.flush
io.output_csr_address := csr_address.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := io.flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := io.flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := io.flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,51 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class IF2ID extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
})
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := io.stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := io.stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
interrupt_flag.io.in := io.interrupt_flag
interrupt_flag.io.stall := io.stall
interrupt_flag.io.flush := io.flush
io.output_interrupt_flag := interrupt_flag.io.out
}

View File

@@ -0,0 +1,218 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(Bool())
val ex_aluop2_source = Output(Bool())
val ex_memory_read_enable = Output(Bool())
val ex_memory_write_enable = Output(Bool())
val ex_reg_write_source = Output(UInt(2.W))
val ex_reg_write_enable = Output(Bool())
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val ex_csr_write_enable = Output(Bool())
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
// Lab3(Forward) ID rs
// io.regs_reg1_read_address := rs1
// io.regs_reg2_read_address := rs2
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
// Lab3(Forward) ID rs End
io.ex_immediate := MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
io.ex_aluop2_source := Mux(
opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.ex_memory_read_enable := opcode === InstructionTypes.L
io.ex_memory_write_enable := opcode === InstructionTypes.S
io.ex_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult,
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.csr -> RegWriteSource.CSR,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
// Lab3(Forward) ID rd
// io.ex_reg_write_enable := false.B
// io.ex_reg_write_address := rd
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
opcode === Instructions.jalr || opcode === Instructions.csr
io.ex_reg_write_enable := rd_used
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
// Lab3(Forward) ID rd End
io.ex_csr_address := io.instruction(31, 20)
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
)
}

View File

@@ -0,0 +1,48 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util.MuxCase
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val stall_flag_ctrl = Input(Bool())
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val rom_instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val id_instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
pc := MuxCase(
pc + 4.U,
IndexedSeq(
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
)
)
io.instruction_address := pc
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
}

View File

@@ -0,0 +1,83 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class MEM2WB extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_data = Module(new PipelineRegister())
memory_read_data.io.in := io.memory_read_data
memory_read_data.io.stall := stall
memory_read_data.io.flush := flush
io.output_memory_read_data := memory_read_data.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,109 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
class MemoryAccess extends Module {
val io = IO(new Bundle() {
val alu_result = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val funct3 = Input(UInt(3.W))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
val forward_data = Output(UInt(Parameters.DataWidth))
val bundle = Flipped(new RAMBundle)
})
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
io.bundle.write_enable := io.memory_write_enable
io.bundle.write_data := 0.U
io.bundle.address := io.alu_result
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.wb_memory_read_data := 0.U
when(io.memory_read_enable) {
val data = io.bundle.read_data
io.wb_memory_read_data := MuxLookup(
io.funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable) {
io.bundle.write_data := io.reg2_data
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(io.funct3 === InstructionsTypeS.sb) {
io.bundle.write_strobe(mem_address_index) := true.B
io.bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
}
}
io.forward_data := Mux(io.regs_write_source === RegWriteSource.CSR, io.csr_read_data, io.alu_result)
}

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_forward
import chisel3._
import chisel3.util._
import riscv.Parameters
class WriteBack extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_data = Output(UInt(Parameters.DataWidth))
})
io.regs_write_data := MuxLookup(
io.regs_write_source,
io.alu_result,
IndexedSeq(
RegWriteSource.Memory -> io.memory_read_data,
RegWriteSource.CSR -> io.csr_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
)
)
}

View File

@@ -0,0 +1,103 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data = Output(UInt(Parameters.DataWidth))
val mepc_write_data = Output(UInt(Parameters.DataWidth))
val mcause_write_data = Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val ex_interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
)
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
when(io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := MuxLookup(
io.instruction_ex,
10.U,
IndexedSeq(
InstructionsEnv.ecall -> 11.U,
InstructionsEnv.ebreak -> 3.U,
)
)
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.interrupt_flag =/= InterruptStatus.None && interrupt_enable) {
io.csr_bundle.mstatus_write_data := mstatus_disable_interrupt
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mtvec
}.elsewhen(io.instruction_ex === InstructionsRet.mret) {
io.csr_bundle.mstatus_write_data := mstatus_recover_interrupt
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := true.B
io.ex_interrupt_assert := true.B
io.ex_interrupt_handler_address := io.csr_bundle.mepc
}.otherwise {
io.csr_bundle.mstatus_write_data := io.csr_bundle.mstatus
io.csr_bundle.mepc_write_data := io.csr_bundle.mepc
io.csr_bundle.mcause_write_data := io.csr_bundle.mcause
io.csr_bundle.direct_write_enable := false.B
io.ex_interrupt_assert := false.B
io.ex_interrupt_handler_address := 0.U
}
}

View File

@@ -0,0 +1,148 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
import riscv.core.{CPUBundle, CSR, RegisterFile}
class CPU extends Module {
val io = IO(new CPUBundle)
val ctrl = Module(new Control)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val if2id = Module(new IF2ID)
val id = Module(new InstructionDecode)
val id2ex = Module(new ID2EX)
val ex = Module(new Execute)
val ex2mem = Module(new EX2MEM)
val mem = Module(new MemoryAccess)
val mem2wb = Module(new MEM2WB)
val wb = Module(new WriteBack)
val clint = Module(new CLINT)
val csr_regs = Module(new CSR)
ctrl.io.jump_flag := ex.io.if_jump_flag
ctrl.io.rs1_id := id.io.regs_reg1_read_address
ctrl.io.rs2_id := id.io.regs_reg2_read_address
ctrl.io.rd_ex := id2ex.io.output_regs_write_address
ctrl.io.reg_write_enable_ex := id2ex.io.output_regs_write_enable
ctrl.io.rd_mem := ex2mem.io.output_regs_write_address
ctrl.io.reg_write_enable_mem := ex2mem.io.output_regs_write_enable
regs.io.write_enable := mem2wb.io.output_regs_write_enable
regs.io.write_address := mem2wb.io.output_regs_write_address
regs.io.write_data := wb.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
regs.io.debug_read_address := io.debug_read_address
io.debug_read_data := regs.io.debug_read_data
io.instruction_address := inst_fetch.io.instruction_address
inst_fetch.io.stall_flag_ctrl := ctrl.io.pc_stall
inst_fetch.io.jump_flag_id := ex.io.if_jump_flag
inst_fetch.io.jump_address_id := ex.io.if_jump_address
inst_fetch.io.rom_instruction := io.instruction
inst_fetch.io.instruction_valid := io.instruction_valid
if2id.io.stall := ctrl.io.if2id_stall
if2id.io.flush := ctrl.io.if2id_flush
if2id.io.instruction := inst_fetch.io.id_instruction
if2id.io.instruction_address := inst_fetch.io.instruction_address
if2id.io.interrupt_flag := io.interrupt_flag
id.io.instruction := if2id.io.output_instruction
id2ex.io.flush := ctrl.io.id2ex_flush
id2ex.io.instruction := if2id.io.output_instruction
id2ex.io.instruction_address := if2id.io.output_instruction_address
id2ex.io.reg1_data := regs.io.read_data1
id2ex.io.reg2_data := regs.io.read_data2
id2ex.io.regs_reg1_read_address := id.io.regs_reg1_read_address
id2ex.io.regs_reg2_read_address := id.io.regs_reg2_read_address
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
id2ex.io.regs_write_address := id.io.ex_reg_write_address
id2ex.io.regs_write_source := id.io.ex_reg_write_source
id2ex.io.immediate := id.io.ex_immediate
id2ex.io.aluop1_source := id.io.ex_aluop1_source
id2ex.io.aluop2_source := id.io.ex_aluop2_source
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
id2ex.io.csr_address := id.io.ex_csr_address
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
ex.io.instruction := id2ex.io.output_instruction
ex.io.instruction_address := id2ex.io.output_instruction_address
ex.io.reg1_data := id2ex.io.output_reg1_data
ex.io.reg2_data := id2ex.io.output_reg2_data
ex.io.immediate_id := id2ex.io.output_immediate
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
ex.io.csr_read_data_id := id2ex.io.output_csr_read_data
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
ex2mem.io.regs_write_enable := id2ex.io.output_regs_write_enable
ex2mem.io.regs_write_source := id2ex.io.output_regs_write_source
ex2mem.io.regs_write_address := id2ex.io.output_regs_write_address
ex2mem.io.instruction_address := id2ex.io.output_instruction_address
ex2mem.io.funct3 := id2ex.io.output_instruction(14, 12)
ex2mem.io.reg2_data := ex.io.mem_reg2_data
ex2mem.io.memory_read_enable := id2ex.io.output_memory_read_enable
ex2mem.io.memory_write_enable := id2ex.io.output_memory_write_enable
ex2mem.io.alu_result := ex.io.mem_alu_result
ex2mem.io.csr_read_data := id2ex.io.output_csr_read_data
mem.io.alu_result := ex2mem.io.output_alu_result
mem.io.reg2_data := ex2mem.io.output_reg2_data
mem.io.memory_read_enable := ex2mem.io.output_memory_read_enable
mem.io.memory_write_enable := ex2mem.io.output_memory_write_enable
mem.io.funct3 := ex2mem.io.output_funct3
mem.io.regs_write_source := ex2mem.io.output_regs_write_source
mem.io.csr_read_data := ex2mem.io.output_csr_read_data
io.device_select := mem.io.bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
io.memory_bundle <> mem.io.bundle
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## mem.io.bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
mem2wb.io.instruction_address := ex2mem.io.output_instruction_address
mem2wb.io.alu_result := ex2mem.io.output_alu_result
mem2wb.io.regs_write_enable := ex2mem.io.output_regs_write_enable
mem2wb.io.regs_write_source := ex2mem.io.output_regs_write_source
mem2wb.io.regs_write_address := ex2mem.io.output_regs_write_address
mem2wb.io.memory_read_data := mem.io.wb_memory_read_data
mem2wb.io.csr_read_data := ex2mem.io.output_csr_read_data
wb.io.instruction_address := mem2wb.io.output_instruction_address
wb.io.alu_result := mem2wb.io.output_alu_result
wb.io.memory_read_data := mem2wb.io.output_memory_read_data
wb.io.regs_write_source := mem2wb.io.output_regs_write_source
wb.io.csr_read_data := mem2wb.io.output_csr_read_data
clint.io.instruction_address_if := inst_fetch.io.instruction_address
clint.io.instruction_address_id := if2id.io.output_instruction_address
clint.io.instruction_ex := id2ex.io.output_instruction
clint.io.jump_flag := ex.io.clint_jump_flag
clint.io.jump_address := ex.io.clint_jump_address
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
}

View File

@@ -0,0 +1,46 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
class Control extends Module {
val io = IO(new Bundle {
val jump_flag = Input(Bool())
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_ex = Input(Bool())
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_mem = Input(Bool())
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
val pc_stall = Output(Bool())
val if2id_stall = Output(Bool())
})
// Lab3(Stall)
val hazard_from_ex = io.reg_write_enable_ex && io.rd_ex =/= 0.U && (io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val hazard_from_mem = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
val stall = hazard_from_ex || hazard_from_mem
val flush = io.jump_flag
io.pc_stall := stall && !flush
io.if2id_stall := stall && !flush
io.if2id_flush := flush
io.id2ex_flush := flush || stall
// Lab3(Stall) End
}

View File

@@ -0,0 +1,108 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class EX2MEM extends Module {
val io = IO(new Bundle() {
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val funct3 = Input(UInt(3.W))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val alu_result = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_funct3 = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.AddrBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val funct3 = Module(new PipelineRegister(3))
funct3.io.in := io.funct3
funct3.io.stall := stall
funct3.io.flush := flush
io.output_funct3 := funct3.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := flush
io.output_reg2_data := reg2_data.io.out
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,101 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util._
import riscv.Parameters
import riscv.core.{ALU, ALUControl}
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate_id = Input(UInt(Parameters.DataWidth))
val aluop1_source_id = Input(UInt(1.W))
val aluop2_source_id = Input(UInt(1.W))
val csr_read_data_id = Input(UInt(Parameters.DataWidth))
val interrupt_assert_clint = Input(Bool())
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
val mem_alu_result = Output(UInt(Parameters.DataWidth))
val mem_reg2_data = Output(UInt(Parameters.DataWidth))
val csr_write_data = Output(UInt(Parameters.DataWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.AddrWidth))
val clint_jump_flag = Output(Bool())
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val uimm = io.instruction(19, 15)
// ALU compute
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
alu.io.func := alu_ctrl.io.alu_funct
alu.io.op1 := Mux(
io.aluop1_source_id === ALUOp1Source.InstructionAddress,
io.instruction_address,
io.reg1_data
)
alu.io.op2 := Mux(
io.aluop2_source_id === ALUOp2Source.Immediate,
io.immediate_id,
io.reg2_data
)
io.mem_alu_result := alu.io.result
io.mem_reg2_data := io.reg2_data
io.csr_write_data := MuxLookup(funct3, 0.U, IndexedSeq(
InstructionsTypeCSR.csrrw -> io.reg1_data,
InstructionsTypeCSR.csrrc -> io.csr_read_data_id.&((~io.reg1_data).asUInt),
InstructionsTypeCSR.csrrs -> io.csr_read_data_id.|(io.reg1_data),
InstructionsTypeCSR.csrrwi -> Cat(0.U(27.W), uimm),
InstructionsTypeCSR.csrrci -> io.csr_read_data_id.&((~Cat(0.U(27.W), uimm)).asUInt),
InstructionsTypeCSR.csrrsi -> io.csr_read_data_id.|(Cat(0.U(27.W), uimm)),
))
// jump and interrupt
val instruction_jump_flag = (opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
)
)
io.clint_jump_flag := instruction_jump_flag
io.clint_jump_address := alu.io.result
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
io.if_jump_address := Mux(io.interrupt_assert_clint,
io.interrupt_handler_address_clint,
alu.io.result
)
}

View File

@@ -0,0 +1,164 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class ID2EX extends Module {
val io = IO(new Bundle {
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val regs_reg1_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_enable = Input(Bool())
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_source = Input(UInt(2.W))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_write_enable = Input(Bool())
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_source = Output(UInt(2.W))
val output_reg1_data = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_immediate = Output(UInt(Parameters.DataWidth))
val output_aluop1_source = Output(UInt(1.W))
val output_aluop2_source = Output(UInt(1.W))
val output_csr_write_enable = Output(Bool())
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val regs_reg1_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg1_read_address.io.in := io.regs_reg1_read_address
regs_reg1_read_address.io.stall := stall
regs_reg1_read_address.io.flush := io.flush
io.output_regs_reg1_read_address := regs_reg1_read_address.io.out
val regs_reg2_read_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_reg2_read_address.io.in := io.regs_reg2_read_address
regs_reg2_read_address.io.stall := stall
regs_reg2_read_address.io.flush := io.flush
io.output_regs_reg2_read_address := regs_reg2_read_address.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := io.flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := io.flush
io.output_regs_write_address := regs_write_address.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := io.flush
io.output_regs_write_source := regs_write_source.io.out
val reg1_data = Module(new PipelineRegister())
reg1_data.io.in := io.reg1_data
reg1_data.io.stall := stall
reg1_data.io.flush := io.flush
io.output_reg1_data := reg1_data.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := io.flush
io.output_reg2_data := reg2_data.io.out
val immediate = Module(new PipelineRegister())
immediate.io.in := io.immediate
immediate.io.stall := stall
immediate.io.flush := io.flush
io.output_immediate := immediate.io.out
val aluop1_source = Module(new PipelineRegister(1))
aluop1_source.io.in := io.aluop1_source
aluop1_source.io.stall := stall
aluop1_source.io.flush := io.flush
io.output_aluop1_source := aluop1_source.io.out
val aluop2_source = Module(new PipelineRegister(1))
aluop2_source.io.in := io.aluop2_source
aluop2_source.io.stall := stall
aluop2_source.io.flush := io.flush
io.output_aluop2_source := aluop2_source.io.out
val csr_write_enable = Module(new PipelineRegister(1))
csr_write_enable.io.in := io.csr_write_enable
csr_write_enable.io.stall := stall
csr_write_enable.io.flush := io.flush
io.output_csr_write_enable := csr_write_enable.io.out
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
csr_address.io.in := io.csr_address
csr_address.io.stall := stall
csr_address.io.flush := io.flush
io.output_csr_address := csr_address.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := io.flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := io.flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := io.flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,51 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class IF2ID extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
})
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := io.stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := io.stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
interrupt_flag.io.in := io.interrupt_flag
interrupt_flag.io.stall := io.stall
interrupt_flag.io.flush := io.flush
io.output_interrupt_flag := interrupt_flag.io.out
}

View File

@@ -0,0 +1,214 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(Bool())
val ex_aluop2_source = Output(Bool())
val ex_memory_read_enable = Output(Bool())
val ex_memory_write_enable = Output(Bool())
val ex_reg_write_source = Output(UInt(2.W))
val ex_reg_write_enable = Output(Bool())
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val ex_csr_write_enable = Output(Bool())
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
// Lab3(Stall) ID rs
val rs1_used = opcode =/= Instructions.lui && opcode =/= Instructions.auipc && opcode =/= Instructions.jal
val rs2_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.S || opcode === InstructionTypes.B
io.regs_reg1_read_address := Mux(rs1_used, rs1, 0.U)
io.regs_reg2_read_address := Mux(rs2_used, rs2, 0.U)
// Lab3(Stall) ID rs End
io.ex_immediate := MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
io.ex_aluop2_source := Mux(
opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.ex_memory_read_enable := opcode === InstructionTypes.L
io.ex_memory_write_enable := opcode === InstructionTypes.S
io.ex_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult,
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.csr -> RegWriteSource.CSR,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
// Lab3(Stall) ID rd
val rd_used = opcode === InstructionTypes.RM || opcode === InstructionTypes.I || opcode === InstructionTypes.L ||
opcode === Instructions.lui || opcode === Instructions.auipc || opcode === Instructions.jal ||
opcode === Instructions.jalr || opcode === Instructions.csr
io.ex_reg_write_enable := rd_used
io.ex_reg_write_address := Mux(rd_used, rd, 0.U)
// Lab3(Stall) ID rd End
io.ex_csr_address := io.instruction(31, 20)
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
)
}

View File

@@ -0,0 +1,48 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util.MuxCase
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val stall_flag_ctrl = Input(Bool())
val jump_flag_id = Input(Bool())
val jump_address_id = Input(UInt(Parameters.AddrWidth))
val rom_instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val id_instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
pc := MuxCase(
pc + 4.U,
IndexedSeq(
(io.jump_flag_id && !io.stall_flag_ctrl) -> io.jump_address_id,
(io.stall_flag_ctrl || !io.instruction_valid) -> pc
)
)
io.instruction_address := pc
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
}

View File

@@ -0,0 +1,83 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class MEM2WB extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val regs_write_enable = Input(Bool())
val regs_write_source = Input(UInt(2.W))
val regs_write_address = Input(UInt(Parameters.AddrWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_alu_result = Output(UInt(Parameters.DataWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_source = Output(UInt(2.W))
val output_regs_write_address = Output(UInt(Parameters.AddrWidth))
val output_memory_read_data = Output(UInt(Parameters.DataWidth))
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val flush = false.B
val alu_result = Module(new PipelineRegister())
alu_result.io.in := io.alu_result
alu_result.io.stall := stall
alu_result.io.flush := flush
io.output_alu_result := alu_result.io.out
val memory_read_data = Module(new PipelineRegister())
memory_read_data.io.in := io.memory_read_data
memory_read_data.io.stall := stall
memory_read_data.io.flush := flush
io.output_memory_read_data := memory_read_data.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := flush
io.output_regs_write_source := regs_write_source.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := flush
io.output_regs_write_address := regs_write_address.io.out
val instruction_address = Module(new PipelineRegister(Parameters.InstructionBits))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := flush
io.output_instruction_address := instruction_address.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,106 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
class MemoryAccess extends Module {
val io = IO(new Bundle() {
val alu_result = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val funct3 = Input(UInt(3.W))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val wb_memory_read_data = Output(UInt(Parameters.DataWidth))
val bundle = Flipped(new RAMBundle)
})
val mem_address_index = io.alu_result(log2Up(Parameters.WordSize) - 1, 0).asUInt
io.bundle.write_enable := io.memory_write_enable
io.bundle.write_data := 0.U
io.bundle.address := io.alu_result
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
io.wb_memory_read_data := 0.U
when(io.memory_read_enable) {
val data = io.bundle.read_data
io.wb_memory_read_data := MuxLookup(
io.funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable) {
io.bundle.write_data := io.reg2_data
io.bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(io.funct3 === InstructionsTypeS.sb) {
io.bundle.write_strobe(mem_address_index) := true.B
io.bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(io.funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
io.bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(io.funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.bundle.write_strobe(i) := true.B
}
}
}
}

View File

@@ -0,0 +1,40 @@
// Copyright 2022 Canbin Huang
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.fivestage_stall
import chisel3._
import chisel3.util._
import riscv.Parameters
class WriteBack extends Module {
val io = IO(new Bundle() {
val instruction_address = Input(UInt(Parameters.AddrWidth))
val alu_result = Input(UInt(Parameters.DataWidth))
val memory_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_source = Input(UInt(2.W))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val regs_write_data = Output(UInt(Parameters.DataWidth))
})
io.regs_write_data := MuxLookup(
io.regs_write_source,
io.alu_result,
IndexedSeq(
RegWriteSource.Memory -> io.memory_read_data,
RegWriteSource.CSR -> io.csr_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
)
)
}

View File

@@ -0,0 +1,88 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import chisel3.util.MuxLookup
import riscv.Parameters
object InterruptStatus {
val None = 0x0.U(8.W)
val Timer0 = 0x1.U(8.W)
val Ret = 0xFF.U(8.W)
}
class CSRDirectAccessBundle extends Bundle {
val mstatus = Input(UInt(Parameters.DataWidth))
val mepc = Input(UInt(Parameters.DataWidth))
val mcause = Input(UInt(Parameters.DataWidth))
val mtvec = Input(UInt(Parameters.DataWidth))
val mstatus_write_data = Output(UInt(Parameters.DataWidth))
val mepc_write_data = Output(UInt(Parameters.DataWidth))
val mcause_write_data = Output(UInt(Parameters.DataWidth))
val direct_write_enable = Output(Bool())
}
// Core Local Interrupt Controller
class CLINT extends Module {
val io = IO(new Bundle {
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val instruction_ex = Input(UInt(Parameters.InstructionWidth))
val instruction_address_if = Input(UInt(Parameters.AddrWidth))
val instruction_address_id = Input(UInt(Parameters.AddrWidth))
val jump_flag = Input(Bool())
val jump_address = Input(UInt(Parameters.AddrWidth))
val ex_interrupt_handler_address = Output(UInt(Parameters.AddrWidth))
val ex_interrupt_assert = Output(Bool())
val csr_bundle = new CSRDirectAccessBundle
})
val interrupt_enable = io.csr_bundle.mstatus(3)
val jumpping = RegNext(io.jump_flag || io.ex_interrupt_assert)
val instruction_address = Mux(
io.jump_flag,
io.jump_address,
Mux(jumpping, io.instruction_address_if, io.instruction_address_id)
)
val mstatus_disable_interrupt = io.csr_bundle.mstatus(31, 4) ## 0.U(1.W) ## io.csr_bundle.mstatus(2, 0)
val mstatus_recover_interrupt = io.csr_bundle.mstatus(31, 4) ## io.csr_bundle.mstatus(7) ## io.csr_bundle.mstatus(2, 0)
val exception = io.instruction_ex === InstructionsEnv.ecall || io.instruction_ex === InstructionsEnv.ebreak
val interrupt = io.interrupt_flag =/= InterruptStatus.None && interrupt_enable
val mret = io.instruction_ex === InstructionsRet.mret
val interrupt_assert = exception || interrupt || mret
io.csr_bundle.mstatus_write_data := Mux(mret, mstatus_recover_interrupt, mstatus_disable_interrupt)
io.csr_bundle.mepc_write_data := instruction_address
io.csr_bundle.mcause_write_data := Mux(
exception,
MuxLookup(
io.instruction_ex,
10.U,
IndexedSeq(
InstructionsEnv.ecall -> 11.U,
InstructionsEnv.ebreak -> 3.U,
)
),
Mux(io.interrupt_flag(0), 0x80000007L.U, 0x8000000BL.U)
)
io.csr_bundle.direct_write_enable := interrupt_assert
io.ex_interrupt_assert := interrupt_assert
io.ex_interrupt_handler_address := Mux(mret, io.csr_bundle.mepc, io.csr_bundle.mtvec)
}

View File

@@ -0,0 +1,107 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import riscv.Parameters
import riscv.core.{CPUBundle, CSR, RegisterFile}
class CPU extends Module {
val io = IO(new CPUBundle)
val ctrl = Module(new Control)
val regs = Module(new RegisterFile)
val inst_fetch = Module(new InstructionFetch)
val if2id = Module(new IF2ID)
val id = Module(new InstructionDecode)
val id2ex = Module(new ID2EX)
val ex = Module(new Execute)
val clint = Module(new CLINT)
val csr_regs = Module(new CSR)
// Lab3(ThreeStage)
// if2id.io.flush := false.B
// id2ex.io.flush := false.B
ctrl.io.jump_flag_ex := ex.io.if_jump_flag
if2id.io.flush := ctrl.io.if2id_flush
id2ex.io.flush := ctrl.io.id2ex_flush
// Lab3(ThreeStage) End
regs.io.write_enable := id2ex.io.output_regs_write_enable
regs.io.write_address := id2ex.io.output_regs_write_address
regs.io.write_data := ex.io.regs_write_data
regs.io.read_address1 := id.io.regs_reg1_read_address
regs.io.read_address2 := id.io.regs_reg2_read_address
regs.io.debug_read_address := io.debug_read_address
io.debug_read_data := regs.io.debug_read_data
io.instruction_address := inst_fetch.io.instruction_address
inst_fetch.io.jump_flag_ex := ex.io.if_jump_flag
inst_fetch.io.jump_address_ex := ex.io.if_jump_address
inst_fetch.io.rom_instruction := io.instruction
inst_fetch.io.instruction_valid := io.instruction_valid
if2id.io.instruction := inst_fetch.io.id_instruction
if2id.io.instruction_address := inst_fetch.io.instruction_address
if2id.io.interrupt_flag := io.interrupt_flag
id.io.instruction := if2id.io.output_instruction
id2ex.io.instruction := if2id.io.output_instruction
id2ex.io.instruction_address := if2id.io.output_instruction_address
id2ex.io.reg1_data := regs.io.read_data1
id2ex.io.reg2_data := regs.io.read_data2
id2ex.io.regs_write_enable := id.io.ex_reg_write_enable
id2ex.io.regs_write_address := id.io.ex_reg_write_address
id2ex.io.regs_write_source := id.io.ex_reg_write_source
id2ex.io.immediate := id.io.ex_immediate
id2ex.io.aluop1_source := id.io.ex_aluop1_source
id2ex.io.aluop2_source := id.io.ex_aluop2_source
id2ex.io.csr_write_enable := id.io.ex_csr_write_enable
id2ex.io.csr_address := id.io.ex_csr_address
id2ex.io.memory_read_enable := id.io.ex_memory_read_enable
id2ex.io.memory_write_enable := id.io.ex_memory_write_enable
id2ex.io.csr_read_data := csr_regs.io.id_reg_read_data
ex.io.instruction := id2ex.io.output_instruction
ex.io.instruction_address := id2ex.io.output_instruction_address
ex.io.reg1_data := id2ex.io.output_reg1_data
ex.io.reg2_data := id2ex.io.output_reg2_data
ex.io.csr_read_data := id2ex.io.output_csr_read_data
ex.io.immediate_id := id2ex.io.output_immediate
ex.io.aluop1_source_id := id2ex.io.output_aluop1_source
ex.io.aluop2_source_id := id2ex.io.output_aluop2_source
ex.io.memory_read_enable_id := id2ex.io.output_memory_read_enable
ex.io.memory_write_enable_id := id2ex.io.output_memory_write_enable
ex.io.regs_write_source_id := id2ex.io.output_regs_write_source
ex.io.interrupt_assert_clint := clint.io.ex_interrupt_assert
ex.io.interrupt_handler_address_clint := clint.io.ex_interrupt_handler_address
io.device_select := ex.io.memory_bundle.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
io.memory_bundle <> ex.io.memory_bundle
io.memory_bundle.address := 0.U(Parameters.SlaveDeviceCountBits.W) ## ex.io.memory_bundle.address(Parameters.AddrBits - 1 - Parameters.SlaveDeviceCountBits, 0)
clint.io.instruction_address_if := inst_fetch.io.instruction_address
clint.io.instruction_address_id := if2id.io.output_instruction_address
clint.io.instruction_ex := id2ex.io.output_instruction
clint.io.jump_flag := ex.io.clint_jump_flag
clint.io.jump_address := ex.io.clint_jump_address
clint.io.interrupt_flag := if2id.io.output_interrupt_flag
clint.io.csr_bundle <> csr_regs.io.clint_access_bundle
csr_regs.io.reg_read_address_id := id.io.ex_csr_address
csr_regs.io.reg_write_enable_ex := id2ex.io.output_csr_write_enable
csr_regs.io.reg_write_address_ex := id2ex.io.output_csr_address
csr_regs.io.reg_write_data_ex := ex.io.csr_write_data
}

View File

@@ -0,0 +1,30 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
class Control extends Module {
// Lab3(ThreeStage)
val io = IO(new Bundle {
val jump_flag_ex = Input(Bool())
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
})
val flush = io.jump_flag_ex
io.if2id_flush := flush
io.id2ex_flush := flush
// Lab3(ThreeStage) End
}

View File

@@ -0,0 +1,191 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import chisel3.util._
import peripheral.RAMBundle
import riscv.Parameters
import riscv.core.{ALU, ALUControl}
class Execute extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val csr_read_data = Input(UInt(Parameters.DataWidth))
val immediate_id = Input(UInt(Parameters.DataWidth))
val aluop1_source_id = Input(UInt(1.W))
val aluop2_source_id = Input(UInt(1.W))
val memory_read_enable_id = Input(Bool())
val memory_write_enable_id = Input(Bool())
val regs_write_source_id = Input(UInt(2.W))
val interrupt_assert_clint = Input(Bool())
val interrupt_handler_address_clint = Input(UInt(Parameters.AddrWidth))
val memory_bundle = Flipped(new RAMBundle)
val csr_write_data = Output(UInt(Parameters.DataWidth))
val regs_write_data = Output(UInt(Parameters.DataWidth))
val if_jump_flag = Output(Bool())
val if_jump_address = Output(UInt(Parameters.AddrWidth))
val clint_jump_flag = Output(Bool())
val clint_jump_address = Output(UInt(Parameters.AddrWidth))
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val uimm = io.instruction(19, 15)
// ALU compute
val alu = Module(new ALU)
val alu_ctrl = Module(new ALUControl)
alu_ctrl.io.opcode := opcode
alu_ctrl.io.funct3 := funct3
alu_ctrl.io.funct7 := funct7
alu.io.func := alu_ctrl.io.alu_funct
alu.io.op1 := Mux(
io.aluop1_source_id === ALUOp1Source.InstructionAddress,
io.instruction_address,
io.reg1_data
)
alu.io.op2 := Mux(
io.aluop2_source_id === ALUOp2Source.Immediate,
io.immediate_id,
io.reg2_data
)
io.csr_write_data := MuxLookup(
funct3,
0.U,
IndexedSeq(
InstructionsTypeCSR.csrrw -> io.reg1_data,
InstructionsTypeCSR.csrrc -> (io.csr_read_data & (~io.reg1_data).asUInt),
InstructionsTypeCSR.csrrs -> (io.csr_read_data | io.reg1_data),
InstructionsTypeCSR.csrrwi -> (0.U(27.W) ## uimm),
InstructionsTypeCSR.csrrci -> (io.csr_read_data & (~(0.U(27.W) ## uimm)).asUInt),
InstructionsTypeCSR.csrrsi -> (io.csr_read_data | 0.U(27.W) ## uimm),
)
)
// memory access
val mem_address_index = alu.io.result(log2Up(Parameters.WordSize) - 1, 0).asUInt
val mem_read_data = Wire(UInt(Parameters.DataWidth))
io.memory_bundle.write_enable := io.memory_write_enable_id
io.memory_bundle.write_data := 0.U
io.memory_bundle.address := alu.io.result
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
mem_read_data := 0.U
when(io.memory_read_enable_id) {
val data = io.memory_bundle.read_data
mem_read_data := MuxLookup(
funct3,
0.U,
IndexedSeq(
InstructionsTypeL.lb -> MuxLookup(
mem_address_index,
Cat(Fill(24, data(31)), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, data(7)), data(7, 0)),
1.U -> Cat(Fill(24, data(15)), data(15, 8)),
2.U -> Cat(Fill(24, data(23)), data(23, 16))
)
),
InstructionsTypeL.lbu -> MuxLookup(
mem_address_index,
Cat(Fill(24, 0.U), data(31, 24)),
IndexedSeq(
0.U -> Cat(Fill(24, 0.U), data(7, 0)),
1.U -> Cat(Fill(24, 0.U), data(15, 8)),
2.U -> Cat(Fill(24, 0.U), data(23, 16))
)
),
InstructionsTypeL.lh -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, data(15)), data(15, 0)),
Cat(Fill(16, data(31)), data(31, 16))
),
InstructionsTypeL.lhu -> Mux(
mem_address_index === 0.U,
Cat(Fill(16, 0.U), data(15, 0)),
Cat(Fill(16, 0.U), data(31, 16))
),
InstructionsTypeL.lw -> data
)
)
}.elsewhen(io.memory_write_enable_id) {
io.memory_bundle.write_data := io.reg2_data
io.memory_bundle.write_strobe := VecInit(Seq.fill(Parameters.WordSize)(false.B))
when(funct3 === InstructionsTypeS.sb) {
io.memory_bundle.write_strobe(mem_address_index) := true.B
io.memory_bundle.write_data := io.reg2_data(Parameters.ByteBits, 0) << (mem_address_index << log2Up(Parameters.ByteBits).U)
}.elsewhen(funct3 === InstructionsTypeS.sh) {
when(mem_address_index === 0.U) {
for (i <- 0 until Parameters.WordSize / 2) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0)
}.otherwise {
for (i <- Parameters.WordSize / 2 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
io.memory_bundle.write_data := io.reg2_data(Parameters.WordSize / 2 * Parameters.ByteBits, 0) << (Parameters
.WordSize / 2 * Parameters.ByteBits)
}
}.elsewhen(funct3 === InstructionsTypeS.sw) {
for (i <- 0 until Parameters.WordSize) {
io.memory_bundle.write_strobe(i) := true.B
}
}
}
// write back
io.regs_write_data := MuxLookup(
io.regs_write_source_id,
alu.io.result,
IndexedSeq(
RegWriteSource.Memory -> mem_read_data,
RegWriteSource.CSR -> io.csr_read_data,
RegWriteSource.NextInstructionAddress -> (io.instruction_address + 4.U)
)
)
// jump and interrupt
val instruction_jump_flag = (opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data),
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data),
InstructionsTypeB.blt -> (io.reg1_data.asSInt < io.reg2_data.asSInt),
InstructionsTypeB.bge -> (io.reg1_data.asSInt >= io.reg2_data.asSInt),
InstructionsTypeB.bltu -> (io.reg1_data.asUInt < io.reg2_data.asUInt),
InstructionsTypeB.bgeu -> (io.reg1_data.asUInt >= io.reg2_data.asUInt)
)
)
io.clint_jump_flag := instruction_jump_flag
io.clint_jump_address := alu.io.result
io.if_jump_flag := io.interrupt_assert_clint || instruction_jump_flag
io.if_jump_address := Mux(io.interrupt_assert_clint,
io.interrupt_handler_address_clint,
alu.io.result
)
}

View File

@@ -0,0 +1,148 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class ID2EX extends Module {
val io = IO(new Bundle {
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val regs_write_enable = Input(Bool())
val regs_write_address = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_write_source = Input(UInt(2.W))
val reg1_data = Input(UInt(Parameters.DataWidth))
val reg2_data = Input(UInt(Parameters.DataWidth))
val immediate = Input(UInt(Parameters.DataWidth))
val aluop1_source = Input(UInt(1.W))
val aluop2_source = Input(UInt(1.W))
val csr_write_enable = Input(Bool())
val csr_address = Input(UInt(Parameters.CSRRegisterAddrWidth))
val memory_read_enable = Input(Bool())
val memory_write_enable = Input(Bool())
val csr_read_data = Input(UInt(Parameters.DataWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_regs_write_enable = Output(Bool())
val output_regs_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val output_regs_write_source = Output(UInt(2.W))
val output_reg1_data = Output(UInt(Parameters.DataWidth))
val output_reg2_data = Output(UInt(Parameters.DataWidth))
val output_immediate = Output(UInt(Parameters.DataWidth))
val output_aluop1_source = Output(UInt(1.W))
val output_aluop2_source = Output(UInt(1.W))
val output_csr_write_enable = Output(Bool())
val output_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val output_memory_read_enable = Output(Bool())
val output_memory_write_enable = Output(Bool())
val output_csr_read_data = Output(UInt(Parameters.DataWidth))
})
val stall = false.B
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val regs_write_enable = Module(new PipelineRegister(1))
regs_write_enable.io.in := io.regs_write_enable
regs_write_enable.io.stall := stall
regs_write_enable.io.flush := io.flush
io.output_regs_write_enable := regs_write_enable.io.out
val regs_write_address = Module(new PipelineRegister(Parameters.PhysicalRegisterAddrBits))
regs_write_address.io.in := io.regs_write_address
regs_write_address.io.stall := stall
regs_write_address.io.flush := io.flush
io.output_regs_write_address := regs_write_address.io.out
val regs_write_source = Module(new PipelineRegister(2))
regs_write_source.io.in := io.regs_write_source
regs_write_source.io.stall := stall
regs_write_source.io.flush := io.flush
io.output_regs_write_source := regs_write_source.io.out
val reg1_data = Module(new PipelineRegister())
reg1_data.io.in := io.reg1_data
reg1_data.io.stall := stall
reg1_data.io.flush := io.flush
io.output_reg1_data := reg1_data.io.out
val reg2_data = Module(new PipelineRegister())
reg2_data.io.in := io.reg2_data
reg2_data.io.stall := stall
reg2_data.io.flush := io.flush
io.output_reg2_data := reg2_data.io.out
val immediate = Module(new PipelineRegister())
immediate.io.in := io.immediate
immediate.io.stall := stall
immediate.io.flush := io.flush
io.output_immediate := immediate.io.out
val aluop1_source = Module(new PipelineRegister(1))
aluop1_source.io.in := io.aluop1_source
aluop1_source.io.stall := stall
aluop1_source.io.flush := io.flush
io.output_aluop1_source := aluop1_source.io.out
val aluop2_source = Module(new PipelineRegister(1))
aluop2_source.io.in := io.aluop2_source
aluop2_source.io.stall := stall
aluop2_source.io.flush := io.flush
io.output_aluop2_source := aluop2_source.io.out
val csr_write_enable = Module(new PipelineRegister(1))
csr_write_enable.io.in := io.csr_write_enable
csr_write_enable.io.stall := stall
csr_write_enable.io.flush := io.flush
io.output_csr_write_enable := csr_write_enable.io.out
val csr_address = Module(new PipelineRegister(Parameters.CSRRegisterAddrBits))
csr_address.io.in := io.csr_address
csr_address.io.stall := stall
csr_address.io.flush := io.flush
io.output_csr_address := csr_address.io.out
val memory_read_enable = Module(new PipelineRegister(1))
memory_read_enable.io.in := io.memory_read_enable
memory_read_enable.io.stall := stall
memory_read_enable.io.flush := io.flush
io.output_memory_read_enable := memory_read_enable.io.out
val memory_write_enable = Module(new PipelineRegister(1))
memory_write_enable.io.in := io.memory_write_enable
memory_write_enable.io.stall := stall
memory_write_enable.io.flush := io.flush
io.output_memory_write_enable := memory_write_enable.io.out
val csr_read_data = Module(new PipelineRegister())
csr_read_data.io.in := io.csr_read_data
csr_read_data.io.stall := stall
csr_read_data.io.flush := io.flush
io.output_csr_read_data := csr_read_data.io.out
}

View File

@@ -0,0 +1,52 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import riscv.Parameters
import riscv.core.PipelineRegister
class IF2ID extends Module {
val io = IO(new Bundle {
val flush = Input(Bool())
val instruction = Input(UInt(Parameters.InstructionWidth))
val instruction_address = Input(UInt(Parameters.AddrWidth))
val interrupt_flag = Input(UInt(Parameters.InterruptFlagWidth))
val output_instruction = Output(UInt(Parameters.DataWidth))
val output_instruction_address = Output(UInt(Parameters.AddrWidth))
val output_interrupt_flag = Output(UInt(Parameters.InterruptFlagWidth))
})
val stall = false.B
val instruction = Module(new PipelineRegister(defaultValue = InstructionsNop.nop))
instruction.io.in := io.instruction
instruction.io.stall := stall
instruction.io.flush := io.flush
io.output_instruction := instruction.io.out
val instruction_address = Module(new PipelineRegister(defaultValue = ProgramCounter.EntryAddress))
instruction_address.io.in := io.instruction_address
instruction_address.io.stall := stall
instruction_address.io.flush := io.flush
io.output_instruction_address := instruction_address.io.out
val interrupt_flag = Module(new PipelineRegister(Parameters.InterruptFlagBits))
interrupt_flag.io.in := io.interrupt_flag
interrupt_flag.io.stall := stall
interrupt_flag.io.flush := io.flush
io.output_interrupt_flag := interrupt_flag.io.out
}

View File

@@ -0,0 +1,207 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import chisel3.util._
import riscv.Parameters
object InstructionTypes {
val L = "b0000011".U
val I = "b0010011".U
val S = "b0100011".U
val RM = "b0110011".U
val B = "b1100011".U
}
object Instructions {
val lui = "b0110111".U
val nop = "b0000001".U
val jal = "b1101111".U
val jalr = "b1100111".U
val auipc = "b0010111".U
val csr = "b1110011".U
val fence = "b0001111".U
}
object InstructionsTypeL {
val lb = "b000".U
val lh = "b001".U
val lw = "b010".U
val lbu = "b100".U
val lhu = "b101".U
}
object InstructionsTypeI {
val addi = 0.U
val slli = 1.U
val slti = 2.U
val sltiu = 3.U
val xori = 4.U
val sri = 5.U
val ori = 6.U
val andi = 7.U
}
object InstructionsTypeS {
val sb = "b000".U
val sh = "b001".U
val sw = "b010".U
}
object InstructionsTypeR {
val add_sub = 0.U
val sll = 1.U
val slt = 2.U
val sltu = 3.U
val xor = 4.U
val sr = 5.U
val or = 6.U
val and = 7.U
}
object InstructionsTypeM {
val mul = 0.U
val mulh = 1.U
val mulhsu = 2.U
val mulhum = 3.U
val div = 4.U
val divu = 5.U
val rem = 6.U
val remu = 7.U
}
object InstructionsTypeB {
val beq = "b000".U
val bne = "b001".U
val blt = "b100".U
val bge = "b101".U
val bltu = "b110".U
val bgeu = "b111".U
}
object InstructionsTypeCSR {
val csrrw = "b001".U
val csrrs = "b010".U
val csrrc = "b011".U
val csrrwi = "b101".U
val csrrsi = "b110".U
val csrrci = "b111".U
}
object InstructionsNop {
val nop = 0x00000013L.U(Parameters.DataWidth)
}
object InstructionsRet {
val mret = 0x30200073L.U(Parameters.DataWidth)
val ret = 0x00008067L.U(Parameters.DataWidth)
}
object InstructionsEnv {
val ecall = 0x00000073L.U(Parameters.DataWidth)
val ebreak = 0x00100073L.U(Parameters.DataWidth)
}
object ALUOp1Source {
val Register = 0.U(1.W)
val InstructionAddress = 1.U(1.W)
}
object ALUOp2Source {
val Register = 0.U(1.W)
val Immediate = 1.U(1.W)
}
object RegWriteSource {
val ALUResult = 0.U(2.W)
val Memory = 1.U(2.W)
val CSR = 2.U(2.W)
val NextInstructionAddress = 3.U(2.W)
}
class InstructionDecode extends Module {
val io = IO(new Bundle {
val instruction = Input(UInt(Parameters.InstructionWidth))
val regs_reg1_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val regs_reg2_read_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_immediate = Output(UInt(Parameters.DataWidth))
val ex_aluop1_source = Output(Bool())
val ex_aluop2_source = Output(Bool())
val ex_memory_read_enable = Output(Bool())
val ex_memory_write_enable = Output(Bool())
val ex_reg_write_source = Output(UInt(2.W))
val ex_reg_write_enable = Output(Bool())
val ex_reg_write_address = Output(UInt(Parameters.PhysicalRegisterAddrWidth))
val ex_csr_address = Output(UInt(Parameters.CSRRegisterAddrWidth))
val ex_csr_write_enable = Output(Bool())
})
val opcode = io.instruction(6, 0)
val funct3 = io.instruction(14, 12)
val funct7 = io.instruction(31, 25)
val rd = io.instruction(11, 7)
val rs1 = io.instruction(19, 15)
val rs2 = io.instruction(24, 20)
io.regs_reg1_read_address := Mux(opcode === Instructions.lui, 0.U(Parameters.PhysicalRegisterAddrWidth), rs1)
io.regs_reg2_read_address := rs2
io.ex_immediate := MuxLookup(
opcode,
Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)),
IndexedSeq(
InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.L -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
Instructions.jalr -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
InstructionTypes.S -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 25), io.instruction(11, 7)),
InstructionTypes.B -> Cat(Fill(20, io.instruction(31)), io.instruction(7), io.instruction(30, 25), io.instruction(11, 8), 0.U(1.W)),
Instructions.lui -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.auipc -> Cat(io.instruction(31, 12), 0.U(12.W)),
Instructions.jal -> Cat(Fill(12, io.instruction(31)), io.instruction(19, 12), io.instruction(20), io.instruction(30, 21), 0.U(1.W))
)
)
io.ex_aluop1_source := Mux(
opcode === Instructions.auipc || opcode === InstructionTypes.B || opcode === Instructions.jal,
ALUOp1Source.InstructionAddress,
ALUOp1Source.Register
)
io.ex_aluop2_source := Mux(
opcode === InstructionTypes.RM,
ALUOp2Source.Register,
ALUOp2Source.Immediate
)
io.ex_memory_read_enable := opcode === InstructionTypes.L
io.ex_memory_write_enable := opcode === InstructionTypes.S
io.ex_reg_write_source := MuxLookup(
opcode,
RegWriteSource.ALUResult,
IndexedSeq(
InstructionTypes.L -> RegWriteSource.Memory,
Instructions.csr -> RegWriteSource.CSR,
Instructions.jal -> RegWriteSource.NextInstructionAddress,
Instructions.jalr -> RegWriteSource.NextInstructionAddress
)
)
io.ex_reg_write_enable := (opcode === InstructionTypes.RM) || (opcode === InstructionTypes.I) ||
(opcode === InstructionTypes.L) || (opcode === Instructions.auipc) || (opcode === Instructions.lui) ||
(opcode === Instructions.jal) || (opcode === Instructions.jalr) || (opcode === Instructions.csr)
io.ex_reg_write_address := rd
io.ex_csr_address := io.instruction(31, 20)
io.ex_csr_write_enable := (opcode === Instructions.csr) && (
funct3 === InstructionsTypeCSR.csrrw || funct3 === InstructionsTypeCSR.csrrwi ||
funct3 === InstructionsTypeCSR.csrrs || funct3 === InstructionsTypeCSR.csrrsi ||
funct3 === InstructionsTypeCSR.csrrc || funct3 === InstructionsTypeCSR.csrrci
)
}

View File

@@ -0,0 +1,47 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package riscv.core.threestage
import chisel3._
import chisel3.util.MuxCase
import riscv.Parameters
object ProgramCounter {
val EntryAddress = Parameters.EntryAddress
}
class InstructionFetch extends Module {
val io = IO(new Bundle {
val jump_flag_ex = Input(Bool())
val jump_address_ex = Input(UInt(Parameters.AddrWidth))
val rom_instruction = Input(UInt(Parameters.DataWidth))
val instruction_valid = Input(Bool())
val instruction_address = Output(UInt(Parameters.AddrWidth))
val id_instruction = Output(UInt(Parameters.InstructionWidth))
})
val pc = RegInit(ProgramCounter.EntryAddress)
pc := MuxCase(
pc,
IndexedSeq(
io.jump_flag_ex -> io.jump_address_ex,
io.instruction_valid -> (pc + 4.U)
)
)
io.instruction_address := pc
io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
}

Binary file not shown.

184
lab3/要求.txt Normal file
View File

@@ -0,0 +1,184 @@
实验三 流水线 CPU🚁
在完成单周期 CPU 实验后,你已经对 CPU 的原理和结构已经有了基本的了解。但单周期的 CPU 设计中,关键路径太长,频率难以提升,并且每个时钟周期只能执行一条指令,指令吞吐率低。下面,我们将尝试使多条指令重叠执行(即流水线技术)来解决这个问题。
竞争冒险的处理是流水线 CPU 设计的难点和关键所在。在下面的实验中,我们首先设计一个简单的三级流水线 CPUIF、ID 和 EX 三级),它只涉及分支和跳转指令带来的控制冒险,处理起来较为简单;然后,我们再将三级流水线 CPU 的 EX 级继续切分为 EX、MEM 和 WB形成经典的五级流水线这样做带来的数据冒险需要使用阻塞和转发技术进行处理最后我们将分支和跳转提前到 ID 阶段,进一步缩短分支延迟。
本实验中五级流水线 CPU 的架构与 Computer Organization and Design, RISC-V Edition 中的流水线 CPU 架构基本相同,读者可同时参考此书第 4.5~4.8 节。
在本实验中,你将学习到:
使用流水线设计缩短关键路径
正确处理流水线阻塞与清空
使用转发逻辑减少流水线阻塞
不管使用 IDE 还是执行命令,根目录是 lab3 文件夹。
流水线寄存器🚁
流水线寄存器是在流水线中起缓存作用的寄存器,目的是切分组合逻辑,缩短关键路径。它的基本功能非常简单,在每一个时钟周期,根据复位(流水线清空)或阻塞(流水线暂停)的状态,将寄存器内容清空、保持或设置为新的值。寄存器的输出则是寄存器中保存的值。为了方便复用,我们可以定义一个带参数的 PipelineRegister 模块,用来实现不同数据位宽的流水线寄存器。
实验代码已经在 src/main/scala/riscv/core/PipelineRegister.scala 中定义好了模块接口stall 和 flush 分别为流水线寄存器的阻塞和清空信号in 和 out 分别为要写入寄存器的值和寄存器的当前值。
实验任务: 实现流水线寄存器
请你修改 // Lab3(PipelineRegister) 注释处的代码,使其能通过 PipelineRegisterTest 测试。
提示
在完成此题时你可以暂时抛开 CPU只需要用实验零中的基础知识完成上述功能即可最低所需代码不超过 7 行,请将它当作一道简单的开胃菜享用吧!
三级流水线🚁
下面是三级流水线 CPU 的结构图,数据通路用蓝线表示,控制信号用红线表示。
three_stage_pipelined_CPU_structure
我们用 IF2ID 和 ID2EX 这两组流水线寄存器将单周期 CPU 的组合逻辑部分切分为三个阶段:
取指Instruction FetchIF根据 PC 中的指令地址从内存中取出指令码;
译码Instruction DecodeID将指令码解码为控制信号并从寄存器组中读取操作数
执行ExecuteEX包括 ALU 运算、访问内存和结果写回。
这三个阶段的代码与单周期 CPU 大同小异,所以我已经帮你写好啦,接下来让我们把主要精力放在处理竞争冒险上。
解决控制冒险:清空🚁
在三级流水线中,由于所有数据处理操作都在 EX 阶段进行,因此不存在数据冒险,我们只需要处理程序跳转带来的控制冒险。有三种情况可能发生程序跳转:
EX 段执行到跳转指令
EX 段执行到分支指令且分支条件成立
发生中断EX 段收到 CLINT 发来的 InterruptAssert 信号,这相当于在 EX 段的指令之上叠加了一条跳转指令EX 段的指令继续执行IF 段和 ID 段的指令将被丢弃
无论哪种情况,都是由 EX 段向 IF 段发送跳转信号 jump_flag 和跳转的目标地址 jump_address但在 jump_address 写入 PC 并从该处取出指令前,流水线的 IF 和 ID 段已经各有两条不需要执行的指令,好在这两条指令的结果还没有写回,我们只需要清空对应的流水线寄存器,把它们变成两条空指令即可。
实验任务:支持三级流水线的控制冒险
我们用一个控制单元来检测控制冒险并清空流水线,模块定义在 src/main/scala/riscv/core/threestage/Control.scala为了避免此题过于简单我们没有提供模块接口请根据以上分析确定模块的输入输出在 // Lab3(Flush) 处将代码补充完整,并在 src/main/scala/riscv/core/threestage/CPU.scala 的 // Lab3(Flush) 处补充相关连线,使其能够通过 ThreeStageCPUTest 测试。
五级流水线🚁
在三级流水线中,执行阶段逻辑复杂,仍然可能导致较大的延迟。为了进一步缩短关键路径,我们可以扩展流水线级数,将执行阶段进一步分为 ALU 阶段、访存阶段以及写回阶段,如下图所示。
five_stage_pipelined_CPU_structure
把三级流水线进一步分割为五级流水线将带来更加复杂的数据冒险,下面我们将尝试使用阻塞的方式解决数据冒险,得到一个功能完整的五级流水线 CPU。接着我们可以使用旁路和将分支跳转提前到 ID 阶段进一步提升 CPU 效率,这两部分将作为拓展实验供同学们选做。注意,上面的 CPU 结构图是我们完成所有实验之后的结果,在完成“缩短分支延迟”实验之前,我们 CPU 的结构将与上图稍有不同。例如,我们紧接着讨论的五级流水线 CPU 在 EX 阶段判断程序是否发生跳转,而不是 ID 阶段。
解决数据冒险:阻塞🚁
当处于 ID 阶段的指令要读取的寄存器依赖于 EX 或 MEM 阶段的指令时,发生数据冒险。此时,我们可以保持 IF 和 ID 两个阶段状态不变,直到被依赖的指令执行完成,即 ID 段能够从寄存器组获得它所需要的数据,再继续执行。让我们考虑如下指令序列,并思考几个问题:
0000: add x1, x0, x0
0004: sub x2, x0, x1
0008: and x3, x1, x2
000C: jalr x4, x1, 0
0010: or x5, x3, x4
0014: xor x6, x4, x5
假设没有阻塞,它们在流水线中的状态如下:
时钟周期 0 1 2 3 4 5 6
IF add sub and jalr or xor
ID add sub and jalr or xor
EX add sub and jalr or
MEM add sub and jalr
WB add sub and
在第 2 个时钟周期,指令 sub x2, x0, x1 处于 ID 阶段,需要从寄存器组读出它的源操作数,但它的源操作数依赖于前一条指令,且前一条指令的结果还没有写回,需要阻塞;同理,在第 3 个时钟周期,指令 and x3, x1, x2 需要读取的源操作数依赖于前两条指令,也需要阻塞;但是这两条指令分别需要阻塞多少个时钟周期?
在第 4 个时钟周期,指令 jalr x4, x1, 0 处于 ID 阶段,它的源操作数依赖于处于 WB 阶段的指令的结果,此时需不需要阻塞?
最后两条指令的源操作数同样依赖于前面的指令,这两条指令需不需要阻塞?
请你先思考片刻,下面我将给出阻塞后的流水线状态并作分析:
时钟周期 0 1 2 3 4 5 6 7 8 9 10
IF add sub and and and jalr jalr jalr or xor add
ID add sub sub sub and and and jalr or nop
EX add nop nop sub nop nop and jalr nop
MEM add nop nop sub nop nop and jalr
WB add nop nop sub nop nop and
位于 ID 阶段的指令和位于 WB 阶段的指令之间不会发生数据冒险,这是因为我们的寄存器组模拟实现了 Double Pumping 功能,即 WB 阶段在前半个时钟周期向寄存器组写入数据ID 阶段在后半个时钟周期从寄存器组读出数据,请你打开 src/main/scala/riscv/core/RegisterFile 查看相关代码。因此,在上面的例子中,对 sub 和 and 指令的阻塞只需持续到它们依赖的指令进入 WB 阶段即可,而 jalr 指令无需阻塞。
值得注意的是,我们在阻塞 PC 和 IF2ID 寄存器以保持 IF 和 ID 阶段不变的同时,需要清空 ID2EX 寄存器以在 EX 阶段插入空指令(“气泡”),否则 ID 阶段的指令还是会进入 EX 阶段,这样就不是“阻塞”,而变成“重复”了。
另外jalr 是跳转指令,虽然它后面两条指令依赖于它写入的寄存器,但是它们本就不应该紧接着被执行,而是应该被清空,所以在第 10 个时钟周期应该清空 IF2ID 和 ID2EX 寄存器,而不是阻塞。(上表中加粗的 nop 表示因清空信号而插入的空指令,未加粗的 nop 表示从上一个流水段进入下一个流水段的空指令。)
特别提示:除了以上讨论的情况之外,寄存器 x0 在 risc-v 中具有特殊作用,以它为目标寄存器的指令的结果将被丢弃、以它为输入寄存器的指令也不会在相应输入寄存器结果上产生依赖。 也就是说,目标或输入寄存器为 x0 时,该寄存器的结果无需阻塞。
借用这一特点,我们对判断依赖和产生阻塞时约定:一条指令至多涉及两个输入寄存器 rs1 和 rs2 ,以及一个目标寄存器 rd 。若某一格式的指令不包含这些寄存器的某一个时,如 I-type 指令不含 rs2由 Decoder 输出相应寄存器地址为 0即 x0 。该约定不会影响指令的正确执行,其由 ALUOpSource 选择正确的输入,同时也不会使流水线控制错误产生阻塞。
实验任务:用阻塞解决数据冒险
我们在 src/main/scala/riscv/core/fivestage_stall/InstructionDecode.scala 中留下了相应接口,请根据上述约定使 ID 输出合适的寄存器地址,以供后续冒险分析。完成后应能通过 DecoderStallTest 测试。
我们用一个控制单元来检测并解决控制冒险和数据冒险,模块接口已经定义在 src/main/scala/riscv/core/fivestage_stall/Control.scala请根据以上分析修改 // Lab3(ThreeStage) 处的代码,使其能够通过 FiveStageCPUStallTest 测试。
拓展:使用旁路减少阻塞🚁
至此,我们已经解决完所有竞争冒险,做出一个功能基本完整的五级流水线 CPU 了!但是,对同一个寄存器的连续操作在程序中是非常常见的,如果只使用阻塞来解决数据冒险,将产生大量“气泡”,降低执行效率。
实际上,我们可以直接从流水线寄存器中直接获得指令的执行结果,并不需要阻塞直到前面的指令把结果写入寄存器组后再从寄存器组读取,即在 EX 段和 EX2MEM、MEM2WB 这两组流水线寄存器之间建立“旁路”,让 EX 段可以直接获取前面指令的执行结果。我们考虑如下指令序列:
0000: addi x1, x0, 1
0004: sub x2, x0, x1
0008: and x2, x1, x2
000C: lw x2, 4(x2)
0010: or x3, x1, x2
下表是建立了旁路后的流水线状态,我们增加了 EX2MEM 和 MEM2WB 两行用来表示暂存在流水线寄存器中的执行结果。
时钟周期 0 1 2 3 4 5 6 7
IF addi sub and lw or
ID addi sub and lw or
EX addi sub and lw or or
EX2MEM addi: x1 sub: x2 and: x2
MEM addi sub and lw nop
MEM2WB addi: x1 sub: x2 and: x2 lw: x2
WB addi sub and lw
虽然第二条指令 sub x2, x0, x1 依赖于前一条指令的执行结果,但是在第 3 个时钟周期,位于 EX 段的 sub 指令可以直接从 EX2MEM 寄存器中获取第一条指令执行后 x1 寄存器的值作为它的源操作数而无需阻塞;同样地,第三条指令依赖于前两条指令,在第 4 个时钟周期,位于 EX 段的 and 指令可以从 EX2MEM 和 MEM2WB 中获取它的源操作数。值得注意的是,在第 5 个时钟周期EX2MEM 和 MEM2WB 中都存有 x2 的值,此时我们应该取“最新”的那个,也就是位于 EX2MEM 中的值。在第 6 个时钟周期,情况有些不同,因为第四条指令是 load 指令,它需要等到 MEM 阶段结束才能得到结果,因此处于 EX 段的 or 指令无法从 EX2MEM 中获取它的源操作数,必须阻塞一个时钟周期后从 MEM2WB 中获取。
实验任务:用旁路减少阻塞
InstructionDecode中的实现与五级阻塞流水线CPU基本一致你可以复制前面填好的内容。
我们用一个控制单元来处理流水线的阻塞和清空,模块接口已经定义在 src/main/scala/riscv/core/fivestage_forward/Control.scala再用一个旁路单元来检测数据冒险并发出旁路控制信号模块接口已经定义在 src/main/scala/riscv/core/fivestage_forward/Forwarding.scala另外还需要在执行单元src/main/scala/riscv/core/fivestage_forward/Execute.scala中根据旁路单元的控制信号使用对应的旁路数据。请你根据以上分析修改上述三个模块中 // Lab3(Forward) 处的代码,使其能够通过 FiveStageCPUForward 测试。
提示:你可以复用上道题中 Control 模块的部分代码;如果对模块接口中某个信号的功能有疑惑,可参考上面的 CPU 结构图,或做出你认为合理的修改并简要记录在报告中。
拓展:缩短分支延迟🚁
我们已经利用旁路将数据冒险带来的损失降低到至多一个时钟周期了,但你也许对与目前流水线的效率还是不太满意,因为每次跳转都需要浪费两个时钟周期。接下来,我们往 CPU 中加入少量硬件,将分支/跳转指令的执行从 EX 段提前到 ID 段,进而把程序跳转的损失减少到一个时钟周期。
首先,我们需要把跳转的判断从 EX 段移到 ID 段;其次,跳转目标地址的计算是使用 EX 段的 ALU 进行的,因此我们需要给 ID 段增加一个加法器来计算目标地址;最后,我们需要添加额外的旁路逻辑,将前面指令的执行结果旁路到 ID 段给分支或跳转指令使用,如果所依赖的结果还没有产生,还需要进行阻塞。作为本实验的最后一题,我不再为你提供数据冒险的指令序列样例,请你自行考虑其他所有类型的指令与分支或跳转指令的搭配,找出其中的竞争冒险并进行解决。
实验任务:缩短分支延迟
我们已经为你定义好相关模块的接口并移除了 Execute 模块中分支和跳转的相关代码,请你修改 src/main/scala/riscv/core/fivestage_final 下的 InstructionDecode.scala、Control.scala 和 Forwarding.scala 中 // Lab3(Final) 处的代码,使其能够通过 FiveStageCPUFinal 测试。你可以复制上道题中相应代码并作修改。
提示:如何有效 debug🚁
五级流水线 CPU 已经较为复杂,实现过程中的小错误都有可能导致结果出错。本小节为您提供如何有效 debug 的提示。
debug 时应当从小和简单的内容开始逐步排除再考虑更复杂的内容。基础的检查包括检查是否有文件还没有填写实现代码如ID的代码未从前一步复制过来、检查是否有拼写错误或错用名字相近的信号线 等。
排除这些后,再考虑更复杂的可能性,其中重要的一步是 用最少的内容复现错误,这样可以排除更多的无关变量。在五级流水线三个小实验的 CPUTest 中,最简单的测试是 “store and load single byte” 测试,其代码在 csrc/sb.S仅十几条汇编指令。如果您的 CPU 在不能通过该测试,您可以通过这些方法排查错误:
打印🚁
在一些关键部件处进行打印,如
class RegisterFile extends Module {
// ......
// DEBUG
val debug_clk_cnt = RegInit(0.U(32.W))
debug_clk_cnt := debug_clk_cnt + 1.U
when (io.write_enable) {
printf(cf"[Reg] at clock ${debug_clk_cnt} write to register ${io.write_address}: 0x${io.write_data}%x\n\n")
}
}
其在寄存器写使能有效时,打印所写入的值。 其中 printf 为 Chisel3 提供的打印函数, cf 为字符串插值器,可以在字符串里直观地打印,详见 Printing in Chisel。
该方法需要找到某个容易看出错误根源的部件如寄存器、MEM 等。
TODO查看输出截图
查看波形图🚁
可以用 GTKWave 查看波形图并进行分析。TODOGTKWave 教程。
充分利用提示🚁
一般而言,本实验设计上不要求非常深入、复杂的 debug因而会在部件的输入信号上予以提示即不会引入多余的输入信号。您可以了解这些输入信号的含义并查看其是否被您的代码利用上。
实验没有提供 Control 或 Forwarding 的单元测试,这是因为它们逻辑并不复杂,提供单元测试相当于给出了答案。为找出错误,可以按照如下框架进行思考:首先,五级流水线中,当前指令处于 EX 时,至多依赖于前两条指令,前面第三条指令已经完成并退出流水线; 同时依赖于前两条指令时,两条指令的目标寄存器是否相同 。其次,被依赖的指令可能在 EX 阶段得到其结果,也可能在 MEM 阶段得到。综合这两个维度,您应考虑其组合下的所有情况:
考虑情况表
上表适用于 Stall 和 Forwarding 两个小实验,对于缩短分支延迟,由于又在 ID 阶段引入了依赖,上表还需翻倍,分别对当前时钟周期下 ID 和 EX 阶段的指令进行讨论。
烧板验证🚁
如果你已经完成了所有基础实验,那么你的 CPU 应该能够运行简单的程序,你可以通过 Top 模块中传入 CPU 模块构造函数的参数来选择你要使用的 CPU 版本:如果你只完成了基础实验,请选择 ImplementationType.FiveStageStall如果你完成了第一个拓展实验请选择 ImplementationType.FiveStageForward如果你完成了第二个拓展实验请选择 ImplementationType.FiveStageFinal。
实验报告🚁
简述您已实现的最复杂 CPU 的关键思路,包括 Contrl 和 Forwarding如果有的控制逻辑。
实验中没有特别讨论 CSR 指令的控制和数据冒险,请您简要分析 CSR 指令是否会产生上述冒险,并是否需要特别的处理措施。
说明您在完成实验的过程中,遇到的实验指导不足或改进建议。

View File

@@ -158,7 +158,7 @@ class AXI4LiteSlave(addrWidth: Int, dataWidth: Int) extends Module {
switch(state) { switch(state) {
is(AXI4LiteStates.Idle) { is(AXI4LiteStates.Idle) {
// 默认:清除控制信号 // 默认信号
ARREADY := false.B ARREADY := false.B
RVALID := false.B RVALID := false.B
AWREADY := false.B AWREADY := false.B
@@ -168,7 +168,7 @@ class AXI4LiteSlave(addrWidth: Int, dataWidth: Int) extends Module {
write := false.B write := false.B
// 优先响应读请求
when(io.channels.read_address_channel.ARVALID) { when(io.channels.read_address_channel.ARVALID) {
addr := io.channels.read_address_channel.ARADDR addr := io.channels.read_address_channel.ARADDR
ARREADY := true.B ARREADY := true.B
@@ -192,7 +192,7 @@ class AXI4LiteSlave(addrWidth: Int, dataWidth: Int) extends Module {
read := true.B read := true.B
when(io.bundle.read_valid && !RVALID) { when(io.bundle.read_valid && !RVALID) {
// 设备已经准备好数据,将其锁存并拉高 RVALID // 设备已经准备好数据,将其锁存并RVALID为1
rdataReg := io.bundle.read_data rdataReg := io.bundle.read_data
RVALID := true.B RVALID := true.B
}.elsewhen(RVALID && io.channels.read_data_channel.RREADY) { }.elsewhen(RVALID && io.channels.read_data_channel.RREADY) {

View File

@@ -0,0 +1,31 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\@writefile{toc}{\contentsline {section}{\numberline {1}实验目的}{1}{section.1}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2}实验环境}{1}{section.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {3}实验原理}{1}{section.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}AXI4-Lite 协议概述}{1}{subsection.3.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}通信框架}{2}{subsection.3.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}握手机制}{2}{subsection.3.3}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {4}模块实现与分析}{2}{section.4}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}状态机设计}{2}{subsection.4.1}\protected@file@percent }
\@writefile{lol}{\contentsline {lstlisting}{\numberline {1}状态定义}{2}{lstlisting.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}AXI4LiteMaster 实现}{3}{subsection.4.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.1}主机状态机逻辑}{3}{subsubsection.4.2.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.2.2}关键代码实现}{3}{subsubsection.4.2.2}\protected@file@percent }
\newlabel{lst:master_core}{{2}{3}{主机状态机核心代码}{lstlisting.2}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {2}主机状态机核心代码}{3}{lstlisting.2}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}AXI4LiteSlave 实现}{4}{subsection.4.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.1}从机状态机逻辑}{4}{subsubsection.4.3.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {4.3.2}关键代码实现}{4}{subsubsection.4.3.2}\protected@file@percent }
\newlabel{lst:slave_core}{{3}{4}{从机状态机核心代码}{lstlisting.3}{}}
\@writefile{lol}{\contentsline {lstlisting}{\numberline {3}从机状态机核心代码}{4}{lstlisting.3}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}性能优化}{5}{subsection.4.4}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {5}CSR 指令与总线交互}{5}{section.5}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {6}测试结果与分析}{6}{section.6}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}测试原理}{6}{subsection.6.1}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {6.2}分析}{6}{subsection.6.2}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {7}改进建议}{6}{section.7}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {8}实验结论}{6}{section.8}\protected@file@percent }
\gdef \@abspage@last{7}

View File

@@ -0,0 +1,265 @@
# Fdb version 4
["pdflatex"] 1766329011.89127 "e:/jizu/2025-fall-yatcpu-repo/lab4/实验报告/lab4_report.tex" "lab4_report.pdf" "lab4_report" 1766329017.28266 2
"C:/Users/26586/AppData/Local/MiKTeX/fonts/map/pdftex/pdftex.map" 1765351489.73151 80909 eab91d9745dd2edfd62a31d53cd5fe15 ""
"C:/Users/26586/AppData/Local/MiKTeX/fonts/pk/ljfour/jknappen/ec/dpi600/tcrm1200.pk" 1760284205.24029 14064 0435e595d6b2364a10c98a375d33de30 ""
"C:/Users/26586/AppData/Local/MiKTeX/miktex/data/le/pdftex/pdflatex.fmt" 1765351984.22676 13286807 d014ff17da888b7ca0b84b7eef16412c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/UGBK.sfd" 1458473944 185547 3920f4d0519124bae1340c8047ea76bc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/sfd/ttf2pk/Unicode.sfd" 1458473944 107591 5aa427daaa6489b60892769618bdfe76 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/jknappen/ec/tcrm1200.tfm" 993062508 1444 95ffe0f19b974d50849790c8225c7ef7 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1233951848 1004 54797486969f23fa377b128694d548df ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1233951848 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmbx12.tfm" 1136765053 1324 c910af8c371558dc20f2d7822f66fe64 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmex10.tfm" 1136765053 992 662f679a0b3d2d53c1b94050fdaa3f50 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmmi12.tfm" 1136765053 1524 4414a8315f39513458b80dfc63bff03a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmmi6.tfm" 1136765053 1512 f21f83efb36853c0b70002322c1ab3ad ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmmi8.tfm" 1136765053 1520 eccf95517727cb11801f4f1aee3a21b4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmr10.tfm" 1136765053 1296 45809c5a464d5f32c8f98ba97c1bb47f ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmr12.tfm" 1136765053 1288 655e228510b4c2a1abe905c368440826 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmr17.tfm" 1136765053 1292 296a67155bdbfc32aa9c636f21e91433 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmr6.tfm" 1136765053 1300 b62933e007d01cfd073f79b963c01526 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmr8.tfm" 1136765053 1292 21c1c5bfeaebccffdb478fd231a0997d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmsy10.tfm" 1136765053 1124 6c73e740cf17375f03eec0ee63599741 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmsy6.tfm" 1136765053 1116 933a60c408fc0a863a92debe84b2d294 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmsy8.tfm" 1136765053 1120 8b7d695260f3cff42e636090a8002094 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmtt10.tfm" 1136765053 768 1321e9409b4137d6fb428ac9dc956269 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmtt12.tfm" 1136765053 772 9a936b7f5e2ff0557fce0f62822f0bbf ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/public/cm/cmtt8.tfm" 1136765053 768 d7b9a2629a0c353102ad947dc9221d49 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs30.tfm" 1247154072 1172 4e2cfca8ad02497ba658b4c090adccff ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs4e.tfm" 1247154072 1172 66721f51f04999b1ba30917a08b01c8c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs4f.tfm" 1247154072 1172 c12a8ce0fafe677e544834df2468041f ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs51.tfm" 1247154072 1172 fb1d3bd240b471452891f42887192d13 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs52.tfm" 1247154072 1172 0963ffe9c2e76e7b6925a1bde177bd42 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs53.tfm" 1247154072 1172 7228a869cb817b7d888ab43e0d269259 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs54.tfm" 1247154072 1172 3fb17769b1ebc198fca44ab9c6c852ac ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs56.tfm" 1247154072 1172 141b3731011a50c51d5d6b8827304282 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs57.tfm" 1247154072 1172 1294d8c0b8a209ee8ed70c57a6da1903 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs5b.tfm" 1247154072 1172 7c814a9e60373cd703dc2fc186e21ebc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs5f.tfm" 1247154072 1172 9ff40c0cbd1482ad98eae027b37631cc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs60.tfm" 1247154072 1172 235d7e5a6fc89c05f1a4122b4907fb70 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs62.tfm" 1247154072 1172 c0b6404b0c47619f5633fcea76672f68 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs63.tfm" 1247154072 1172 133c1833fb153408886bd45a32b088c7 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs65.tfm" 1247154072 1172 f7e3e3697ffcd2b4275e3af6d3c25c95 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs67.tfm" 1247154072 1172 2ac51daa11cb49d568b65a81bc53ad8e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs72.tfm" 1247154072 1172 51f882130cc57719f5641660233dd648 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs77.tfm" 1247154072 1172 bfe9c157cf002926fb65a115992ff876 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs7b.tfm" 1247154072 1172 e71675c5c52fe1114c3609053be64137 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs8b.tfm" 1247154072 1172 d45a7893cb5d4d1acc86184ee0617a85 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs8f.tfm" 1247154072 1172 d3169b8d0b2839b5570b2ad9ce365b23 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs90.tfm" 1247154072 1172 63753d3b531b7077241c60884c9ae88b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs95.tfm" 1247154072 1172 54d017607422ccadcffc744cbcf140a9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs96.tfm" 1247154072 1172 43c87819da51988a0bdbb563a6f1ab1c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifs9a.tfm" 1247154072 1172 3d71a8422b1120012fe2f849914fee8c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unifs/unifsff.tfm" 1247154072 1172 2b17821dccd4868270761aab4643f93d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei30.tfm" 1247154072 1172 18ad1097cc3f3c36c758d33bf2dd19bd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei4e.tfm" 1247154072 1172 2d5e87dd6ec409d864e1fe1662d00646 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei4f.tfm" 1247154072 1172 d30a5fea134273110a27f48164b06e0c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei51.tfm" 1247154072 1172 7ee56fddd7b8de24477f743547fdf508 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei52.tfm" 1247154072 1172 481a000690ef15d58de2a93b3c34574c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei53.tfm" 1247154072 1172 a5c37c86ae9131b27b9c0199f3d12df2 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei54.tfm" 1247154072 1172 d48fa656debc44b54635777f72473a7c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei56.tfm" 1247154072 1172 3d70386494675a81e9a6697b900ec8a8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei57.tfm" 1247154072 1172 22fcff286e20a86fd370e6e42f5ce3ce ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei58.tfm" 1247154072 1172 72bdd9760fa9bdd25369ae236dd1ab29 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei59.tfm" 1247154072 1172 cb2089a3c8bd5826b7666fffdf326cbc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei5b.tfm" 1247154072 1172 2120666fa3540653fd1185d802592022 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei5d.tfm" 1247154072 1172 ad3b1e5fc915d97e4a51b8667388e1de ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei5e.tfm" 1247154072 1172 43d03c144e7fffa57074d64aa459c451 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei5f.tfm" 1247154072 1172 7048f0a8b693444590781debe54eecbd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei60.tfm" 1247154072 1172 96cb70e1efefba6c98e5b547e0d33833 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei62.tfm" 1247154072 1172 3b0f7c4bc785f23eefed0160e713cd09 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei63.tfm" 1247154072 1172 fff11ea27394506a041a526a495f9652 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei64.tfm" 1247154072 1172 abd4be36b7787f9979caadfeef9cdae5 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei65.tfm" 1247154072 1172 c34b1545992ab0d7393a03f889ceeb86 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei66.tfm" 1247154072 1172 023ac6647c726f082a8ecd4350d68793 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei67.tfm" 1247154072 1172 127372bbba8b4f4a65a26e565c0c6a2e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei68.tfm" 1247154072 1172 a6e39128d14a2d8e22ed8239e864feff ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei69.tfm" 1247154072 1172 5ff5aedb967b76341e9dd27872cc92b0 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei6a.tfm" 1247154072 1172 ea35fa13ee483c308a0c68cffa2f52fb ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei6b.tfm" 1247154072 1172 865a135040ed6ad7a3ce493fd0108ece ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei6c.tfm" 1247154072 1172 7dd7a6f05321dd25f399ebba47f53887 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei6d.tfm" 1247154072 1172 e5be6419407f0c8504254055afe6a633 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei72.tfm" 1247154072 1172 0743ca7a73b589a0a7b7707340e6c407 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei73.tfm" 1247154072 1172 04594028df286605c5e043f49c67e7c6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei74.tfm" 1247154072 1172 a9c6136b4c7ff7b154a76d1701531b59 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei76.tfm" 1247154072 1172 717e1aab695517230a61456b5d0d4ae0 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei77.tfm" 1247154072 1172 e79da86bd1270a9d0d9c14bd9641a9f1 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei78.tfm" 1247154072 1172 f839ed6c9e325affc7a6f8b3ce684108 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei7a.tfm" 1247154072 1172 8e66b7d5a581fb748da225cc80739f0e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei7c.tfm" 1247154072 1172 9e4fe5216b40afa8ffc6c259528a5985 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei7e.tfm" 1247154072 1172 fc758d34799896087d8800c18ce979f8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei80.tfm" 1247154072 1172 7c53005410278de6d612480963dd5ced ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei89.tfm" 1247154072 1172 364fffd8ea27d98d6edb9222bf84c180 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei8b.tfm" 1247154072 1172 bdf00141a2e7bd9848cfb6dae5c7e1ef ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei8c.tfm" 1247154072 1172 d7fb4fbe30ca7c33dda3dd09f420024a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei8f.tfm" 1247154072 1172 e5ac568cbbb10c21a8919c10147ccf70 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei90.tfm" 1247154072 1172 bf3a9ea28c06174042dcd642737f0ad2 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei95.tfm" 1247154072 1172 5a7e9ba612e7803abcac167ef6c5a665 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/unihei9a.tfm" 1247154072 1172 8ba4cc771068baafaef7437667c8184d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unihei/uniheiff.tfm" 1247154072 1172 753ad64262b81ffe372ea0e0ce61c8b9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong30.tfm" 1247154072 1172 87d6ba1aff8b955258f6ef7a5d8e86e5 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong4e.tfm" 1247154072 1172 89be830028b08964827966f204abf065 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong4f.tfm" 1247154072 1172 dd7ec0fe171ece0b66015cb8929849f0 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong51.tfm" 1247154072 1172 c46d453988a7d703c4f5c5104bb894f0 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong52.tfm" 1247154072 1172 ebad2f047d83d1be72706895f11e9896 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong53.tfm" 1247154072 1172 e2a03d4bc65395303b42aaff9aacd7be ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong54.tfm" 1247154072 1172 c93f9362e45903cde8748b054b30ab56 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong55.tfm" 1247154072 1172 3c2677828bb3b2231f72896b373b851c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong56.tfm" 1247154072 1172 483bbebc510ee17933c3af062965b6d4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong57.tfm" 1247154072 1172 eb821bcbfd385c0d470afef6ff6ac95b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong58.tfm" 1247154072 1172 9097e54d4337c7af2506271a2618d1d8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong59.tfm" 1247154072 1172 2aa8dc9bdcfa6684a19d81e71fa8a3e1 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong5b.tfm" 1247154072 1172 449ef25f4dcd447addb8325f7bf12b2a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong5c.tfm" 1247154072 1172 bbe7d94072c5d308e673fac2512329ac ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong5d.tfm" 1247154072 1172 1fd8042971efdf7ea35b87f9c6c10b8b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong5e.tfm" 1247154072 1172 19d2fe591b31a07314df704f4d4d5035 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong5f.tfm" 1247154072 1172 e4d92bc2f617835508003ad811702c49 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong60.tfm" 1247154072 1172 7b3876cac8e97dc2d0915ac00b6e4c26 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong62.tfm" 1247154072 1172 9ffac14c72fbc4879502782835fb1e0a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong63.tfm" 1247154072 1172 5558042a53f0a34c54eaf1c8af13f377 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong64.tfm" 1247154072 1172 9123bc1a52f39fa754022a43a1394244 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong65.tfm" 1247154072 1172 2873dd6228ece5c9b075cfdc580febae ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong66.tfm" 1247154072 1172 f300cf9aac35a61638796e3d2ecc0e47 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong67.tfm" 1247154072 1172 bfeea74ab6553bd251ccbd092c04122a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong68.tfm" 1247154072 1172 e36ee82e53889b69220fe0f54fd031bb ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong6a.tfm" 1247154072 1172 00f8a00771908df2108694cbd69134d7 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong6b.tfm" 1247154072 1172 eec47476c8168dac40c6b0d39a32faa4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong6c.tfm" 1247154072 1172 da6dd37ba8d24cc1a36aa510c8ac56f9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong6d.tfm" 1247154072 1172 3942109a9ca7a08ec5324d8eec4093d9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong6e.tfm" 1247154072 1172 42ca517602ab12cb60a5174be463b80a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong72.tfm" 1247154072 1172 3988931ed4f7026bbecd81a5650d7854 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong73.tfm" 1247154072 1172 fd0cb8a34c74e2d27b9d6ceb95f2f96d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong74.tfm" 1247154072 1172 9c784b2c832c4124ae2a4cc407dc47a5 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong75.tfm" 1247154072 1172 402d633b1aba150cdcd663d684057796 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong76.tfm" 1247154072 1172 44cc15829d76f419e5a8bac63a8fed30 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong77.tfm" 1247154072 1172 700f8f915e90952a352eb230ae635c92 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong78.tfm" 1247154072 1172 7693562f5e83d5e3f5e32b3aa27065f6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong79.tfm" 1247154072 1172 ce37048b43f744f562318164cad22210 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong7a.tfm" 1247154072 1172 f8375167264f31944f2511f305972138 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong7b.tfm" 1247154072 1172 11ddb11e6fbba10bd31629a75b0d10c6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong7c.tfm" 1247154072 1172 244f58522afea40d9573f43f05491e74 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong7e.tfm" 1247154072 1172 c58659cf25f9ba2d1c548f969b16af79 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong80.tfm" 1247154072 1172 bc023ebc9b121bce07974f18a4be28bc ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong81.tfm" 1247154072 1172 88aa66087396e79a2d9046555fe05ea9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong83.tfm" 1247154072 1172 7dfd9db201c758b6a39baf9f8fe63ca3 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong88.tfm" 1247154072 1172 e80b61bcc19bffe1009dc0e70ca042e8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong89.tfm" 1247154072 1172 8b185a44b25b68fee81f017ffd4f4c82 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong8b.tfm" 1247154072 1172 cb1829d4415ae14a6d1b42840373e23a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong8c.tfm" 1247154072 1172 ef00399cafeb3f8b6343803347ead58f ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong8d.tfm" 1247154072 1172 766e8f05ddf433a70188e0789a492ab5 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong8e.tfm" 1247154072 1172 9dfad4829b5a6e75e3e50384da3f5d00 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong8f.tfm" 1247154072 1172 39abbbe02586d0f65fa39c19429184a6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong90.tfm" 1247154072 1172 1dd258add692258fd748a53ff76ed075 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong91.tfm" 1247154072 1172 084e1e91aa4ae30efc415c3663943670 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong95.tfm" 1247154072 1172 b83dfb32a9b8d234282a0b11898d2c55 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong96.tfm" 1247154072 1172 97abce3faa5097f1401cb707f6f69600 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong97.tfm" 1247154072 1172 3322410a0eee91e13e02457b09378209 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong98.tfm" 1247154072 1172 0d85b1f7b78508ff1f0a5ef94e0aaca9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisong9a.tfm" 1247154072 1172 37a3cd36cf03e67f393bee80b1370d05 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/tfm/zhmetrics/unisong/unisongff.tfm" 1247154072 1172 156175f4eaa9daea4e21b890ac9fafb8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmbx12.pfb" 1247596666 32080 340ef9bf63678554ee606688e7b5339d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmmi12.pfb" 1247596667 36741 fa121aac0049305630cf160b86157ee4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmmi8.pfb" 1247596666 35469 70d41d2b9ea31d5d813066df7c99281c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmr12.pfb" 1247596667 32722 d7379af29a190c3f453aba36302ff5a9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1247596667 32569 5e5ddc8df908dea60932f3c484a54c0d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmtt10.pfb" 1247596667 31099 c85edf1dd5b9e826d67c9c7293b6786c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmtt12.pfb" 1247596666 24252 1e4e051947e12dfb50fee0b7f4e26e3a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/context/base/mkii/supp-pdf.mkii" 1580390158 71627 94eb9990bed73c364d7f53f960cc8c5b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/bigintcalc/bigintcalc.sty" 1576433602 40635 c40361e206be584d448876bba8a64a3b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/bitset/bitset.sty" 1575926576 33961 6b5c75130e435b2bfdb9f480a09a39f9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/ctex/zhmap/ctex-zhmap-windows.tex" 1657818410 5818 f8fc8b7a2383410fd5810f6ec6565186 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/gettitlestring/gettitlestring.sty" 1576433666 8371 9d55b8bd010bc717624922fb3477d92e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/iftex/ifpdf.sty" 1734114575 480 5778104efadad304ced77548ca2184b1 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/iftex/iftex.sty" 1734114575 7984 7dbb9280f03c0a315425f1b4f35d43ee ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/iftex/ifvtex.sty" 1734114575 1057 525c2192b5febbd8c1f662c9468335bb ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/infwarerr/infwarerr.sty" 1575399508 8356 7bbb2c2373aa810be568c29e333da8ed ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/intcalc/intcalc.sty" 1576433764 31769 002a487f55041f8e805cfbf6385ffd97 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/kvdefinekeys/kvdefinekeys.sty" 1576763304 5412 d5a2436094cd7be85769db90f29250a6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/ltxcmds/ltxcmds.sty" 1702206890 17865 1a9bd36b4f98178fa551aca822290953 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/pdfescape/pdfescape.sty" 1575926700 19007 15924f7228aca6c6d184b115f4baa231 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/pdftexcmds/pdftexcmds.sty" 1623005277 20089 80423eac55aa175305d35b49e04fe23b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/stringenc/stringenc.sty" 1575105840 21514 b7557edcee22835ef6b03ede1802dad4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/generic/uniquecounter/uniquecounter.sty" 1576434012 7008 f92eaa0a3872ed622bbf538217cd2ab7 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/00miktex/epstopdf-sys.cfg" 1616067285 584 2a1075dd71571459f59146da9f7502ad ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/amsmath/amsbsy.sty" 1750428994 2222 27db7d52163edae53881b71ff62e754e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/amsmath/amsgen.sty" 1750428993 4173 1b3e76addfb8afcb47db4811d66e1dc6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/amsmath/amsmath.sty" 1750428995 88401 0c3d1897569ad77cb9d8fb25b0bdf668 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/amsmath/amsopn.sty" 1750428994 4474 c510a88aa5f51b8c773b50a7ee92befd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/amsmath/amstext.sty" 1750428995 2444 9983e1d0683f102e3b190c64a49313aa ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/article.cls" 1749467999 20144 b966087dda3b194755eb460d32e2ef75 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/fix-cm.sty" 1749467999 14741 6ad9efc94c78efc56749b0f059d15546 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/fontenc.sty" 1749467999 5275 2f50a1b91fdc3c2c6ff41843a6854061 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/ifthen.sty" 1749467999 5525 1593ca62a2554dd7423fc8a4e5a82125 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/inputenc.sty" 1749467999 5048 0270515b828149155424600fd2d58ac5 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/size12.clo" 1749467999 8449 8dc66c6c313c8eb2d774af83bca435dd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/base/ts1enc.def" 1749467999 8090 bcb38b4f148e75e16d2c33225dbca53b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/CJK.enc" 1670582841 29591 d67c9aa515f4260cdd60fa9f76d96368 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/CJK.sty" 1670582841 33241 3ee25f21824a4a347866900e5037d6f3 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/CJKspace.sty" 1670582841 2451 fef3f022e9041e00c5a6e0f269d142dd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/CJKutf8.sty" 1670582841 24621 e1c0abd54a87918dd1e31a35b20e99e4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/UTF8/UTF8.bdg" 1670582841 3857 eb1bacae4debef49a730cd935a17d208 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/UTF8/UTF8.chr" 1670582841 8601 48822bfc9ff5adbcc1c7f832dd920f29 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/UTF8/UTF8.enc" 1670582841 6111 5a99517ba8cc0c0905d3c54d7c7bcc48 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjk/mule/MULEenc.sty" 1670582841 12177 48c95ebf85a580326918e5eb490b477b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjkpunct/CJKpunct.spa" 1463194434 7 7979211695692235f48c7d3ba95863ea ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/cjkpunct/CJKpunct.sty" 1463224796 17985 35c6beb757001c750ed764f3ac4ef0d6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/config/ctex-name-utf8.cfg" 1657818410 1770 50e40a993c4c5ea72af9155aff7e605c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/config/ctex.cfg" 1657818410 1230 140911b70e325208170dc573931e772d ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/config/ctexbackend.cfg" 1657818410 1904 e0018b8e661c6b3e37f6e4a53f472d74 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/config/ctexopts.cfg" 1657818410 1291 feb9a19ff907013e8b3014895a284585 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/ctexart.cls" 1657818410 55219 69f0e9646f7b8e2f2ed4c5f3eef59f5c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/ctexhook.sty" 1657818410 6505 33157acfddefdd8fd513e2308e07a435 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/ctexpatch.sty" 1657818410 8448 194e901f66d106236c72ef098b091d00 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/ctexspa.def" 1657818410 10881 81f1c81c512ebcc46745af438dfa73d9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/engine/ctex-engine-pdftex.def" 1657818410 20297 90a9347d15e74883d4c66bd8b9fe695e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/fd/c70rm.fd" 1657818410 1820 94b600cf0e8675b72e2f47cdec13db0a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/fontset/ctex-fontset-windows.def" 1657818410 4952 f781dcade04ad6ae6d09fde004a752be ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/ctex/scheme/ctex-scheme-chinese-article.def" 1657818410 4622 4f152431881516d2a81822d98108b61f ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/enumitem/enumitem.sty" 1738917170 52272 63d293bc0d496619edb57585740861a2 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/epstopdf-pkg/epstopdf-base.sty" 1623003186 13886 d1306dcf79a944f6988e688c1785f9ce ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/etoolbox/etoolbox.sty" 1739279216 46850 d87daedc2abdc653769a6f1067849fe0 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/fancyhdr/fancyhdr.sty" 1740138435 31715 19e60610b63819fe670dfa1cd84a4e94 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/geometry/geometry.cfg" 1578053545 1104 d237cad3f14be9fd91fe1f904d051a01 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/geometry/geometry.sty" 1578053545 42759 e63af52ccddba7489ac0e17d6a3344bd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics-cfg/color.cfg" 1465894292 1213 620bba36b25224fa9b7e1ccb4ecb76fd ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics-cfg/graphics.cfg" 1465894292 1224 978390e9c2234eab29404bc21b268d1e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics-def/pdftex.def" 1713599642 19440 9da9dcbb27470349a580fca7372d454b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/color.sty" 1749322634 7245 a7e8457a46cda4920df85d975267efb4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/graphics.sty" 1749322634 18363 69bb4f5538964bfea50d1e6d89cbe69f ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/graphicx.sty" 1749322634 8118 43b99e52946c33a23f5f43b52d5cc5ec ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/keyval.sty" 1749322634 2671 d9941f4bf4750e9b0603c9a2ec54693b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/mathcolor.ltx" 1749322634 2885 9c645d672ae17285bba324998918efd8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/graphics/trig.sty" 1749322634 4023 e66acf578d6b564c4670fb57ff336a7a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hycolor/hycolor.sty" 1580380792 18571 5a6205e2f490b14bdc73fa03b48f19d6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hyperref/hpdftex.def" 1752319040 48140 5e8a3a4aa88ae09b90d524926a067201 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hyperref/hyperref.sty" 1752319040 223112 93e90b2b1b3ef21af41adaf029922dd3 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hyperref/nameref.sty" 1752319040 11027 0fe7ce2c6b5291fd809c2de7bbdca37e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hyperref/pd1enc.def" 1752319041 14249 e14b403fb70abdf1f6742598a63b0e2a ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/hyperref/puenc.def" 1752319041 117118 e2f5f7983a43f89e2ffcd709fc59d37c ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/kvoptions/kvoptions.sty" 1656236481 22555 6d8e155cfef6d82c3d5c742fea7c992e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/kvsetkeys/kvsetkeys.sty" 1665066333 13815 760b0c02f691ea230f5359c4e1de23a7 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/l3backend/l3backend-pdftex.def" 1751005717 30351 a2b09edc6c93a742566b222c33d0278e ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/l3kernel/expl3.sty" 1758055987 6558 bec0a36183594509927de3d0194841f8 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/listings/listings.cfg" 1741168183 1865 301ae3c26fb8c0243307b619a6aa2dd3 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/listings/listings.sty" 1741168182 81640 997090b6c021dc4af9ee00a97b85c5b4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/listings/lstmisc.sty" 1741168182 77051 be68720e5402397a830abb9eed5a2cb4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/listings/lstpatch.sty" 1741168182 353 9024412f43e92cd5b21fe9ded82d0610 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/refcount/refcount.sty" 1576433952 9878 9e94e8fa600d95f9c7731bb21dfb67a4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/rerunfilecheck/rerunfilecheck.sty" 1751104012 9684 a33a14b82ce60d6e77cb9be689d79ee6 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/url/url.sty" 1388490452 12796 8edb7d69a20b857904dd0ea757c14ec9 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/xcolor/xcolor.sty" 1729265222 55384 b454dec21c2d9f45ec0b793f0995b992 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhmetrics/c70zhfs.fd" 1253728767 998 00d438c2ab2c3d6b03167dfc6defbbd4 ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber-utf8.cfg" 1657817710 5700 603e2f09dad175efabc8594730623a0b ""
"C:/Users/26586/AppData/Local/Programs/MiKTeX/tex/latex/zhnumber/zhnumber.sty" 1657817710 38160 aafa8d740e4f21b62a4acd4835e54359 ""
"C:/WINDOWS/Fonts/msyh.ttc" 1757965193.23002 19704352 fa04b86eb9c632ef04217c3e43d81c4d ""
"C:/WINDOWS/Fonts/simfang.ttf" 1711630440 10580176 decb47e7590859ba54ed4f18208e1ed7 ""
"C:/WINDOWS/Fonts/simhei.ttf" 1711630440 9755440 186b27ff118e04e580eaad8ae78f2420 ""
"C:/WINDOWS/Fonts/simsun.ttc" 1757965193.40189 18070492 1615784d420bffd42e8addd1714f7c6a ""
"e:/jizu/2025-fall-yatcpu-repo/lab4/实验报告/lab4_report.tex" 1766329007.00069 14154 74e01fa76ab2f4386877245dd6ae792d ""
"lab4_report.aux" 1766329015.2437 3240 797e80e1edee136300d79d334ac656f0 "pdflatex"
"lab4_report.out" 1766329015.24672 2148 71433e76451d2b78d790f405cee2e80a "pdflatex"
(generated)
"lab4_report.aux"
"lab4_report.log"
"lab4_report.out"
"lab4_report.pdf"
(rewritten before read)

View File

@@ -0,0 +1,592 @@
PWD E:\jizu\2025-fall-yatcpu-repo\lab4\实验报告
INPUT C:\Users\26586\AppData\Local\MiKTeX\miktex\data\le\pdftex\pdflatex.fmt
INPUT e:\jizu\2025-fall-yatcpu-repo\lab4\实验报告\lab4_report.tex
OUTPUT lab4_report.log
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexart.cls
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexart.cls
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctexbackend.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctexbackend.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctexbackend.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\l3kernel\expl3.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\l3kernel\expl3.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\l3backend\l3backend-pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\l3backend\l3backend-pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\engine\ctex-engine-pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexhook.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexhook.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexpatch.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexpatch.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\fix-cm.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\fix-cm.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\ts1enc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctexopts.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctexopts.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\article.cls
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\article.cls
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\size12.clo
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\size12.clo
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\size12.clo
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\engine\ctex-engine-pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJKutf8.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJKutf8.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\ifpdf.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\ifpdf.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\iftex.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\iftex.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\inputenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\inputenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJK.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJK.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\mule\MULEenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\mule\MULEenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJK.enc
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\fontenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\fontenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjkpunct\CJKpunct.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjkpunct\CJKpunct.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjkpunct\CJKpunct.spa
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjkpunct\CJKpunct.spa
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjkpunct\CJKpunct.spa
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJKspace.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\CJKspace.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.bdg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.bdg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexspa.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\ctexspa.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\hyperref.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhnumber\zhnumber.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhnumber\zhnumber.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhnumber\zhnumber-utf8.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhnumber\zhnumber-utf8.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\scheme\ctex-scheme-chinese-article.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\scheme\ctex-scheme-chinese-article.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctex-name-utf8.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctex-name-utf8.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\fontset\ctex-fontset-windows.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\fontset\ctex-fontset-windows.def
INPUT C:\WINDOWS\Fonts\msyh.ttc
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctex.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\config\ctex.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\geometry\geometry.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\geometry\geometry.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\keyval.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\keyval.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\ifvtex.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\iftex\ifvtex.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\geometry\geometry.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\geometry\geometry.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\geometry\geometry.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\graphicx.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\graphicx.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\graphics.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\graphics.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\trig.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\trig.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\graphics.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\graphics.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\graphics.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-def\pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-def\pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-def\pdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsmath.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsmath.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsopn.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amstext.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amstext.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsgen.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsgen.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsbsy.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsbsy.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\amsmath\amsopn.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\listings.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\listings.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstpatch.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstpatch.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstpatch.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstmisc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstmisc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\lstmisc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\listings.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\listings.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\listings\listings.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\xcolor\xcolor.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\xcolor\xcolor.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\color.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\color.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics-cfg\color.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\mathcolor.ltx
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\mathcolor.ltx
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\mathcolor.ltx
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\hyperref.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\kvsetkeys\kvsetkeys.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\kvsetkeys\kvsetkeys.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\kvdefinekeys\kvdefinekeys.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\kvdefinekeys\kvdefinekeys.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\pdfescape\pdfescape.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\pdfescape\pdfescape.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\ltxcmds\ltxcmds.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\ltxcmds\ltxcmds.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\pdftexcmds\pdftexcmds.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\pdftexcmds\pdftexcmds.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\infwarerr\infwarerr.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\infwarerr\infwarerr.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hycolor\hycolor.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hycolor\hycolor.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\nameref.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\nameref.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\refcount\refcount.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\refcount\refcount.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\gettitlestring\gettitlestring.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\gettitlestring\gettitlestring.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\kvoptions\kvoptions.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\kvoptions\kvoptions.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\etoolbox\etoolbox.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\etoolbox\etoolbox.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\stringenc\stringenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\stringenc\stringenc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\pd1enc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\pd1enc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\pd1enc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\intcalc\intcalc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\intcalc\intcalc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\puenc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\puenc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\puenc.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\url\url.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\url\url.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\bitset\bitset.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\bitset\bitset.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\bigintcalc\bigintcalc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\bigintcalc\bigintcalc.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\hpdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\hpdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\hyperref\hpdftex.def
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\rerunfilecheck\rerunfilecheck.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\rerunfilecheck\rerunfilecheck.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\uniquecounter\uniquecounter.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\uniquecounter\uniquecounter.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\fancyhdr\fancyhdr.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\fancyhdr\fancyhdr.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\enumitem\enumitem.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\enumitem\enumitem.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\ifthen.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\base\ifthen.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.enc
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.enc
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.chr
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\cjk\UTF8\UTF8.chr
INPUT .\lab4_report.aux
INPUT .\lab4_report.aux
INPUT lab4_report.aux
OUTPUT lab4_report.aux
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\context\base\mkii\supp-pdf.mkii
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\context\base\mkii\supp-pdf.mkii
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\context\base\mkii\supp-pdf.mkii
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\epstopdf-pkg\epstopdf-base.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\epstopdf-pkg\epstopdf-base.sty
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\00miktex\epstopdf-sys.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\00miktex\epstopdf-sys.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\00miktex\epstopdf-sys.cfg
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\graphics\color.sty
INPUT .\lab4_report.out
INPUT .\lab4_report.out
INPUT lab4_report.out
INPUT lab4_report.out
OUTPUT lab4_report.pdf
INPUT .\lab4_report.out
INPUT .\lab4_report.out
OUTPUT lab4_report.out
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr17.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmbx12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\fd\c70rm.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\fd\c70rm.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\ctex\fd\c70rm.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei56.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\uniheiff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei7e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei73.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmmi12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmsy10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmex10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\amsfonts\cmextra\cmex7.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong68.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisongff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong65.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr17.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmbx12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei76.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong76.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong89.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong66.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisongff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong74.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong7e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong57.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong54.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong90.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong4f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong30.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong75.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong72.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong73.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong59.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong95.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong62.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong7a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong96.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei73.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei58.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\jknappen\ec\tcrm1200.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmbx12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei64.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei4f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei7c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei7e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei51.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei77.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei74.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmbx12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei69.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong7b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei57.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei90.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\uniheiff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei65.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong56.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong65.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong51.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\ctex\zhmap\ctex-zhmap-windows.tex
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\generic\ctex\zhmap\ctex-zhmap-windows.tex
INPUT C:\Users\26586\AppData\Local\MiKTeX\fonts\map\pdftex\pdftex.map
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\sfd\ttf2pk\UGBK.sfd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\sfd\ttf2pk\Unicode.sfd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei54.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong64.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei90.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei4f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei68.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong91.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong68.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmtt12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong8d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong83.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei59.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei62.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong88.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong79.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong5f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei57.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei72.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmtt10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei73.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei72.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong81.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr6.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmmi12.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmmi8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmmi6.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmsy10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmsy8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmsy6.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmex10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\amsfonts\cmextra\cmex8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\amsfonts\cmextra\cmex7.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhmetrics\c70zhfs.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhmetrics\c70zhfs.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\tex\latex\zhmetrics\c70zhfs.fd
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs54.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifsff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs90.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs77.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs53.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs62.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs96.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs56.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmtt8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmtt8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs72.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs30.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs51.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs57.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs7b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs5f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs4f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs65.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei95.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei78.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei73.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong78.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong77.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs95.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\amsfonts\cmextra\cmex7.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmtt8.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifsff.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs62.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs7b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs5f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs4e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs67.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs30.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs5b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs54.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs56.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs72.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unifs\unifs60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\public\cm\cmr10.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei80.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei62.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei74.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei7a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei63.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei60.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei7e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong6a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6d.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei74.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei52.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei6b.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei9a.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong98.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei80.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong97.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei65.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8f.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei5e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei66.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei8c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei68.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei30.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong58.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong8c.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong8e.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei58.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unihei\unihei89.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong80.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong55.tfm
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\tfm\zhmetrics\unisong\unisong7c.tfm
INPUT lab4_report.aux
INPUT .\lab4_report.out
INPUT .\lab4_report.out
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simfang.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\Users\26586\AppData\Local\MiKTeX\fonts\pk\ljfour\jknappen\ec\dpi600\tcrm1200.pk
INPUT C:\Users\26586\AppData\Local\MiKTeX\fonts\pk\ljfour\jknappen\ec\dpi600\tcrm1200.pk
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simsun.ttc
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\WINDOWS\Fonts\simhei.ttf
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmbx12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmbx12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmmi12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmmi12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmmi8.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmmi8.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmr12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmr12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmsy10.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmsy10.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmtt10.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmtt10.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmtt12.pfb
INPUT C:\Users\26586\AppData\Local\Programs\MiKTeX\fonts\type1\public\amsfonts\cm\cmtt12.pfb

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,288 @@
\documentclass[12pt]{ctexart} % 使用 ctexart 文档类支持中文12pt 字号
\usepackage[utf8]{inputenc} % 输入编码,保持兼容性
\usepackage[margin=2.5cm]{geometry} % 设置页边距
\usepackage{graphicx} % 导入图片
\usepackage{amsmath} % 支持数学公式
\usepackage{listings} % 代码块高亮
\usepackage{xcolor} % 用于代码高亮颜色
\usepackage{hyperref} % 目录、交叉引用可点击生成PDF书签
\hypersetup{
colorlinks=true, % 这是关键,它会让链接文本以颜色显示,而不是边框
linkcolor=black, % 内部链接(如目录、章节引用)的颜色设为黑色
citecolor=green, % 引用文献的颜色(如果用不到可以忽略或设为黑色)
urlcolor=blue, % URL链接的颜色如果用不到可以忽略或设为黑色
filecolor=magenta, % 文件链接的颜色(如果用不到可以忽略或设为黑色)
% 可以添加更多其他 PDF 元数据,让 PDF 文件信息更完整
pdftitle={实验四:总线接口设计与实现},
pdfauthor={朱梓涵},
pdfsubject={AXI4-Lite 总线协议设计与实现报告},
pdfkeywords={RISC-V, CPU, Chisel, AXI4-Lite, 总线, 实验报告}
}
% 目录、交叉引用可点击生成PDF书签
\usepackage{fancyhdr} % 自定义页眉页脚
\usepackage{enumitem} % 列表项自定义
\usepackage{ifthen} % 条件判断(用于图片占位)
% --- 图片缺失占位宏 ---
\newcommand{\includegraphicsorplaceholder}[2][]{%
\IfFileExists{#2}{\includegraphics[#1]{#2}}{\fbox{\parbox[c][0.2\textheight][c]{0.9\textwidth}{\centering Missing image: #2}}}%
}
% --- 页眉页脚设置 ---
\pagestyle{fancy}
\fancyhf{} % 清除所有页眉页脚字段
\fancyhead[L]{\MakeUppercase{实验四:总线接口设计与实现}} % 左侧页眉:大写实验名称
\fancyfoot[C]{\thepage} % 居中页脚:页码
\renewcommand{\headrulewidth}{0.4pt} % 页眉下方的横线粗细
\renewcommand{\footrulewidth}{0.4pt} % 页脚上方的横线粗细
% 解决 fancyhdr 提示的 \headheight 偏小问题
\setlength{\headheight}{15pt}
% --- 标题信息 ---
\title{\vspace{-2cm}\textbf{实验四:总线接口设计与实现}} % 标题,垂直间距调整
\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},
% 添加 Chisel 相关关键字
morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt, elsewhen, otherwise, Wire, Bool, RegInit, asSInt, asUInt, switch, is, ChiselEnum, Value},
literate={:}{{\color{sol-base02}:}}1
}
\lstset{style=ScalaChiselStyle} % 默认代码风格为 Scala/Chisel
% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}
% --- 文档开始 ---
\begin{document}
\maketitle % 生成标题
\thispagestyle{empty} % 标题页无页码
% --- 正文开始 ---
\section{实验目的}
本实验的主要目的是:
\begin{enumerate}[label=\arabic*.]
\item 理解 AXI4-Lite 总线协议的基本原理和通信机制。
\item 学习使用状态机实现总线协议。
\item 掌握主从设备之间的握手通信过程。
\item 理解 MMIOMemory-Mapped I/O的工作原理。
\item 将总线协议集成到流水线 CPU 中。
\end{enumerate}
\section{实验环境}
\begin{itemize}
\item \textbf{操作系统}: Windows 11
\item \textbf{开发工具}: IntelliJ IDEA
\item \textbf{构建工具}: SBT
\item \textbf{仿真与测试}: Verilator, chiseltest
\end{itemize}
\section{实验原理}
\subsection{AXI4-Lite 协议概述}
AXI4-Lite 是总线协议的简化版本。它包含 5 个独立的通道:
\begin{itemize}
\item \textbf{读地址通道AR}:主机发送读地址。
\item \textbf{读数据通道R}:从机返回读取的数据。
\item \textbf{写地址通道AW}:主机发送写地址。
\item \textbf{写数据通道W}:主机发送写数据。
\item \textbf{写响应通道B}:从机返回写操作响应。
\end{itemize}
\subsection{通信框架}
本实验采用的通信框架如下:
\begin{itemize}
\item \textbf{CPU 侧}:通过 \texttt{AXI4LiteMasterBundle} 接口发起读写请求。
\item \textbf{AXI4LiteMaster}:将简单的读写请求转换为符合 AXI4-Lite 协议的信号。
\item \textbf{AXI4LiteChannels}5 个通道的信号线,符合 AXI4-Lite 规范。
\item \textbf{AXI4LiteSlave}:接收 AXI4-Lite 协议信号,转换为设备可理解的读写操作。
\item \textbf{设备侧}:通过 \texttt{AXI4LiteSlaveBundle} 接口响应读写请求。
\end{itemize}
\subsection{握手机制}
AXI4-Lite 协议采用 VALID/READY 握手机制:
\begin{itemize}
\item 发送方通过 \texttt{VALID} 信号表示数据有效。
\item 接收方通过 \texttt{READY} 信号表示准备接收。
\item 只有当 \texttt{VALID}\texttt{READY} 同时为高时,握手完成,数据传输成功。
\end{itemize}
\section{模块实现与分析}
\subsection{状态机设计}
本实验使用状态机实现 AXI4-Lite 协议。定义了以下状态:
\begin{lstlisting}[caption={状态定义}]
object AXI4LiteStates extends ChiselEnum {
val Idle, ReadAddr, ReadDataWait, ReadData,
WriteAddr, WriteData, WriteResp = Value
}
\end{lstlisting}
\subsection{AXI4LiteMaster 实现}
\subsubsection{主机状态机逻辑}
\begin{enumerate}
\item \textbf{Idle 状态}:等待来自 CPU 的读写请求。收到读请求时,保存地址并转到 \texttt{ReadAddr} 状态;收到写请求时,保存地址和数据并转到 \texttt{WriteAddr} 状态。
\item \textbf{ReadAddr 状态}:拉高 \texttt{ARVALID},发送读地址 \texttt{ARADDR}。等待从机 \texttt{ARREADY} 信号,握手完成后,拉高 \texttt{RREADY},转到 \texttt{ReadData} 状态。
\item \textbf{ReadData 状态}:保持 \texttt{RREADY} 为高,等待从机 \texttt{RVALID}。收到 \texttt{RVALID} 时,锁存 \texttt{RDATA},拉高 \texttt{read_valid} 一个周期,通知 CPU 读取完成,随后返回 \texttt{Idle} 状态。
\item \textbf{WriteAddr 状态}:拉高 \texttt{AWVALID},发送写地址 \texttt{AWADDR}。等待从机 \texttt{AWREADY} 信号,握手完成后,拉高 \texttt{WVALID},转到 \texttt{WriteData} 状态。
\item \textbf{WriteData 状态}:保持 \texttt{WVALID} 为高,发送 \texttt{WDATA}\texttt{WSTRB}。等待从机 \texttt{WREADY} 信号,握手完成后,拉高 \texttt{BREADY},转到 \texttt{WriteResp} 状态。
\item \textbf{WriteResp 状态}:保持 \texttt{BREADY} 为高,等待从机 \texttt{BVALID}。收到 \texttt{BVALID} 时,拉高 \texttt{write_valid} 一个周期,随后返回 \texttt{Idle} 状态。
\end{enumerate}
\subsubsection{关键代码实现}
\begin{lstlisting}[caption={主机状态机核心代码}, label={lst:master_core}]
switch(state) {
is(AXI4LiteStates.Idle) {
when(io.bundle.read) {
addr := io.bundle.address
state := AXI4LiteStates.ReadAddr
ARVALID := true.B
}.elsewhen(io.bundle.write) {
addr := io.bundle.address
write_data := io.bundle.write_data
write_strobe := io.bundle.write_strobe
state := AXI4LiteStates.WriteAddr
AWVALID := true.B
}
}
}
\end{lstlisting}
此外,当主机不在 \texttt{Idle} 状态时,\texttt{busy} 信号为高,拒绝新的请求:
\begin{lstlisting}
io.bundle.busy := state =/= AXI4LiteStates.Idle
\end{lstlisting}
\texttt{valid} 信号在状态机执行前清零,确保只持续一个周期:
\begin{lstlisting}
when(read_valid) { read_valid := false.B }
when(write_valid) { write_valid := false.B }
\end{lstlisting}
\subsection{AXI4LiteSlave 实现}
\subsubsection{从机状态机逻辑}
\begin{enumerate}
\item \textbf{Idle 状态}:清除所有控制信号。优先响应读请求(\texttt{ARVALID}),收到时保存地址,拉高 \texttt{ARREADY},转到 \texttt{ReadAddr}。收到写请求时,保存地址,拉高 \texttt{AWREADY},转到 \texttt{WriteAddr}
\item \textbf{ReadAddr 状态}:拉低 \texttt{ARREADY},拉高 \texttt{read} 信号通知设备读取数据,转到 \texttt{ReadData} 状态。
\item \textbf{ReadData 状态}:保持 \texttt{read} 为高,等待设备 \texttt{read_valid}。收到时锁存 \texttt{read_data}\texttt{rdataReg},拉高 \texttt{RVALID},等待主机 \texttt{RREADY}。握手完成后返回 \texttt{Idle} 状态。
\item \textbf{WriteAddr 状态}:拉低 \texttt{AWREADY},等待主机 \texttt{WVALID}。收到写数据后,锁存数据和写选通,拉高 \texttt{WREADY}\texttt{write},转到 \texttt{WriteData}
\item \textbf{WriteData 状态}:拉低 \texttt{WREADY}\texttt{write},拉高 \texttt{BVALID},转到 \texttt{WriteResp}
\item \textbf{WriteResp 状态}:保持 \texttt{BVALID} 为高,等待主机 \texttt{BREADY}。握手完成后返回 \texttt{Idle} 状态。
\end{enumerate}
\subsubsection{关键代码实现}
\begin{lstlisting}[caption={从机状态机核心代码}, label={lst:slave_core}]
switch(state) {
is(AXI4LiteStates.Idle) {
when(io.channels.read_address_channel.ARVALID) {
addr := io.channels.read_address_channel.ARADDR
ARREADY := true.B
state := AXI4LiteStates.ReadAddr
}.elsewhen(io.channels.write_address_channel.AWVALID) {
addr := io.channels.write_address_channel.AWADDR
AWREADY := true.B
state := AXI4LiteStates.WriteAddr
}
}
}
\end{lstlisting}
使用寄存器保证 \texttt{RDATA}\texttt{RVALID} 为高时保持稳定:
\begin{lstlisting}
val rdataReg = RegInit(0.U(dataWidth.W))
io.channels.read_data_channel.RDATA := rdataReg
\end{lstlisting}
\subsection{性能优化}
本实现采用了以下优化策略:
\begin{enumerate}
\item \textbf{流水化握手}:在地址握手完成后立即准备数据握手,减少等待周期。
\item \textbf{优先级处理}:从机优先响应读请求,提高取指效率。
\item \textbf{信号稳定性}:使用寄存器锁存关键数据,避免毛刺。
\end{enumerate}
\section{CSR 指令与总线交互}
CSR 指令在总线协议中的交互主要体现在 MMIOMemory-Mapped I/O上。CPU 通过地址映射访问 CSR 寄存器或外设寄存器:
\begin{itemize}
\item 读写 CSR 时,控制单元发出相应的读写请求。
\item AXI4-Lite Master 接收请求,将地址和数据转换为总线事务。
\item AXI4-Lite Slave 根据地址将请求路由到具体的 CSR 模块或外设。
\item 通过握手机制,确保数据传输的正确性和稳定性。
\end{itemize}
\section{测试结果与分析}
\subsection{测试原理}
\texttt{BusTest.scala} 包含多个测试用例,验证 AXI4-Lite 实现的正确性:
\begin{itemize}
\item \textbf{FunctionalTest}:创建 \texttt{TestBox} 模块,模拟主从机忙碌状态,验证读写事务的地址、数据、选通信号及 \texttt{valid} 信号时序。
\item \textbf{连续事务测试}:随机生成 1000 个读写事务,模拟从机忙碌状态,验证高负载下的总线稳定性。
\item \textbf{其他测试}:包括 \texttt{TimerTest}(定时器)、\texttt{MemoryTestF}(内存)和 \texttt{ROMLoaderTestF}ROM 加载)。
\end{itemize}
\subsection{分析}
\begin{enumerate}
\item \textbf{正确性验证}:所有测试用例通过,说明实现符合 AXI4-Lite 协议规范。数据传输正确,地址、数据、选通信号及 \texttt{valid} 信号时序均符合预期。
\item \textbf{性能分析}:单次读写事务的握手周期符合设计预期(约 3-4 周期)。连续事务测试证明了总线在高负载下的可靠性。
\end{enumerate}
\section{改进建议}
\begin{enumerate}[label=\arabic*.]
\item \textbf{建议:提供更多调试案例和方法指导。}
建议增加具体的调试案例,例如如何追踪一条指令在总线中的完整传输过程,如何分析波形图定位握手失败问题等。
\item \textbf{建议:增加可视化工具。}
建议提供或推荐一些工具,能够将总线上的信号交互以图形化方式展示,辅助理解握手过程。
\end{enumerate}
\section{实验结论}
通过本次实验,我深入理解了 AXI4-Lite 总线协议的工作原理,掌握了使用状态机实现复杂通信协议的方法。我成功实现了:
\begin{itemize}
\item 符合 AXI4-Lite 规范的主机和从机模块。
\item 基于 VALID/READY 握手机制的通信流程。
\item 完善的测试用例,验证了总线的正确性和稳定性。
\end{itemize}
本次实验不仅提升了我的硬件设计能力,也让我对计算机系统中各模块间的互连和通信有了更深刻的认识,为后续更复杂的系统设计打下了坚实基础。
\end{document}

View File

@@ -0,0 +1,33 @@
\contentsline {section}{\numberline {1}实验目的}{4}{section.1}%
\contentsline {section}{\numberline {2}实验原理}{4}{section.2}%
\contentsline {subsection}{\numberline {2.1}AXI4-Lite 协议概述}{4}{subsection.2.1}%
\contentsline {subsection}{\numberline {2.2}通信框架}{4}{subsection.2.2}%
\contentsline {subsection}{\numberline {2.3}握手机制}{5}{subsection.2.3}%
\contentsline {section}{\numberline {3}AXI4-Lite 主从机实现逻辑}{5}{section.3}%
\contentsline {subsection}{\numberline {3.1}状态机设计}{5}{subsection.3.1}%
\contentsline {subsection}{\numberline {3.2}AXI4LiteMaster 实现}{5}{subsection.3.2}%
\contentsline {subsection}{\numberline {3.3}AXI4LiteSlave 实现}{6}{subsection.3.3}%
\contentsline {subsection}{\numberline {3.4}性能优化}{8}{subsection.3.4}%
\contentsline {section}{\numberline {4}BusTest 测试原理与结果}{8}{section.4}%
\contentsline {subsection}{\numberline {4.1}测试原理}{8}{subsection.4.1}%
\contentsline {subsubsection}{\numberline {4.1.1}FunctionalTest - 功能测试}{8}{subsubsection.4.1.1}%
\contentsline {subsubsection}{\numberline {4.1.2}其他测试}{9}{subsubsection.4.1.2}%
\contentsline {subsection}{\numberline {4.2}测试结果}{9}{subsection.4.2}%
\contentsline {subsubsection}{\numberline {4.2.1}预期结果}{9}{subsubsection.4.2.1}%
\contentsline {subsubsection}{\numberline {4.2.2}实际测试输出}{10}{subsubsection.4.2.2}%
\contentsline {subsection}{\numberline {4.3}测试分析}{10}{subsection.4.3}%
\contentsline {section}{\numberline {5}硬件调试(可选)}{10}{section.5}%
\contentsline {subsection}{\numberline {5.1}Vivado 波形分析}{10}{subsection.5.1}%
\contentsline {subsection}{\numberline {5.2}调试建议}{11}{subsection.5.2}%
\contentsline {section}{\numberline {6}实验中遇到的问题与建议}{11}{section.6}%
\contentsline {subsection}{\numberline {6.1}遇到的问题}{11}{subsection.6.1}%
\contentsline {subsection}{\numberline {6.2}改进建议}{12}{subsection.6.2}%
\contentsline {section}{\numberline {7}实验总结}{12}{section.7}%
\contentsline {subsection}{\numberline {7.1}实验收获}{12}{subsection.7.1}%
\contentsline {subsection}{\numberline {7.2}进一步思考}{12}{subsection.7.2}%
\contentsline {subsection}{\numberline {7.3}后续工作}{13}{subsection.7.3}%
\contentsline {section}{\numberline {8}附录}{13}{section.8}%
\contentsline {subsection}{\numberline {8.1}关键代码片段}{13}{subsection.8.1}%
\contentsline {subsubsection}{\numberline {8.1.1}AXI4LiteMaster 核心逻辑}{13}{subsubsection.8.1.1}%
\contentsline {subsubsection}{\numberline {8.1.2}AXI4LiteSlave 核心逻辑}{14}{subsubsection.8.1.2}%
\contentsline {subsection}{\numberline {8.2}参考资料}{14}{subsection.8.2}%

View File

@@ -0,0 +1,507 @@
\documentclass[12pt]{ctexart} % 使用 ctexart 文档类支持中文12pt 字号
\usepackage[utf8]{inputenc} % 输入编码,保持兼容性
\usepackage[margin=2.5cm]{geometry} % 设置页边距
\usepackage{graphicx} % 导入图片
\usepackage{amsmath} % 支持数学公式
\usepackage{listings} % 代码块高亮
\usepackage{xcolor} % 用于代码高亮颜色
\usepackage{hyperref} % 目录、交叉引用可点击生成PDF书签
\hypersetup{
colorlinks=true, % 这是关键,它会让链接文本以颜色显示,而不是边框
linkcolor=black, % 内部链接(如目录、章节引用)的颜色设为黑色
citecolor=green, % 引用文献的颜色(如果用不到可以忽略或设为黑色)
urlcolor=blue, % URL链接的颜色如果用不到可以忽略或设为黑色
filecolor=magenta, % 文件链接的颜色(如果用不到可以忽略或设为黑色)
% 可以添加更多其他 PDF 元数据,让 PDF 文件信息更完整
pdftitle={实验三:流水线 CPU 设计与实现},
pdfauthor={朱梓涵},
pdfsubject={流水线 RISC-V CPU 设计与实现报告},
pdfkeywords={RISC-V, CPU, Chisel, 流水线, 实验报告}
}
% 目录、交叉引用可点击生成PDF书签
\usepackage{fancyhdr} % 自定义页眉页脚
\usepackage{enumitem} % 列表项自定义
\usepackage{ifthen} % 条件判断(用于图片占位)
% --- 图片缺失占位宏 ---
\newcommand{\includegraphicsorplaceholder}[2][]{%
\IfFileExists{#2}{\includegraphics[#1]{#2}}{\fbox{\parbox[c][0.2\textheight][c]{0.9\textwidth}{\centering Missing image: #2}}}%
}
% --- 页眉页脚设置 ---
\pagestyle{fancy}
\fancyhf{} % 清除所有页眉页脚字段
\fancyhead[L]{\MakeUppercase{实验三:流水线 CPU 设计与实现}} % 左侧页眉:大写实验名称
\fancyfoot[C]{\thepage} % 居中页脚:页码
\renewcommand{\headrulewidth}{0.4pt} % 页眉下方的横线粗细
\renewcommand{\footrulewidth}{0.4pt} % 页脚上方的横线粗细
% 解决 fancyhdr 提示的 \headheight 偏小问题
\setlength{\headheight}{15pt}
% --- 标题信息 ---
\title{\vspace{-2cm}\textbf{实验三:流水线 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},
% 添加 Chisel 相关关键字
morekeywords={when, Mux, MuxLookup, IndexedSeq, U, io, :=, object, val, def, class, override, package, import, extends, with, Bits, UInt, SInt, elsewhen, otherwise, Wire, Bool, RegInit, asSInt, asUInt},
literate={:}{{\color{sol-base02}:}}1
}
\lstset{style=ScalaChiselStyle} % 默认代码风格为 Scala/Chisel
% --- 图片计数器与章节联动 ---
\counterwithin{figure}{section}
\counterwithin{table}{section}
% --- 文档开始 ---
\begin{document}
\maketitle % 生成标题
\thispagestyle{empty} % 标题页无页码
% --- 正文开始 ---
\section{实验目的}
本实验旨在深入理解流水线技术在 CPU 设计中的应用,通过实现三级和五级流水线 CPU掌握流水线中竞争冒险的处理方法。实验目标包括
\begin{enumerate}[label=\arabic*.] % 使用 enumerate 环境创建编号列表
\item 理解流水线寄存器的作用,并实现支持阻塞和清空功能的流水线寄存器。
\item 设计并实现三级流水线 CPU掌握控制冒险的处理方法。
\item 设计并实现五级流水线 CPU学习使用阻塞和转发技术处理数据冒险。
\item 将分支跳转提前到译码阶段,进一步缩短分支延迟,优化流水线性能。
\item 通过编写测试用例,验证流水线 CPU 各模块及整体功能的正确性。
\end{enumerate}
\section{实验环境}
\begin{itemize}
\item \textbf{操作系统}: Windows 11
\item \textbf{开发工具}: IntelliJ IDEA
\item \textbf{构建工具}: SBT
\item \textbf{仿真与测试}: Verilator, chiseltest
\end{itemize}
\section{流水线结构与功能划分}
\subsection{三级流水线结构}
三级流水线将单周期 CPU 的组合逻辑切分为三个阶段:
\begin{itemize}
\item \textbf{取指 (IF)}: 根据 PC 从指令存储器取出指令。
\item \textbf{译码 (ID)}: 解码指令,生成控制信号,从寄存器组读取操作数。
\item \textbf{执行 (EX)}: 执行 ALU 运算、访存和写回操作。
\end{itemize}
在三级流水线中,主要需要处理控制冒险。当 EX 段执行跳转或分支指令时IF 和 ID 段的两条指令需要被清空。
\subsection{五级流水线结构}
五级流水线在三级流水线的基础上,将 EX 段进一步细分:
\begin{itemize}
\item \textbf{取指 (IF)}: 根据 PC 从指令存储器取出指令。
\item \textbf{译码 (ID)}: 解码指令,生成控制信号,从寄存器组读取操作数。
\item \textbf{执行 (EX)}: 执行 ALU 运算。
\item \textbf{访存 (MEM)}: 访问数据存储器。
\item \textbf{写回 (WB)}: 将结果写回寄存器组。
\end{itemize}
五级流水线引入了更复杂的数据冒险,需要使用阻塞和转发技术进行处理。
\subsection{缩短分支延迟的五级流水线}
在最终版本的五级流水线中,将分支和跳转指令的执行从 EX 段提前到 ID 段:
\begin{itemize}
\item 在 ID 段增加加法器,用于计算跳转目标地址。
\item 在 ID 段进行分支条件判断,使用转发逻辑从 MEM 和 WB 段获取操作数。
\item 如果依赖的数据还未产生,则进行阻塞。
\end{itemize}
这样做可以将分支延迟从两个时钟周期减少到一个时钟周期。
\section{模块实现与分析}
\subsection{流水线寄存器PipelineRegister}
\subsubsection{功能}
流水线寄存器是流水线 CPU 的核心组件,用于在相邻流水段之间缓存数据和控制信号。它支持三种操作:
\begin{itemize}
\item \textbf{清空 (flush)}: 将寄存器值重置为默认值,用于清除错误路径上的指令。
\item \textbf{阻塞 (stall)}: 保持当前寄存器值不变,用于暂停流水线。
\item \textbf{正常更新}: 在时钟上升沿将输入值写入寄存器。
\end{itemize}
\subsubsection{代码实现}
\begin{lstlisting}[caption={流水线寄存器实现}, label={lst:pipeline_reg}]
class PipelineRegister(width: Int = Parameters.DataBits, defaultValue: UInt = 0.U) extends Module {
val io = IO(new Bundle {
val stall = Input(Bool())
val flush = Input(Bool())
val in = Input(UInt(width.W))
val out = Output(UInt(width.W))
})
// Lab3(PipelineRegister)
val register = RegInit(defaultValue)
when(io.flush) {
register := defaultValue
}.elsewhen(io.stall) {
}.otherwise {
register := io.in
}
io.out := register
// Lab3(PipelineRegister) End
}
\end{lstlisting}
\subsubsection{设计要点}
\begin{itemize}
\item 优先级:\texttt{flush} 信号优先级最高,其次是 \texttt{stall},最后是正常更新。
\item\texttt{flush} 为高时,寄存器被清空为默认值(通常是 NOP 指令或 0
\item\texttt{stall} 为高时,寄存器保持当前值不变。
\item 其他情况下,寄存器在时钟上升沿更新为输入值。
\end{itemize}
\subsection{控制单元Control}
\subsubsection{功能}
控制单元负责检测流水线中的冒险,并生成相应的控制信号:
\begin{itemize}
\item 检测数据冒险,生成阻塞信号。
\item 检测控制冒险,生成清空信号。
\end{itemize}
\subsubsection{代码实现(最终版本)}
\begin{lstlisting}[caption={控制单元实现(缩短分支延迟版本)}, label={lst:control_final}]
class Control extends Module {
val io = IO(new Bundle {
val jump_flag = Input(Bool())
val jump_instruction_id = Input(Bool())
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_ex = Input(Bool())
val rd_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val memory_read_enable_mem = Input(Bool())
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val if2id_flush = Output(Bool())
val id2ex_flush = Output(Bool())
val pc_stall = Output(Bool())
val if2id_stall = Output(Bool())
})
// Lab3(Final)
val stall = Wire(Bool())
val load_use_hazard = io.memory_read_enable_ex && io.rd_ex =/= 0.U &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_ex_alu = io.jump_instruction_id && io.rd_ex =/= 0.U &&
!io.memory_read_enable_ex &&
(io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id)
val id_jump_needs_mem_load = io.jump_instruction_id && io.memory_read_enable_mem && io.rd_mem =/= 0.U &&
(io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id)
stall := load_use_hazard || id_jump_needs_ex_alu || id_jump_needs_mem_load
val flush = io.jump_flag && !stall
io.pc_stall := stall
io.if2id_stall := stall
io.if2id_flush := flush
io.id2ex_flush := stall
// Lab3(Final) End
}
\end{lstlisting}
\subsubsection{设计要点}
在缩短分支延迟的版本中,由于分支和跳转指令在 ID 段执行,控制单元需要处理以下几种情况:
\begin{enumerate}
\item \textbf{Load-use 冒险}: 当 ID 段的指令需要使用 EX 段 load 指令的结果时,必须阻塞一个周期,等待数据从 MEM 段产生后通过转发获取。
\item \textbf{跳转指令依赖 EX 段 ALU 结果}: 当 ID 段的跳转/分支指令需要使用 EX 段的 ALU 计算结果时,需要阻塞一个周期。虽然 EX 段的结果会在下个周期进入 MEM 段,可以通过转发提供给 ID 段,但由于跳转判断需要在 ID 段完成,因此必须等待一个周期。
\item \textbf{跳转指令依赖 MEM 段 load 结果}: 当 ID 段的跳转/分支指令需要使用 MEM 段 load 指令的结果时,需要阻塞一个周期,等待数据进入 WB 段后通过转发获取。
\item \textbf{控制冒险}: 当跳转确实发生时(\texttt{jump\_flag} 为真且无阻塞),需要清空 IF2ID 流水线寄存器,丢弃已取出的错误路径指令。
\item \textbf{阻塞时插入气泡}: 当发生阻塞时,需要清空 ID2EX 流水线寄存器,在 EX 段插入一条 NOP 指令(气泡),防止 ID 段的指令被重复执行。
\end{enumerate}
\subsection{转发单元Forwarding}
\subsubsection{功能}
转发单元负责检测数据冒险,并生成转发控制信号,使得 EX 或 ID 段可以直接从流水线寄存器中获取所需数据,而不必等待数据写回寄存器组,从而减少流水线阻塞。
\subsubsection{代码实现(最终版本)}
\begin{lstlisting}[caption={转发单元实现(缩短分支延迟版本)}, label={lst:forward_final}]
object ForwardingType {
val NoForward = 0.U(2.W)
val ForwardFromMEM = 1.U(2.W)
val ForwardFromWB = 2.U(2.W)
}
class Forwarding extends Module {
val io = IO(new Bundle() {
val rs1_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_id = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs1_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rs2_ex = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val rd_mem = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_mem = Input(Bool())
val rd_wb = Input(UInt(Parameters.PhysicalRegisterAddrWidth))
val reg_write_enable_wb = Input(Bool())
val reg1_forward_id = Output(UInt(2.W))
val reg2_forward_id = Output(UInt(2.W))
val reg1_forward_ex = Output(UInt(2.W))
val reg2_forward_ex = Output(UInt(2.W))
})
// Lab3(Final)
val ex_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_ex)
val ex_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_ex)
val ex_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs1_ex)
val ex_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && (io.rd_wb === io.rs2_ex)
io.reg1_forward_ex := Mux(ex_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(ex_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
val id_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id)
val id_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_id)
val id_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs1 && (io.rd_wb === io.rs1_id)
val id_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs2 && (io.rd_wb === io.rs2_id)
io.reg1_forward_id := Mux(id_mem_hazard_rs1, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
io.reg2_forward_id := Mux(id_mem_hazard_rs2, ForwardingType.ForwardFromMEM,
Mux(id_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward))
// Lab3(Final) End
}
\end{lstlisting}
\subsubsection{设计要点}
转发单元需要同时处理到 EX 段和到 ID 段的转发:
\begin{enumerate}
\item \textbf{EX 段转发}:
\begin{itemize}
\item 如果 EX 段的源寄存器与 MEM 段的目标寄存器相同,从 MEM 段转发。
\item 如果 EX 段的源寄存器与 WB 段的目标寄存器相同,从 WB 段转发。
\item MEM 段转发优先级高于 WB 段转发(保证获取最新的值)。
\end{itemize}
\item \textbf{ID 段转发}:
\begin{itemize}
\item 由于跳转指令在 ID 段执行,需要将 MEM 和 WB 段的结果转发到 ID 段。
\item 如果 ID 段的源寄存器与 MEM 段的目标寄存器相同,从 MEM 段转发。
\item 如果 ID 段的源寄存器与 WB 段的目标寄存器相同(且不与 MEM 段冲突),从 WB 段转发。
\item MEM 段转发优先级同样高于 WB 段转发。
\end{itemize}
\item \textbf{寄存器 x0 的特殊处理}:
\begin{itemize}
\item RISC-V 中寄存器 x0 恒为 0写入 x0 的结果会被丢弃。
\item 因此,转发逻辑中需要检查目标寄存器是否为 0\texttt{rd =/= 0.U}),避免不必要的转发。
\end{itemize}
\end{enumerate}
\subsection{译码单元InstructionDecode}
在缩短分支延迟的版本中,译码单元需要在 ID 段完成分支和跳转指令的执行。
\subsubsection{关键代码}
\begin{lstlisting}[caption={ID 段跳转逻辑}, label={lst:id_jump}]
val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val reg2_data = MuxLookup(io.reg2_forward, io.reg2_data)(
Seq(
ForwardingType.ForwardFromMEM -> io.forward_from_mem,
ForwardingType.ForwardFromWB -> io.forward_from_wb
)
)
val is_jump_instruction = opcode === Instructions.jal || opcode === Instructions.jalr || opcode === InstructionTypes.B
io.ctrl_jump_instruction := is_jump_instruction
val jump_condition_met =
(opcode === Instructions.jal) ||
(opcode === Instructions.jalr) ||
(opcode === InstructionTypes.B) && MuxLookup(
funct3,
false.B,
IndexedSeq(
InstructionsTypeB.beq -> (reg1_data === reg2_data),
InstructionsTypeB.bne -> (reg1_data =/= reg2_data),
InstructionsTypeB.blt -> (reg1_data.asSInt < reg2_data.asSInt),
InstructionsTypeB.bge -> (reg1_data.asSInt >= reg2_data.asSInt),
InstructionsTypeB.bltu -> (reg1_data < reg2_data),
InstructionsTypeB.bgeu -> (reg1_data >= reg2_data)
)
)
val jump_address = Mux(
opcode === Instructions.jalr,
(reg1_data.asSInt + io.ex_immediate.asSInt).asUInt,
(io.instruction_address.asSInt + io.ex_immediate.asSInt).asUInt
) & (~1.U(Parameters.DataWidth)).asUInt
io.if_jump_flag := jump_condition_met || io.interrupt_assert
io.if_jump_address := Mux(
io.interrupt_assert,
io.interrupt_handler_address,
jump_address
)
\end{lstlisting}
\subsubsection{设计要点}
\begin{itemize}
\item 在 ID 段使用转发逻辑获取寄存器数据,确保使用的是最新的值。
\item 根据指令类型jal/jalr/分支)判断跳转条件是否满足。
\item 在 ID 段计算跳转目标地址,无需等到 EX 段。
\item 跳转地址需要与 \texttt{\textasciitilde 1} 进行与运算确保地址为偶数RISC-V 要求)。
\end{itemize}
\section{CSR 指令的冒险分析}
\subsection{数据冒险}
CSRControl and Status Register指令用于读写控制和状态寄存器。在本实验的实现中CSR 指令可能产生以下数据冒险:
\begin{enumerate}
\item \textbf{RAWRead After Write冒险}:
\begin{itemize}
\item 当后续指令需要读取 CSR 指令写入的通用寄存器时,会发生 RAW 冒险。
\item 例如:\texttt{csrrw x1, mstatus, x2} 后跟 \texttt{add x3, x1, x4}
\item 解决方法与普通指令相同通过转发或阻塞解决。CSR 指令在 WB 段将结果写回通用寄存器,可以通过 MEM-EX 和 WB-EX 转发路径提供数据。
\end{itemize}
\item \textbf{CSR 寄存器的 RAW 冒险}:
\begin{itemize}
\item 当连续的 CSR 指令访问同一个 CSR 寄存器时,后续指令可能读取到过时的值。
\item 例如:\texttt{csrrw x1, mstatus, x2} 后跟 \texttt{csrrs x3, mstatus, x4}
\item 本实验未专门处理 CSR 寄存器间的冒险。在实际实现中,可以通过以下方式处理:
\begin{itemize}
\item 检测 CSR 地址冲突,插入阻塞。
\item 为 CSR 单元添加转发逻辑。
\item 简化方案CSR 指令较少出现连续访问,可以通过编译器重排指令避免。
\end{itemize}
\end{itemize}
\end{enumerate}
\subsection{控制冒险}
CSR 指令本身不产生控制冒险(它们不是跳转或分支指令)。但是,某些 CSR 指令(如 \texttt{mret})会改变程序执行流:
\begin{itemize}
\item \texttt{mret} 指令用于从异常处理返回,会跳转到 \texttt{mepc} 寄存器指定的地址。
\item 这类指令在本实验中被当作特殊的跳转指令处理,会触发流水线清空。
\end{itemize}
\subsection{结论}
\begin{itemize}
\item CSR 指令写入通用寄存器的数据冒险可以通过现有的转发和阻塞机制解决。
\item CSR 寄存器间的 RAW 冒险在本实验中未专门处理,实际应用中需要额外的检测和阻塞逻辑。
\item \texttt{mret} 等特殊 CSR 指令产生的控制冒险可以通过流水线清空解决。
\end{itemize}
\section{测试结果}
本实验通过了所有测试用例,包括:
\begin{itemize}
\item \textbf{流水线寄存器测试}: 验证了流水线寄存器的阻塞和清空功能。
\item \textbf{三级流水线 CPU 测试}: 验证了控制冒险的处理,包括递归计算斐波那契数列、快速排序、单字节加载存储等。
\item \textbf{五级流水线阻塞CPU 测试}: 验证了使用阻塞解决数据冒险的正确性。
\item \textbf{五级流水线转发CPU 测试}: 验证了使用转发减少阻塞的优化效果。
\item \textbf{五级流水线缩短分支延迟CPU 测试}: 验证了将跳转提前到 ID 段的优化。
\end{itemize}
所有测试均在 60 秒内完成,共 20 个测试用例全部通过,验证了流水线 CPU 各阶段实现的正确性。
\section{遇到的问题与改进建议}
\subsection{遇到的问题}
\begin{enumerate}[label=\arabic*.]
\item \textbf{问题:转发逻辑的优先级容易混淆。}
在实现转发单元时,需要处理 MEM 段和 WB 段同时满足转发条件的情况。根据流水线原理,应优先使用 MEM 段的数据(更新),但在编写代码时容易写反优先级。
\begin{itemize}
\item \textbf{解决方法}:仔细分析数据流,绘制流水线状态图,明确各阶段数据的新旧关系。使用嵌套的 \texttt{Mux} 语句时,外层 \texttt{Mux} 判断优先级更高的条件。
\end{itemize}
\item \textbf{问题:跳转指令提前到 ID 段后,冒险情况增多。}
将跳转判断从 EX 段提前到 ID 段后,需要考虑 ID 段的跳转指令与 EX、MEM 段指令的依赖关系,冒险检测逻辑变得更加复杂。
\begin{itemize}
\item \textbf{解决方法}:按照实验指导的提示,列出所有可能的冒险组合表格,逐一分析每种情况,确保覆盖所有冒险场景。
\end{itemize}
\item \textbf{问题:调试困难,波形图信号繁多。}
五级流水线 CPU 信号众多,在 GTKWave 中查看波形时很难快速定位错误信号。
\begin{itemize}
\item \textbf{解决方法}:使用 Chisel 的 \texttt{printf} 调试功能,在关键部件(如寄存器文件、控制单元)添加打印语句,输出关键信号的值。结合简单的测试程序(如 \texttt{sb.S}),逐步排查错误。
\end{itemize}
\end{enumerate}
\subsection{改进建议}
\begin{enumerate}[label=\arabic*.]
\item \textbf{建议:提供更多调试案例和方法指导。}
实验指导中的调试部分较为简略,建议增加具体的调试案例,例如如何追踪一条指令在流水线中的完整执行过程,如何分析波形图定位冒险问题等。
\item \textbf{建议:增加可视化工具。}
流水线状态可视化对理解和调试非常有帮助。建议提供或推荐一些工具,能够将流水线各阶段的指令和数据流以图形化方式展示。
\item \textbf{建议:补充 CSR 指令冒险处理的说明。}
实验指导中未详细讨论 CSR 指令的冒险处理,建议在后续版本中补充相关内容,或明确说明本实验中 CSR 指令的简化假设。
\end{enumerate}
\section{实验结论}
通过本次实验,我成功实现了三级和五级流水线 CPU深入理解了流水线技术和竞争冒险的处理方法。在实现过程中我掌握了
\begin{itemize}
\item 流水线寄存器的设计与实现。
\item 控制冒险的检测与清空机制。
\item 数据冒险的阻塞和转发解决方案。
\item 分支延迟优化技术(将跳转提前到 ID 段)。
\end{itemize}
通过编写和分析测试用例,我学会了如何验证流水线 CPU 的正确性,并掌握了使用打印和波形图进行调试的方法。本次实验使我对计算机组成原理中的流水线技术有了更深入的实践理解,为后续更复杂的处理器设计奠定了坚实的基础。
\end{document}

BIN
lab4/朱梓涵24325356.rar Normal file

Binary file not shown.

View File

@@ -0,0 +1,362 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bus
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.util._
import riscv.Parameters
object AXI4Lite {
val protWidth = 3
val respWidth = 2
}
class AXI4LiteWriteAddressChannel(addrWidth: Int) extends Bundle {
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWADDR = Output(UInt(addrWidth.W))
val AWPROT = Output(UInt(AXI4Lite.protWidth.W))
}
class AXI4LiteWriteDataChannel(dataWidth: Int) extends Bundle {
val WVALID = Output(Bool())
val WREADY = Input(Bool())
val WDATA = Output(UInt(dataWidth.W))
val WSTRB = Output(UInt((dataWidth / 8).W))
}
class AXI4LiteWriteResponseChannel extends Bundle {
val BVALID = Input(Bool())
val BREADY = Output(Bool())
val BRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteReadAddressChannel(addrWidth: Int) extends Bundle {
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARADDR = Output(UInt(addrWidth.W))
val ARPROT = Output(UInt(AXI4Lite.protWidth.W))
}
class AXI4LiteReadDataChannel(dataWidth: Int) extends Bundle {
val RVALID = Input(Bool())
val RREADY = Output(Bool())
val RDATA = Input(UInt(dataWidth.W))
val RRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteInterface(addrWidth: Int, dataWidth: Int) extends Bundle {
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWADDR = Output(UInt(addrWidth.W))
val AWPROT = Output(UInt(AXI4Lite.protWidth.W))
val WVALID = Output(Bool())
val WREADY = Input(Bool())
val WDATA = Output(UInt(dataWidth.W))
val WSTRB = Output(UInt((dataWidth / 8).W))
val BVALID = Input(Bool())
val BREADY = Output(Bool())
val BRESP = Input(UInt(AXI4Lite.respWidth.W))
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARADDR = Output(UInt(addrWidth.W))
val ARPROT = Output(UInt(AXI4Lite.protWidth.W))
val RVALID = Input(Bool())
val RREADY = Output(Bool())
val RDATA = Input(UInt(dataWidth.W))
val RRESP = Input(UInt(AXI4Lite.respWidth.W))
}
class AXI4LiteChannels(addrWidth: Int, dataWidth: Int) extends Bundle {
val write_address_channel = new AXI4LiteWriteAddressChannel(addrWidth)
val write_data_channel = new AXI4LiteWriteDataChannel(dataWidth)
val write_response_channel = new AXI4LiteWriteResponseChannel()
val read_address_channel = new AXI4LiteReadAddressChannel(addrWidth)
val read_data_channel = new AXI4LiteReadDataChannel(dataWidth)
}
class AXI4LiteSlaveBundle(addrWidth: Int, dataWidth: Int) extends Bundle {
val read = Output(Bool()) // tell slave device to read
val write = Output(Bool()) // tell slave device to write
val read_data = Input(UInt(dataWidth.W)) // data read from slave device
val read_valid = Input(Bool()) // indicates if read_data is valid
val write_data = Output(UInt(dataWidth.W))
val write_strobe = Output(Vec(Parameters.WordSize, Bool()))
val address = Output(UInt(addrWidth.W))
}
class AXI4LiteMasterBundle(addrWidth: Int, dataWidth: Int) extends Bundle {
val read = Input(Bool()) // request a read transaction
val write = Input(Bool()) // request a write transaction
val read_data = Output(UInt(dataWidth.W))
val write_data = Input(UInt(dataWidth.W))
val write_strobe = Input(Vec(Parameters.WordSize, Bool()))
val address = Input(UInt(addrWidth.W))
val busy = Output(Bool()) // if busy, master is not ready to accept new transactions
val read_valid = Output(Bool()) // indicates read transaction done successfully and asserts for ONLY 1 cycle.
val write_valid = Output(Bool()) // indicates write transaction done successfully and asserts for ONLY 1 cycle.
}
object AXI4LiteStates extends ChiselEnum {
val Idle, ReadAddr, ReadDataWait, ReadData, WriteAddr, WriteData, WriteResp = Value
}
class AXI4LiteSlave(addrWidth: Int, dataWidth: Int) extends Module {
val io = IO(new Bundle {
val channels = Flipped(new AXI4LiteChannels(addrWidth, dataWidth))
val bundle = new AXI4LiteSlaveBundle(addrWidth, dataWidth)
})
val state = RegInit(AXI4LiteStates.Idle)
val addr = RegInit(0.U(dataWidth.W))
io.bundle.address := addr
val read = RegInit(false.B)
io.bundle.read := read
val write = RegInit(false.B)
io.bundle.write := write
val write_data = RegInit(0.U(dataWidth.W))
io.bundle.write_data := write_data
val write_strobe = RegInit(VecInit(Seq.fill(Parameters.WordSize)(false.B)))
io.bundle.write_strobe := write_strobe
val ARREADY = RegInit(false.B)
io.channels.read_address_channel.ARREADY := ARREADY
val RVALID = RegInit(false.B)
io.channels.read_data_channel.RVALID := RVALID
val RRESP = RegInit(0.U(AXI4Lite.respWidth))
io.channels.read_data_channel.RRESP := RRESP
val AWREADY = RegInit(false.B)
io.channels.write_address_channel.AWREADY := AWREADY
val WREADY = RegInit(false.B)
io.channels.write_data_channel.WREADY := WREADY
write_data := io.channels.write_data_channel.WDATA
val BVALID = RegInit(false.B)
io.channels.write_response_channel.BVALID := BVALID
val BRESP = WireInit(0.U(AXI4Lite.respWidth))
io.channels.write_response_channel.BRESP := BRESP
//lab4(BUS)
// 读数据寄存器,保证 RDATA 在 RVALID 为高时稳定
val rdataReg = RegInit(0.U(dataWidth.W))
io.channels.read_data_channel.RDATA := rdataReg
switch(state) {
is(AXI4LiteStates.Idle) {
// 默认信号
ARREADY := false.B
RVALID := false.B
AWREADY := false.B
WREADY := false.B
BVALID := false.B
read := false.B
write := false.B
when(io.channels.read_address_channel.ARVALID) {
addr := io.channels.read_address_channel.ARADDR
ARREADY := true.B
state := AXI4LiteStates.ReadAddr
}.elsewhen(io.channels.write_address_channel.AWVALID) {
addr := io.channels.write_address_channel.AWADDR
AWREADY := true.B
state := AXI4LiteStates.WriteAddr
}
}
is(AXI4LiteStates.ReadAddr) {
// 已经完成 ARVALID/ARREADY 握手,将地址送给从设备并发起一次读
ARREADY := false.B
read := true.B
state := AXI4LiteStates.ReadData
}
is(AXI4LiteStates.ReadData) {
// 保持对设备的读请求,等待设备返回 read_valid
read := true.B
when(io.bundle.read_valid && !RVALID) {
// 设备已经准备好数据将其锁存并让RVALID为1
rdataReg := io.bundle.read_data
RVALID := true.B
}.elsewhen(RVALID && io.channels.read_data_channel.RREADY) {
// 主机已经接收数据,完成一次读事务
RVALID := false.B
read := false.B
state := AXI4LiteStates.Idle
}
}
is(AXI4LiteStates.WriteAddr) {
// 写地址握手结束,等待写数据
AWREADY := false.B
when(io.channels.write_data_channel.WVALID) {
// 收到写数据,锁存写数据及写选通
write_data := io.channels.write_data_channel.WDATA
val wstrb = io.channels.write_data_channel.WSTRB
when(wstrb === 0.U) {
write_strobe := VecInit(Seq.fill(Parameters.WordSize)(true.B))
}.otherwise {
write_strobe := VecInit(wstrb.asBools)
}
WREADY := true.B
write := true.B
state := AXI4LiteStates.WriteData
}
}
is(AXI4LiteStates.WriteData) {
// 向设备发出一次写请求WREADY 在一个周期后拉低
WREADY := false.B
write := false.B
BVALID := true.B
state := AXI4LiteStates.WriteResp
}
is(AXI4LiteStates.WriteResp) {
// 等待主机对写响应握手
when(io.channels.write_response_channel.BREADY) {
BVALID := false.B
state := AXI4LiteStates.Idle
}
}
}
}
class AXI4LiteMaster(addrWidth: Int, dataWidth: Int) extends Module {
val io = IO(new Bundle {
val channels = new AXI4LiteChannels(addrWidth, dataWidth)
val bundle = new AXI4LiteMasterBundle(addrWidth, dataWidth)
})
val state = RegInit(AXI4LiteStates.Idle)
io.bundle.busy := state =/= AXI4LiteStates.Idle
val addr = RegInit(0.U(dataWidth.W))
val read_valid = RegInit(false.B)
io.bundle.read_valid := read_valid
val write_valid = RegInit(false.B)
io.bundle.write_valid := write_valid
val write_data = RegInit(0.U(dataWidth.W))
val write_strobe = RegInit(VecInit(Seq.fill(Parameters.WordSize)(false.B)))
val read_data = RegInit(0.U(dataWidth.W))
io.channels.read_address_channel.ARADDR := 0.U
val ARVALID = RegInit(false.B)
io.channels.read_address_channel.ARVALID := ARVALID
io.channels.read_address_channel.ARPROT := 0.U
val RREADY = RegInit(false.B)
io.channels.read_data_channel.RREADY := RREADY
io.bundle.read_data := read_data
val AWVALID = RegInit(false.B)
io.channels.write_address_channel.AWADDR := 0.U
io.channels.write_address_channel.AWVALID := AWVALID
val WVALID = RegInit(false.B)
io.channels.write_data_channel.WVALID := WVALID
io.channels.write_data_channel.WDATA := write_data
io.channels.write_address_channel.AWPROT := 0.U
io.channels.write_data_channel.WSTRB := write_strobe.asUInt
val BREADY = RegInit(false.B)
io.channels.write_response_channel.BREADY := BREADY
//lab4(BUS)
// read_valid / write_valid 只拉高一个周期在switch之前清零以便switch可以覆盖
when(read_valid) { read_valid := false.B }
when(write_valid) { write_valid := false.B }
switch(state) {
is(AXI4LiteStates.Idle) {
ARVALID := false.B
RREADY := false.B
AWVALID := false.B
WVALID := false.B
BREADY := false.B
when(io.bundle.read) {
// 发起读事务
addr := io.bundle.address
state := AXI4LiteStates.ReadAddr
ARVALID := true.B
}.elsewhen(io.bundle.write) {
// 发起写事务
addr := io.bundle.address
write_data := io.bundle.write_data
write_strobe := io.bundle.write_strobe
state := AXI4LiteStates.WriteAddr
AWVALID := true.B
}
}
is(AXI4LiteStates.ReadAddr) {
// 发送读地址,直到从机准备好
ARVALID := true.B
io.channels.read_address_channel.ARADDR := addr
when(io.channels.read_address_channel.ARREADY) {
ARVALID := false.B
RREADY := true.B
state := AXI4LiteStates.ReadData
}
}
is(AXI4LiteStates.ReadData) {
// 保持 RREADY 高,等待从机 RVALID
RREADY := true.B
when(io.channels.read_data_channel.RVALID) {
read_data := io.channels.read_data_channel.RDATA
RREADY := false.B
read_valid := true.B
state := AXI4LiteStates.Idle
}
}
is(AXI4LiteStates.WriteAddr) {
// 发送写地址,直到从机准备好
AWVALID := true.B
io.channels.write_address_channel.AWADDR := addr
when(io.channels.write_address_channel.AWREADY) {
AWVALID := false.B
WVALID := true.B
state := AXI4LiteStates.WriteData
}
}
is(AXI4LiteStates.WriteData) {
// 发送写数据,直到从机接受
WVALID := true.B
io.channels.write_data_channel.WDATA := write_data
io.channels.write_data_channel.WSTRB := write_strobe.asUInt
when(io.channels.write_data_channel.WREADY) {
WVALID := false.B
BREADY := true.B
state := AXI4LiteStates.WriteResp
}
}
is(AXI4LiteStates.WriteResp) {
// 等待从机写响应
BREADY := true.B
when(io.channels.write_response_channel.BVALID) {
BREADY := false.B
write_valid := true.B
state := AXI4LiteStates.Idle
}
}
}
}

View File

@@ -0,0 +1,40 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bus
import chisel3._
import riscv.Parameters
class BusArbiter extends Module {
val io = IO(new Bundle {
val bus_request = Input(Vec(Parameters.MasterDeviceCount, Bool()))
val bus_granted = Output(Vec(Parameters.MasterDeviceCount, Bool()))
val ctrl_stall_flag = Output(Bool())
})
val granted = Wire(UInt())
// Static Priority Arbitration
// Higher number = Higher priority
granted := 0.U
for (i <- 0 until Parameters.MasterDeviceCount) {
when(io.bus_request(i.U)) {
granted := i.U
}
}
for (i <- 0 until Parameters.MasterDeviceCount) {
io.bus_granted(i.U) := i.U === granted
}
io.ctrl_stall_flag := !io.bus_granted(0.U)
}

View File

@@ -0,0 +1,33 @@
// Copyright 2021 Howard Lau
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bus
import chisel3._
import peripheral.DummyMaster
import riscv.Parameters
class BusSwitch extends Module {
val io = IO(new Bundle {
val address = Input(UInt(Parameters.AddrWidth))
val slaves = Vec(Parameters.SlaveDeviceCount, new AXI4LiteChannels(Parameters.AddrBits, Parameters.DataBits))
val master = Flipped(new AXI4LiteChannels(Parameters.AddrBits, Parameters.DataBits))
})
val dummy = Module(new DummyMaster)
val index = io.address(Parameters.AddrBits - 1, Parameters.AddrBits - Parameters.SlaveDeviceCountBits)
for (i <- 0 until Parameters.SlaveDeviceCount) {
io.slaves(i) <> dummy.io.channels
}
io.master <> io.slaves(index)
}

Binary file not shown.