基于五阶段流水线的RISC-V CPU模拟器实现 (2)

编译会得到可执行程序Simulator。该模拟器是一个命令行程序,在命令行上的执行方式是

./Simulator riscv-elf-file-name [-v] [-s] [-d] [-b param] Parameters: [-v] verbose output [-s] single step [-d] dump memory and register trace to dump.txt [-b param] branch perdiction strategy, accepted param AT, NT, BTFNT, BPB

其中riscv-elf-file-name对应可执行的RISC-V ELF文件,比如riscv-elf/文件夹下的所有*.riscv文件。一个典型的运行流程和输出如下

hehaodeMacBook-Pro:build hehao$ ./Simulator ../riscv-elf/ackermann.riscv Ackermann(0,0) = 1 Ackermann(0,1) = 2 Ackermann(0,2) = 3 Ackermann(0,3) = 4 Ackermann(0,4) = 5 Ackermann(1,0) = 2 Ackermann(1,1) = 3 Ackermann(1,2) = 4 Ackermann(1,3) = 5 Ackermann(1,4) = 6 Ackermann(2,0) = 3 Ackermann(2,1) = 5 Ackermann(2,2) = 7 Ackermann(2,3) = 9 Ackermann(2,4) = 11 Ackermann(3,0) = 5 Ackermann(3,1) = 13 Ackermann(3,2) = 29 Ackermann(3,3) = 61 Ackermann(3,4) = 125 Program exit from an exit() system call ------------ STATISTICS ----------- Number of Instructions: 430754 Number of Cycles: 574548 Avg Cycles per Instrcution: 1.3338 Branch Perdiction Accuacy: 0.5045 (Strategy: Always Not Taken) Number of Control Hazards: 48010 Number of Data Hazards: 279916 Number of Memory Hazards: 47774 -----------------------------------

在默认的设置下,一开始会首先打印执行的程序的输出,然后会输出一组关于CPU执行情况的统计数据。

如果要进行单步调试的话,可以使用-s和-v参数

./Simulator ../riscv-elf/ackermann.riscv -s -v

得到的输出如下

hehaodeMacBook-Pro:build hehao$ ./Simulator ../riscv-elf/ackermann.riscv -s -v ==========ELF Information========== Type: ELF64 Encoding: Little Endian ISA: RISC-V(0xf3) Number of Sections: 19 ID Name Address Size [0] 0x0 0 [1] .text 0x100b0 3668 [2] .rodata 0x10f08 29 [3] .eh_frame 0x10f28 4 [4] .init_array 0x11000 8 [5] .fini_array 0x11008 8 [6] .data 0x11010 1864 [7] .sdata 0x11758 24 [8] .sbss 0x11770 8 [9] .bss 0x11778 72 [10] .comment 0x0 26 [11] .debug_aranges 0x0 48 [12] .debug_info 0x0 46 [13] .debug_abbrev 0x0 20 [14] .debug_line 0x0 222 [15] .debug_str 0x0 267 [16] .symtab 0x0 2616 [17] .strtab 0x0 913 [18] .shstrtab 0x0 172 Number of Segments: 2 ID Flags Address FSize MSize [0] 0x5 0x10000 3884 3884 [1] 0x6 0x11000 1904 1984 =================================== Memory Pages: 0x0-0x400000: 0x10000-0x11000 0x11000-0x12000 Fetched instruction 0x00002197 at address 0x100b0 Decode: Bubble Execute: Bubble Memory Access: Bubble WriteBack: Bubble ------------ CPU STATE ------------ PC: 0x100b4 zero: 0x00000000(0) ra: 0x00000000(0) sp: 0x80000000(2147483648) gp: 0x00000000(0) tp: 0x00000000(0) t0: 0x00000000(0) t1: 0x00000000(0) t2: 0x00000000(0) s0: 0x00000000(0) s1: 0x00000000(0) a0: 0x00000000(0) a1: 0x00000000(0) a2: 0x00000000(0) a3: 0x00000000(0) a4: 0x00000000(0) a5: 0x00000000(0) a6: 0x00000000(0) a7: 0x00000000(0) s2: 0x00000000(0) s3: 0x00000000(0) s4: 0x00000000(0) s5: 0x00000000(0) s6: 0x00000000(0) s7: 0x00000000(0) s8: 0x00000000(0) s9: 0x00000000(0) s10: 0x00000000(0) s11: 0x00000000(0) t3: 0x00000000(0) t4: 0x00000000(0) t5: 0x00000000(0) t6: 0x00000000(0) ----------------------------------- Type d to dump memory in dump.txt, press ENTER to continue:

在单步调试中,可以输入d来保存内存快照,使用ENTER前进到下一条指令。命令行显示的信息包括ELF信息、流水线状态和CPU寄存器状态。

使用-v参数并重定向标准输出可以得到关于流水线执行状态和寄存器状态的完整历史。

此外,可以使用-b参数指定不同的分支预测策略,例如

./Simulator ../riscv-elf/ackermann.riscv -b AT ./Simulator ../riscv-elf/ackermann.riscv -b NT ./Simulator ../riscv-elf/ackermann.riscv -b BTFNT ./Simulator ../riscv-elf/ackermann.riscv -b BPB

其中,AT表示Always Taken,NT表示Not Taken,BTFNT表示Back Taken Forward Not Taken,BPB表示Branch Prediction Buffer。

2.4 代码架构

基于五阶段流水线的RISC-V CPU模拟器实现

模拟器代码架构的概览图见上。模拟器的入口是Main.cpp,其中包含了解析参数、加载ELF文件、初始化模拟器的模块,并在最后调用模拟器的simulate()函数进入模拟器的执行。除非模拟器执行出错,否者simulate()函数理论上不会返回。

模拟器本身被设计成一个巨大的类,也就是代码中的class Simulator(参见Simulator.h、Simulator.cpp)。Simulator类中的数据包含了PC、通用寄存器、流水线寄存器、执行历史记录器、内存模块和分支预测模块,其中,由于内存模块和分支预测模块相对比较独立,因此实现为独立的两个类MemoryManager和BranchPredictor。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfxjz.html