整体架构包括:MiniMIPS32 处理器、指令存储器(8KB~16KB,按字节编址),数据存储器(8KB ~16KB,按字节编址)、GPIO控制器(3个LED灯和4个7 段数码管)、32位定时器、地址译码接口模块。
1.MiniMIPS32.v:作为顶层模块,负责实例化各个处理阶段和相关模块,并连接它们的输入输出信号。
2.f_stage.v:实现指令取指阶段的功能,控制指令存储器的访问、获取下一条指令,并处理异常情况。
3.ifid_reg.v:指令译码阶段与取指阶段之间的寄存器,存储来自取指阶段的信息,并传递给译码阶段。
4.id_stage.v:实现流水线中的译码阶段功能,接收输入信号并输出译码阶段所需的控制信号和操作数。
5.idexe_reg.v:译码阶段与执行阶段之间的寄存器,存储来自译码阶段的信息,并传递给执行阶段。
6.exe_stage.v:实现流水线执行阶段的功能,接收来自译码阶段和 HILO 寄存器的信息,执行相应的操作和计算。
7.exemem_reg.v:执行阶段与访存阶段之间的寄存器,根据条件将来自执行阶段的信息传递给访存阶段,并在时钟上升沿时更新输出信号。
8.mem_stage.v:实现流水线存储器阶段的功能,处理来自执行阶段的信息,包括 ALU 操作码、写寄存器地址、写寄存器使能、写数据等,并处理异常相关信号。
9.memwb_reg.v:根据条件存储来自访存阶段的信息,并在时钟上升沿时将这些信息传递给写回阶段。
10.wb_stage.v:实现写回阶段的功能,处理数据存储器的读出数据以及写回寄存器的数据。
11.regfile.v:实现寄存器文件的功能,包括读写操作。
12.hilo.v:实现双端口寄存器的功能,用于数据的读取和写入。
实现指令取指阶段的功能时,依据输入的控制信号和状态,控制指令存储器的访问以及获取下一条指令,并处理异常情况。
执行过程:
根据复位信号,判断是否需要将指令存储器的访问使能信号(ce)设置为禁用状态。
根据复位信号,将当前指令地址(pc)初始化为初始值(PC_INIT),或者保持不变。
根据转移指令的相关输入信号,计算下一条指令的地址(pc_next)。
根据流水线暂停信号和其他条件,确定指令存储器的访问使能信号(ice)的有效性。
根据时钟信号,在不同情况下更新当前指令地址(pc):
当发生异常时,将当前指令地址(pc)设置为异常处理程序入口地址(cp0_excaddr)。
当流水线暂停信号(stall)为 NOSTOP 时,将当前指令地址(pc)更新为下一条指令地址(pc_next)。
根据不同情况,确定异常处理相关的输出信号(if_exccode_o 和 if_badvaddr_o)。
时钟信号(cpu_clk_50M)和复位信号(cpu_rst_n);转移指令相关的输入信号包括三个跳转地址(jump_addr_1、jump_addr_2 和 jump_addr_3)以及跳转选择信号(jtsel);异常处理相关的输入信号包括清空流水线信号(flush)和异常处理程序入口地址(cp0_excaddr)。
指令存储器的访问使能信号(ice)、当前指令地址(pc)、访问指令存储器的地址(iaddr)、下一条指令地址(pc_plus_4),以及异常处理相关的信号(if_exccode_o 和 if_badvaddr_o)。
(4)流程图
实现流水线中的译码阶段功能。接收多个输入信号,例如重置信号、指令、寄存器值等,并输出译码阶段所需的控制信号和操作数。
过程:
指令提取:首先,从指令存储器中读取指令,并将其分解为不同的字段,如操作码(op)、函数码(func)、目的寄存器(rd)、源寄存器(rs)、rt、移位量(sa)和立即数(imm)等。这些字段是指令的重要组成部分,它们决定了指令的行为。
指令识别:使用逻辑表达式或解码逻辑来识别具体的指令。例如,根据不同的操作码和函数码,可以识别出不同的指令,如系统调用(SYSCALL)、异常返回(ERET)、从协处理器0移动数据到寄存器(MFC0)和向协处理器0移动数据(MTC0)等。
设置输出信号:一旦指令被识别,根据指令的类型和需要执行的操作,设置相应的输出信号。这些输出信号将被用来控制处理器的后续阶段,如执行阶段或访问内存阶段。
cpu_rst_n:CPU 复位信号
id_pc_i:来自 IF 取值阶段的 PC 值
pc_plus_4:PC 加 4 的值
id_inst_i:来自指令存储器的指令字
rd1:来自通用寄存器堆的数据 1
rd2:来自通用寄存器堆的数据 2
exe2id_wreg、exe2id_wa、exe2id_wd:来自执行阶段的写回信号及相关信息
mem2id_wreg、mem2id_wa、mem2id_wd:来自访存阶段的写回信号及相关信息
exe2id_mreg、mem2id_mreg:来自执行阶段和访存阶段的流水线暂停信号
id_in_delay_i:位于译码阶段的指令是否是延迟槽指令
id_exccode_i:位于译码阶段的指令的异常类型编码
id_badvaddr_i:位于译码阶段的指令的错误地址
flush_im:取消从指令存储器 IM 读取的指令
id_alutype_o、id_aluop_o、id_whilo_o、id_mreg_o、id_wa_o、id_wreg_o、id_din_o:
传递给执行阶段的译码信息
id_src1_o、id_src2_o:传递给执行阶段的源操作数 1 和源操作数 2
rreg1、ra1、rreg2、ra2:传递给读通用寄存器堆的使能和地址
jump_addr_1、jump_addr_2、jump_addr_3、jtsel、ret_addr:转移指令的输出信号
stallreq_id:译码阶段的流水线暂停信号
cp0_addr:CP0 中寄存器的地址
id_pc_o:位于译码阶段的指令的 PC 值
id_in_delay_o:位于译码阶段的指令是否是延迟槽指令
next_delay_o:下一条进入译码阶段的指令是否是延迟槽指令
id_exccode_o:位于译码阶段的指令的异常类型编码
id_badvaddr_o:位于译码阶段的指令的错误地址
实现流水线执行阶段的功能,接收来自译码阶段和HILO寄存器的信息,并根据指令执行相应的操作和计算。该阶段的功能包括逻辑运算、移位运算、算术运算、数据移动,以及对 CP0 寄存器的读写操作。根据输入信号和内部操作码 exe_aluop_i 的不同,执行相应的操作,并将结果输出到对应端口。同时,根据计算结果检查是否发生整数溢出异常,并将异常码赋值给exe_exccode_o。
cpu_clk_50M和cpu_rst_n:时钟和复位信号。
exe_alutype_i和exe_aluop_i:从译码阶段获得的 ALU 类型和 ALU 操作码。
exe_src1_i和exe_src2_i:从译码阶段获得的操作数 1 和操作数 2。
exe_wa_i、exe_wreg_i、exe_mreg_i、exe_din_i和exe_whilo_i:从译码阶段
获得的写地址、写使能、内存使能、数据输入和 WHILO 相关信息。
ret_addr:转移指令添加的返回地址。
hi_i 和 lo_i:从 HILO 寄存器获得的数据。
mem2exe_whilo 和 mem2exe_hilo:从访存阶段获得的 HILO 寄存器的值。
wb2exe_whilo 和 wb2exe_hilo:从写回阶段获得的 HILO 寄存器的值。
cp0_addr_i 和 cp0_data_i:MFC0、MTC0 指令相关的 CP0 寄存器地址和数
据。
mem2exe_cp0_we、mem2exe_cp0_wa 和 mem2exe_cp0_wd:从访存阶段获得
的 CP0 寄存器写使能、写地址和写数据。
wb2exe_cp0_we、wb2exe_cp0_wa 和 wb2exe_cp0_wd:从写回阶段获得的 CP0
寄存器写使能、写地址和写数据。
exe_pc_i、exe_in_delay_i、exe_exccode_i 和 exe_badvaddr_i:异常处理相关的指令地址、延迟槽信号、异常代码和异常地址。
exe_aluop_o、exe_wa_o、exe_wreg_o、exe_wd_o、exe_mreg_o、exe_din_o、
exe_whilo_o 和 exe_hilo_o:送至执行阶段的 ALU 操作码、写地址、写使能、数据输出、内存使能、数据输出、WHILO 相关信息和 HILO 寄存器数据。
stallreq_exe:执行阶段暂停信号。
cp0_re_o、cp0_raddr_o、cp0_we_o、cp0_waddr_o 和 cp0_wdata_o:MFC0、
MTC0 指令相关的 CP0 寄存器读使能、读地址、写使能、写地址和写数据。
exe_pc_o、exe_in_delay_o、exe_exccode_o 和 exe_badvaddr_o:异常处理相关的指令信号
(4)流程图
实现了流水线存储器阶段的功能,该阶段接收来自执行阶段的信息,包括 ALU 操作码、写寄存器地址、写寄存器使能信号和写数据等。此外,还接收执行阶段的其他信号,如乘除寄存器使能、乘除寄存器数据以及是否处于乘除操作期间。该阶段将写回阶段所需的信息输出,包括写寄存器地址、写寄存器使能信号和写数据。同时,还输出控制数据存储器的信号,如存储器地址、写使能、写数据以及读数据选择信号。此外,该阶段还处理异常相关的信号,包括写异常处理相关寄存器的使能信号、地址和数据。
cpu_rst_n: CPU 的复位信号
mem_aluop_i: 从执行阶段获得的 ALU 操作码
mem_wa_i: 从执行阶段获得的写寄存器地址
mem_wreg_i: 从执行阶段获得的写使能信号
mem_wd_i: 从执行阶段获得的写数据
mem_mreg_i: 从执行阶段获得的内存写使能信号
mem_din_i: 从执行阶段获得的内存写数据
mem_whilo_i: 从执行阶段获得的 Hi-Lo 写使能信号
mem_hilo_i: 从执行阶段获得的 Hi-Lo 写数据
cp0_we_i: 从执行阶段获得的 CP0 协处理器写使能信号
cp0_waddr_i: 从执行阶段获得的 CP0 协处理器写地址
cp0_wdata_i: 从执行阶段获得的 CP0 协处理器写数据
wb2mem_cp0_we: 写回阶段到访存阶段的 CP0 协处理器写使能信号
wb2mem_cp0_wa: 写回阶段到访存阶段的 CP0 协处理器写地址
wb2mem_cp0_wd: 写回阶段到访存阶段的 CP0 协处理器写数据
mem_pc_i: 从执行阶段获得的程序计数器值
mem_in_delay_i: 从执行阶段获得的延迟输入信号
mem_exccode_i: 从执行阶段获得的异常码
mem_badvaddr_i: 从执行阶段获得的坏虚拟地址
cp0_status: CP0 协处理器的状态寄存器值
cp0_cause: CP0 协处理器的原因寄存器值
mem_wa_o: 送往写回阶段的写寄存器地址
mem_wreg_o: 送往写回阶段的写使能信号
mem_dreg_o: 送往写回阶段的写数据
mem_mreg_o: 送往写回阶段的内存写使能信号
dre: 送往写回阶段的字节选择信号
mem_whilo_o: 送往写回阶段的 Hi-Lo 写使能信号
mem_hilo_o: 送往写回阶段的 Hi-Lo 写数据
dce: 送往数据存储器的使能信号
daddr: 数据存储器的访问地址
we: 数据存储器的写使能信号
din: 待写入数据存储器的数据
cp0_we_o: 直接送往写回阶段的 CP0 协处理器写使能信号
cp0_waddr_o: 直接送往写回阶段的 CP0 协处理器写地址
cp0_wdata_o: 直接送往写回阶段的 CP0 协处理器写数据
cp0_pc: CP0 协处理器的程序计数器值
cp0_in_delay: 输入到 CP0 协处理器的延迟输入信号
cp0_exccode: CP0 协处理器的异常码
(4)流程图
实现了写回阶段(Write Back Stage),该阶段负责处理从数据存储器读取的数据以及将数据写回到目标寄存器。
cpu_rst_n:CPU 的复位信号。
wb_mreg_i:写回数据选择信号,用于选择写回目的寄存器的数据。
wb_dre_i:用于选择从数据存储器读出的数据的字节顺序。
wb_wa_i:写回目的寄存器的地址。
wb_wreg_i:写回使能信号,用于控制是否写回目的寄存器。
wb_dreg_i:从数据存储器读出的数据。
wb_whilo_i:写回目的寄存器是否为 HI/LO 寄存器的信号。
wb_hilo_i:写回 HI/LO 寄存器的数据。
dm:从数据存储器读出的数据。
wb_wa_o:写回目的寄存器的地址输出。
wb_wreg_o:写回使能信号输出。
wb_wd_o:写回数据输出。
wb_whilo_o:写回目的寄存器是否为 HI/LO 寄存器的信号输出。
wb_hilo_o:写回 HI/LO 寄存器的数据输出。
cp0_we_o:CP0 协处理器的写使能信号输出。
cp0_waddr_o:CP0 协处理器的写地址输出。
cp0_wdata_o:CP0 协处理器的写数据输出。
sign:有无符号加载存储器的控制信号。
实现了一个基本的寄存器文件(Register File)模块。该模块具有两个读端口和一个写端口,根据输入的地址、数据和控制信号执行寄存器的读写操作。
cpu_clk_50M: 时钟信号,50MHz 的 CPU 时钟。
cpu_rst_n: 复位信号,低电平有效。
wa: 写地址,用于指定要写入的寄存器的地址。
wd: 写数据,要写入寄存器的数据。
we: 写使能信号,用于控制是否进行写操作。
ra1: 读地址 1,用于指定要读取的寄存器的地址。
re1: 读使能信号 1,用于控制是否进行读操作。
ra2: 读地址 2,用于指定要读取的寄存器的地址。
re2: 读使能信号 2,用于控制是否进行读操作。
rd1: 读数据 1,从指定的读地址 1 处读取的数据。
rd2: 读数据 2,从指定的读地址 2 处读取的数据。
实现了双端口寄存器的功能,该模块配备了两个读端口和一个写端口,用于数据的读取和写入。写端口可以同时写入两个数据,这些数据分别存储在 hi_o 和 lo_o 寄存器中。读端口则用于单独读取 hi_o 和 lo_o 寄存器中的数据。
cpu_clk_50M:CPU 的时钟信号。
cpu_rst_n:复位信号。
we:写使能信号。
hi_i:写端口的高位数据输入信号。
lo_i:写端口的低位数据输入信号。
hi_o:读端口的高位数据输出信号。
lo_o:读端口的低位数据输出信号。
这是一个位于指令译码阶段和取指阶段之间的寄存器。ifid_reg 模块用于保存取指阶段传递的信息,并将这些信息传递到译码阶段。在特定条件下,该模块能够执行复位、清空流水线、流水线暂停和异常处理等操作。
时钟信号(cpu_clk_50M)、复位信号(cpu_rst_n)和来自取指阶段的信息(if_pc)。
送至译码阶段的指令地址(id_pc),取指阶段加四后的指令地址(id_pc_plus_4)。
9、idexe_reg.v
这是一个位于译码阶段和执行阶段之间的寄存器,用于存储从译码阶段接收到的信息,并将这些信息传递到执行阶段。
cpu_clk_50M: 50MHz 的 CPU 时钟信号。
cpu_rst_n: CPU 的复位信号,低电平有效。
id_alutype: 译码阶段的 ALU 类型信号。
id_aluop: 译码阶段的 ALU 操作码信号。
id_src1: 译码阶段的源操作数 1 信号。
id_src2: 译码阶段的源操作数 2 信号。
id_wa: 译码阶段的写入寄存器地址信号。
id_wreg: 译码阶段的写寄存器使能信号。
id_mreg: 译码阶段的写内存使能信号。
id_din: 译码阶段的写入数据信号。
id_whilo: 译码阶段的写 HILO 寄存器使能信号。
id_ret_addr: 转移指令(Return)的返回地址信号。
id_cp0_addr: MFC0(Move from Coprocessor 0)和 MTC0(Move to Coprocessor
id_in_delay: 异常处理阶段的延迟指令输入信号。
id_pc: 译码阶段的指令地址信号。
stall: 流水线暂停信号。
flush: 异常处理阶段的流水线清空信号。
id_exccode: 译码阶段的异常代码信号。
id_badvaddr: 异常处理阶段的无效地址信号。
exe_alutype: 执行阶段的 ALU 类型信号。
exe_aluop: 执行阶段的 ALU 操作码信号。
exe_src1: 执行阶段的源操作数 1 信号。
exe_src2: 执行阶段的源操作数 2 信号。
exe_wa: 执行阶段的写入寄存器地址信号。
exe_wreg: 执行阶段的写寄存器使能信号。
exe_mreg: 执行阶段的写内存使能信号。
exe_din: 执行阶段的写入数据信号。
exe_whilo: 执行阶段的写 HILO 寄存器使能信号。
exe_ret_addr: 转移指令(Return)的返回地址信号。
exe_cp0_addr: MFC0 ( Move from Coprocessor 0 ) 和 MTC0 ( Move to
Coprocessor 0)指令的寄存器地址信号。
exe_pc: 执行阶段的指令地址信号。
exe_in_delay: 执行阶段的延迟指令输入信号。
next_delay_o: 下一阶段的延迟指令输出信号。
exe_exccode: 执行阶段的异常代码信号。
exe_badvaddr: 执行阶段的无效地址信号。
(4)流程图
在流水线的执行阶段和访存阶段之间传递信息。根据不同的条件,将来自执行阶段的信息传递到访存阶段,并在时钟上升沿时更新输出信号。
cpu_clk_50M:CPU 的时钟信号。
cpu_rst_n:CPU 的复位信号。
exe_aluop:来自执行阶段的 ALU 操作码。
exe_wa:来自执行阶段的写入目标寄存器地址。
exe_wreg:指示是否对目标寄存器进行写操作。
exe_wd:来自执行阶段的写入数据。
exe_mreg:指示是否对内存寄存器进行写操作。
exe_din:来自执行阶段的写入内存数据。
exe_whilo:指示是否对 Hi/Lo 寄存器进行写操作。
exe_hilo:来自执行阶段的 Hi/Lo 寄存器数据。
mem_aluop:发送给访存阶段的 ALU 操作码。
mem_wa:发送给访存阶段的写入目标寄存器地址。
mem_wreg:指示访存阶段是否对目标寄存器进行写操作。
mem_wd:发送给访存阶段的写入数据。
mem_mreg:指示访存阶段是否对内存寄存器进行写操作。
mem_din:发送给访存阶段的写入内存数据。
mem_whilo:指示访存阶段是否对 Hi/Lo 寄存器进行写操作。
mem_hilo:发送给访存阶段的 Hi/Lo 寄存器数据。
根据不同的条件,将访存阶段的信息存储起来,并在时钟上升沿时将这些信息传递到写回阶段。
cpu_clk_50M: 时钟信号。
cpu_rst_n: 复位信号。
mem_wa: 访存阶段的写目标寄存器地址。
mem_wreg: 访存阶段的写使能信号。
mem_dreg: 访存阶段的读数据。
mem_mreg: 访存阶段的内存寄存器使能信号。
mem_dre: 访存阶段的数据读取扩展。
mem_whilo: 访存阶段的 Hi/Lo 寄存器使能信号。
mem_hilo: 访存阶段的 Hi/Lo 寄存器数据。
mem_cp0_we: 访存阶段的 CP0 写使能信号。
mem_cp0_waddr: 访存阶段的 CP0 写地址。
mem_cp0_wdata: 访存阶段的 CP0 写数据。
flush: 异常处理信号。
mem_sign: 有无符号加载存储器信号。
wb_wa: 写回阶段的写目标寄存器地址。
wb_wreg: 写回阶段的写使能信号。
wb_dreg: 写回阶段的读数据。
wb_mreg: 写回阶段的内存寄存器使能信号。
wb_dre: 写回阶段的数据读取扩展。
wb_whilo: 写回阶段的 Hi/Lo 寄存器使能信号。
wb_hilo: 写回阶段的 Hi/Lo 寄存器数据。
wb_cp0_we: 写回阶段的 CP0 写使能信号。
wb_cp0_waddr: 写回阶段的 CP0 写地址。
wb_cp0_wdata: 写回阶段的 CP0 写数据。
wb_sign: 写回阶段的有无符号加载存储器信号。
MiniMIPS32 处理器支持指令存储器(inst_rom)和数据存储器(data_ram),其操作由时钟信号(cpu_clk_50M)和复位信号(cpu_rst_n)进行控制。
cpu_clk_50M: CPU 的时钟信号
cpu_rst_n: CPU 的复位信号
连接到 inst_rom 模块的信号:
iaddr:指令地址输出
ice:指令使能输出
inst:指令输入
连接到 data_ram 模块的信号:
dce:数据使能输出
daddr:数据地址输出
we:数据写使能输出
din:数据输入
dm:数据输出
其他信号包括:
int_i:中断输入信号
pc:指令地址
id_pc_i:译码阶段的指令地址
re1:是否使用寄存器 1
ra1:寄存器 1 地址
rd1:寄存器 1 数据输出
re2:是否使用寄存器 2
ra2:寄存器 2 地址
rd2:寄存器 2 数据输出
jump_addr_1、jump_addr_2、jump_addr_3:跳转指令的地址
jtsel:跳转选择信号
id_aluop_o:译码阶段的 ALU 操作类型输出
id_alutype_o:译码阶段的 ALU 类型输出
id_src1_o:译码阶段的操作数 1 输出
id_src2_o:译码阶段的操作数 2 输出
id_wreg_o:译码阶段的写寄存器使能输出
id_wa_o:译码阶段的写寄存器地址输出
id_whilo_o:译码阶段的写 HI/LO 寄存器使能输出
id_mreg_o:译码阶段的写多路复用使能输出
id_din_o:译码阶段的写数据输入
exe_aluop_i:执行阶段的 ALU 操作类型输入
exe_alutype_i:执行阶段的 ALU 类型输入
exe_src1_i:执行阶段的操作数 1 输入
exe_src2_i:执行阶段的操作数 2 输入
exe_wreg_i:执行阶段的写寄存器使能输入
exe_wa_i:执行阶段的写寄存器地址输入
exe_whilo_i:执行阶段的写 HI/LO 寄存器使能输入
exe_mreg_i:执行阶段的写多路复用使能输入
exe_din_i:执行阶段的写数据输入
iaddr: 指令 ROM 的读地址
ice: 指令 ROM 的使能信号
inst: 指令 ROM 读取的指令
dce: 数据 RAM 的使能信号
daddr: 数据 RAM 的地址
we: 数据 RAM 的写使能信号
din: 数据 RAM 的写数据
dm: 数据 RAM 读取的数据
int_i: CP0 中断信号
在流水线处理中,多指令并行执行常常导致数据依赖问题,即后续指令依赖于前序指令的输出。MiniMIPS32采用数据前递技术,将生成的数据直接传送至依赖这些数据的指令,有效避免了因数据等待导致的流水线阻塞。这种策略显著降低了处理器运行时的延迟,并提升了指令的处理效率。具体来说,当指令B依赖于指令A的输出时,一旦指令A产生结果,该结果会立即被传递给指令B,无需指令A完成全部执行阶段。
MiniMIPS32处理器通过实现先进的控制流处理技术,有效管理程序中的跳转和分支。这包括采用延迟槽机制和分支预测算法,以优化如`beq`(条件分支)等转移指令的执行。延迟槽技术允许在转移指令之后插入可预测的指令,这样即便分支预测出现错误,也不会对性能造成显著影响。这种策略不仅提高了处理器处理控制流变化的能力,还减少了因分支错误预测导致的性能损失。
MiniMIPS32处理器在流水线操作中可能会遇到数据依赖或资源冲突,导致某些指令的执行需要暂时中止。为了应对这种情况,MiniMIPS32引入了暂停机制,允许处理器在必要时暂停流水线中的特定指令执行。这种机制确保了在解决依赖或冲突之前,相关指令不会继续进行。例如,当一条指令因数据相关性而需要等待前一条指令的结果时,处理器会自动插入等待周期,直到所需的数据变得可用。这种策略有助于维持流水线的稳定性,同时确保数据处理的准确性和效率。
发生暂停机制的场景主要包括以下几种情况:
1. 加载相关性:例如,当执行加载指令(如 LW 指令)时,数据可能在写回阶段才被获取。如果后续指令在数据加载完成之前就尝试使用这些数据,可能会导致数据错误。为了解决这个问题,流水线需要在加载指令完成之前暂停,以确保数据的正确性。
2. 多周期指令:某些指令,如除法指令(DIV),需要多个周期才能完成。在这些指令的执行过程中,流水线可能需要暂停,以确保其他指令不会干扰当前的除法操作。这种暂停机制有助于维护指令的正确执行顺序和结果的准确性。
七、异常处理:
在处理器的操作过程中,可能会遭遇多种未预见的事件,例如非法内存访问或算术运算错误。为了应对这些情况,MiniMIPS32 设计了一套全面的异常处理系统。该系统能够在异常情况发生时,迅速识别并采取行动。具体来说,处理器会首先保存当前的执行状态,然后转移到一个专门的异常处理程序。在异常得到妥善处理之后,处理器将恢复到原先的状态,继续执行后续的指令。这种机制不仅保障了系统的稳定性,也确保了其在面对突发状况时的可靠性。
异常通常被归类为以下五种类型:
1. 指令执行错误:这包括执行不存在的指令、进行除以零的除法运算、计算结果超出预期范围的溢出,以及内存地址对齐错误等情形。
2. 数据完整性问题:当采用如ECC(错误校正码)等硬件校验机制的存储设备检测到校验失败时,会触发此类异常。
3. 地址转换异常:在存储管理单元尝试对内存页进行地址转换过程中,如果硬件转换表中缺少相应的条目,将引发此类异常。
4. 系统调用和陷阱:由特定的系统指令触发,用于请求操作系统内核执行特定的操作。
5. 外部事件(中断):包括由外部设备如键盘、鼠标或打印机等产生的中断。
CP0 协处理器的详细功能可以概述如下:
1. 处理器工作状态配置:利用其内部寄存器,CP0 能够调整 CPU 的多种特性,包括但不限于数据的字节序(大端或小端模式)。
2. 高速缓存控制:CP0 负责管理 CPU 缓存的读写操作,确保数据的快速存取。
3. 异常控制:CP0 具备检测异常事件的能力,并能够处理这些事件。这包括保存异常发生时的状态信息,并指导处理器跳转到相应的异常处理程序。
4. 存储管理:CP0 负责管理内存存储区域,包括内存分页和转换后备缓冲器(TLB)的控制,以优化内存访问效率。
5. 中断设置和处理:CP0 管理着中断的启用与屏蔽,以及处理来自外部设备的中断信号,确保系统能够及时响应外部事件。
CP0 协处理器内部包含多个寄存器,这些寄存器用于监控和控制不同类型的异常和中断,从而维护系统的稳定运行。
本次小学期的实验,首先总览地复习了前两个学期学到的计算机系统基础和计算机组成原理的知识点,五级流水线的构成(指令取指 IF、译码 ID、执行EXE、访存MEM和写回WB阶段)、每个阶段的具体任务、发生冒险时的处理机制(数据、结构、控制冒险)。同样,在过去的课程实验中,已经尝试在verilog中实现单周期cpu和多周期cpu,而这次需要学习verilog中流水线cpu的代码。
本次小学期不仅复习了之前的知识点,在再一次学习流水线cpu的机制和verilog中处理器代码时,我也学到了新的知识。
一个流水线处理器的基本任务(五段流水及流水段寄存器的模块):从MiniMIPS32处理器原型系统和本身的顶层设计图开始分析,我们可以明确思路就是将每一部分进行模块化,然后具体实现,也就是说如果要理解每一句代码,那变量的设计就要在这里分清了。利用这两个整体逻辑图,我们就可以具体分析每一个verilog文件的内容,也就是我们主要的任务。按照流水线处理器的思路,一定设立了五个阶段,利用理论知识分析每个阶段的代码,然后会看到一些信号传递,产生疑问。然后查询理清,这是阶段之间需要信号协调,让不同指令处在不同阶段同时执行,沿着思路,就需要各个阶段之间的寄存器,接下来再分析寄存器文件(Regfile、HI/LO)思路和具体内容即可。其中,比较难学的是控制信号的传递,例如在译码阶段生成的控制信号,通过寄存器文件传递到控制阶段,就可以联系影响执行阶段的操作,像要使用ALU或执行指令之类,这就要涉及三个文件的分析。到这一程度,我已经知道流水线处理器的大部分内容的工作机制,可是再看代码,为什么一直会有一些奇怪的变量和条件判断,这是因为MiniMIPS32处理器是一个具体处理器,一定有着自己规定的特殊机制,然后开始分析与课堂中常规学到的不同部分。
一个优秀的流水线处理器的高端任务(支持定向前推、转移指令、支持暂停机制、异常处理):这一阶段依然先从整体出发,分析一下这些机制是什么原理。例如,通过上学期的学习我已经熟知定向前推的目的,是优化时间,即使将某个指令的结果转给下一个用到该指令结果的指令,以便流水高效工作,那么衔接这个思路,我们就去找.v文件中的转发机制即可。
最后说一下学习感受,事实上这段代码实际的工程量难以想象,如果尝试在一个月里实现,即使照着敲一遍,并确保每一部分不出错,可能就要耗时两周多。但通过已经优化且完成的代码进行学习,让我学习到流水线处理器的实现内容和看到更多的细节方面,也让我发现自己平时在学习的过程中不应该只注重练习,也要注重代码方式和细节的学习,例如注释给出的思路,变量的放置等。学习模块化后的代码,梳理文件的关系,也强化了我以后敲代码对每一模块作用细化的能力。