基于C++仿真的MIPS32指令系统虚拟计算机设计与实现

目录
1 项目简介 4
2 功能介绍 4
2.1 概述 4
2.2 功能描述 4
2.2.1 指令控制 4
2.2.2 指令执行 5
2.2.3 内存控制 5
2.2.4 寄存器控制 5
2.2.5 流水线 6
2.2.6 使用说明 6
2.2.7 关于 7
2.2.8 退出 7
2.2.9 流水线绘图 7
3 设计介绍 7
3.1 设计思路 7
3.2 数据结构设计 8
3.3 功能模块设计 8
3.3.1 内存模块 9
3.3.2 寄存器模块 9
3.3.3 取指模块 9
3.3.4 译码模块 10
3.3.5 执行模块 10
3.3.6 记录模块 11
3.3.7 全局数据模块 11
3.3.8 菜单面板模块 11
3.3.9 流水线模块 12
3.3.10 控制模块 13
3.3.11 流水线绘图模块 14
4 关键算法 14
4.1 流水线生成 14
4.1.1 各项数据的意义 14
4.1.2 二维XY坐标系 15
4.1.3 寄存器占用检测与标记 16
4.1.4 部件占用检测与标记 16
4.1.5 时间点检测 17
4.1.6 生成步骤 18
4.2 流水线单步执行 19
4.2.1 二维XY坐标系的读取 19
4.2.2 时间点检测 19
4.2.3 各部件调用 19
4.3 流水线绘图 19
4.3.1 图形库调用 19
4.3.2 过程绘制 19
5 测试及结果 19
5.1 菜单面板 19
5.2 指令执行 21
5.2.1 测试前准备 21
5.2.2 全部执行 22
5.2.3 单步执行 23
5.3 流水线 24
5.3.1 全部流通情况 24
5.3.2 写$zero寄存器情况 26
5.3.3 数据相关情况 28
5.3.4 混合情况 30
6 详细设计 33
6.1 内存类 33
6.2 寄存器类 33
6.3 取指类 34
6.4 译码类 34
6.5 执行类 34
6.6 记录类 36
6.7 菜单面板类 36
6.8 全局数据类 37
6.9 流水线类 39
6.10 全局控制类 40
7 结束语 42
7.1 总结 42
7.2 展望 42
8 参考文献 43
1 项目简介
项目介绍:利用C/C++语言开发基于MIPS32指令系统的虚拟计算机。要求:
(1)完成MIPS32指令的取指、译码、计算、访存和写回五个步骤的软件模拟
(2)能够向系统输入机器语言源程序
(3)能够对内部寄存器进行初始花
(4)能够运行程序
(5)能够查看运行结果,能够反映指令的执行过程
(6)能够模拟五段流水线的执行过程
(7)能够解决数据相关的问题
(8)能够反映流水线的执行过程
开发语言:C/C++
开发环境:Windows10 1803、Visual Studio 2017
2 功能介绍
2.1 概述
为了满足“项目简介”中所提出的程序设计要求,故需要对程序的功能有明确的划分,让使用者能够很快上手并熟练的使用该程序。在本节中,笔者将对程序的各个功能模块做简单的介绍,以帮助使用者能够较快的知晓该程序的模块划分、各个模块的功能以及各个模块的使用方法。
本程序共分8个功能模块,分别为:1-指令控制、2-指令执行、3-内存控制、4-寄存器控制、5-流水线、6-使用说明、7-关于、8-退出。各个功能模块有其不同的功能及作用,读者从功能模块的名字大概可以猜测。每一个功能模块内部还有不同的小模块,具体的介绍将在下文详细展开描述。
为了能够更形象的展示流水线的过程,笔者还单独使用C语言编制了一个基于graphics图形库的程序,将控制台输出的信息以图形化方式呈现。此功能模块也将在下文做具体的介绍。
2.2 功能描述
2.2.1 指令控制
本功能模块负责指令的输入输出。程序在运行之前,必须有已经输入的指令序列,否则将不能够正常执行而直接退出。如果用户想要正常的使用该程序,则必须将已经准备好的指令序列输入。因为该虚拟计算机基于MIPS32指令集,所以每一条指令的长度固定为32位长度的0/1序列。
在输入时,用户可以选择单行或多行输入,但是在输入完毕后,必须另起一行,并以”##”作为结束标识,否则程序将不能够正确读取并译码。
在该模块下,有4个子模块,提供更加准确的指令控制,分别为:输入指令、查看指令、修改指令、清空指令,详细介绍如下:
(1)输入指令:提供单行或多行输入指令的功能,输入的指令将顺序存储在内存的00H-FFH区域。每一条32位的指令占用4个内存空间。
(2)查看指令:从内存的00H开始读取,直至FFH,若读取的内存区域不为00H内容,则判断有指令。程序调用“译码”功能,将32位的指令译码为能够阅读的汇编代码。
(3)修改指令:用户指定一个需要修改的指令地址,并给出要修改的指令。程序将根据指令地址与指令内容修改。注意,如果提供的指令地址与指令内容非法,程序将拒绝执行,要求用户重新提供正确的地址与内容。
(4)清空指令:清空程序内存区域中指令区域的所有指令内容,即将内存00H-FFH区域全部强制填为00H。
2.2.2 指令执行
本功能模块负责指令的执行控制。当用户输入指令后,便可以使用该功能模块模拟执行指令。注意,此功能模块所提供的指令执行是串行执行方法,与“项目简介”中所描述的“流水线”功能无关。
该功能模块下可细分为4个子模块,分别为:全部执行、单步执行、执行记录、清除记录,详细介绍如下:
(1)全部执行:一步执行完(内存指令区域的)全部指令,当执行完后,程序会列出所执行过的全部指令内容[ 具体有:执行时间、指令内容、指令解释、涉及到的寄存器信息]。
(2)单步执行:每次执行一条(内存指令区域)指令,当执行完后,程序会列出所执行过的指令的指令内容。
在“全部执行”与“单步执行”过程中,程序每次执行一条指令,都会向”record.txt”文件中写入一条执行记录,写入方式为追加写入,每次执行都会新起一行,不会修改之前写入过的记录。执行记录详细记录了指令执行的各项细节,包括:执行时间、指令内容、指令解释、涉及到的寄存器。本文转载自http://www.biyezuopin.vip/onews.asp?id=14678用户可以在程序目录下的”record.txt”文件中查看具体的细节。
(3)执行记录:查看存储在程序同目录下”record.txt”文件中的内容,即所有的指令执行记录。
(4)清除记录:将存储在程序同目录下”record.txt”文件中的内容全部清空。

6.1 内存类
#pragma once
#include "overalldata.h"
class CMemory
{
public:char mem[MEMORY_NUM]; 
private:
	int instruction_size;
	int data_size;
	int memory_state;
	int current_instruction_address;
public:
	CMemory();
	~CMemory();
	int SetMemoryBusy();
	int SetMemoryFree();
	int ReturnCurrentState(int &);
	int InitAllMemoryWith0();
	int InitAllMemoryWithValue(int); 
	int WriteToMemory(int, char); 
	int ReadFromMemory(int, char &);
	int ResetCurrentInstructionAddress();
	int GetCurrentInstructionAddress();
	int AddInstructionAddress(); 
};
6.2 寄存器类
#pragma once
#include "overalldata.h"
#include <string>
using namespace std;
class CRegister
{
public:int reg[REGISTER_NUM];
private:
	int register_state;
public:
	CRegister();
	~CRegister();
	int SetRegisterBusy();
	int SetRegisterFree(); 
	int ReturnCurrentState(int &);
	int InitAllRegisterWith0();
	int InitAllRegisterWithValue(int);
	int WriteToOneRegister(int, int);
	int ReadFromOneRegister(int, int &); 
};
6.3 取指类
#pragma once
#include "overalldata.h"
class CFetch
{
public:int PC;
private:
	int fetch_state;
public:
	CFetch();
	~CFetch();
	int SetFetchBusy(); 
	int SetFetchFree();
	int ReturnCurrentState(int &);
	int GetPC();
	int PCSelfAdd();
	int EditPC(int);
	int ResetPC();
	int FetchInstructionFromMemory(int, char[], int &);
};
6.4 译码类
#pragma once
#include "overalldata.h"
class CDecoding
{
private:
	int decoding_state;
public:
	CDecoding();
	~CDecoding();
	int SetDecodingBusy();
	int SetDecodingFree();
	int ReturnCurrentState(int &);
	int BitSelectTransform(int, int, int, int &);
	int InstructionsDecoding(int, InstructionStruct &, int &);
	bool InstructionCheckZero(int instruction_type, InstructionStruct data);
};
6.5 执行类
#pragma once
#include <string>
#include "overalldata.h"
using namespace std;
class CExecute
{
private:
	int execute_state;
	int instruction_num;
public:
	CExecute();
	~CExecute();
	int SetExecuteBusy();
	int SetExecuteFree();
	int ReturnCurrentState(int &); 
	int sign_extended(int &);
	int zero_extended(int &);
	//R-Type
	int execute_addu(InstructionStruct, int[]);
	int execute_subu(InstructionStruct, int[]);
	int execute_and(InstructionStruct, int[]);
	int execute_or(InstructionStruct, int[]);
	int execute_xor(InstructionStruct, int[]);
	int execute_nor(InstructionStruct, int[]);
	int execute_sll(InstructionStruct, int[]);
	int execute_srl(InstructionStruct, int[]);
	int execute_jr(InstructionStruct, int[], int &);
	//I-Type
	int execute_addi(InstructionStruct, int[]);
	int execute_andi(InstructionStruct, int[]);
	int execute_ori(InstructionStruct, int[]);
	int execute_xori(InstructionStruct, int[]);
	int execute_lw(InstructionStruct, int[], char[]);
	int execute_sw(InstructionStruct, int[], char[]);
	int execute_beq(InstructionStruct, int[], int &);
	//J-Type
	int execute_j(InstructionStruct, int &);

	int ExecuteControl(int instruction_type, InstructionStruct instruction_data, char memory[], int reg[], int &PC);
	int ExecuteControlCheckIfOk(int instruction_type, InstructionStruct instruction_data, char memory[], int reg[], int &PC);
	int ExecuteControlAction(int instruction_type, InstructionStruct instruction_data, char memory[], int reg[], int &PC);
	string KnowExecuteDetail(int instruction_type, InstructionStruct data, char mem[], int reg[], int &PC);
	int KnowExecuteResult(int instruction_type, InstructionStruct data, char mem[], int reg[], int &PC);
	int KnowMemoryReadContent(int instruction_type, InstructionStruct data, char mem[], int reg[]);
	string KnowWhichToWriteTo(int instruction_type, InstructionStruct data, char mem[], int reg[]);
};

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sheziqiong/article/details/127133443