*计导大作业———冯诺依曼式CPU模拟器*

(记录一下计导大作业的艰难经历)
  我觉得在写这个实验之前最先要做得就是卸载Dev-C++,这个IDE是真的不太好用,曾经一个助教就怒斥我还在用Dev【笑哭】。强烈推荐VS2019,如果你是一个爱折腾的人也可以考虑VScode,现阶段对于我来说两者的区别就是,VS内存贼大,编译稍微慢一点,而code打开项目很快。如果你想下载完打开就能用,少下个20G的游戏就用VS,或者花半天时间去设置一下VScode。当然如果刚开始用VS2019可能会有一些不习惯,上B站看会小姐姐教程就好了。
  本次计导实验过程不算复杂,但是唯一恶心人的就是指令集不完整,正常来说寄存器与主存的交互大多是RR型,RS型,SR型,SS型,以及与立即数的交互,但是老师给出的指令集只有一部分,大部分都是与立即数的交互和SR型,所以如果你只写了指令集上有的部分应该是过不了的,最好的方法是把所有情况都写进去,其实也没有增加写的代码,因为写好一种指令类型就可以拷贝过去,稍微改一下运算符即可。
  对于整整12个寄存器,最好把他们封装成一个struct Register结构体,减少函数要传的参数,毕竟不能单核使用全局变量,而且最大限度减小错误。
  主要思路:
  单核:
  用malloc动态分配一个32768长度的short类型的一维数组,模拟主存。将主存初始化为0后,将指令序列从文件中读出,一条指令是32个01组成的字符串,每8位转化为一个short整型,即代码段中每四位short是一条指令。
用程序计数器ip定位运行到哪条指令,第一位short是指令类型,第二位确定源寄存器和目的寄存器,第三位和第四位转化为一个立即数,若第三位大于128说明立即数是负数,要注意区分转化。分析完指令后要将ip+4(主存4个short是一条指令),指向下一条指令。
取得并分析指令后根据指令类型在自动机里执行相应的case语句,即完成相应指令操作。完成后输出所有寄存器的值,并且判断是否是停机指令。若为停机指令,则自动机输出相应停机状态,退出while循环,指令执行完毕。遇到停机指令后,输出代码段和数据段的值,代码段把每四位short整型转化位int型输出,数据每两位转化并输出。
 多核:
 多核中要求两个核心要共享内存,于是把主存memory设为全局变量,以便两个子线程访问主存。两个子线程执行的代码是相同的,根据要求修改读入指令序列函数ReadCmdFile(),把指令序列同时写入地址256开始处,而且在子线程初始化寄存器后,把程序寄存器ip分别设为0和256,同时把主存16384处该为票数100或10(测试)。根据多核新加的两条有关锁内存的指令,增加互斥锁hMutex,以实现该指令要求。
为了使两个子线程都能顺利运行,设置了hMu互斥锁,用于Output函数和PutReg函数,防止两个函数在输出时由于线程竞争而打断。 
单核的验收是在oj上通过即可。多核的验收要求模块化和检查运行结果的准确性。多核运行结果的检查和单核不一样,多核每次运行的结果都是不同的,不能通过对比老师给出的运行结果来确定准确性。正确的做法是检查Output函数,即输出指令的结果是否是从9递减到0。注意不能重复和遗漏,因为票是一张一张卖的,核1和核2都可能输出,这不影响。
如,
在这里插入图片描述
在这里插入图片描述
这里就不一一给出了。
在这里插入图片描述

模块化的实现其实就是把一个长的.c文件分成多个.c文件,不会让人只看一个很长的文件看得那么 累,也更好维护。用vs2019的话就是在源文件那里多建几个.c文件,在头文件那里建立.h文件。这些网上也有很多教程,不多说了。要注意的是,头文件只能放函数声明,全局变量声明,类型定义,而全局变量的定义和函数定义应该放在.c文件中,更为准确的说,头文件只能放不分配内存的那些东西。
最后分享一下单核和多核的源代码,望debug愉快。
传送门——>gitee仓库
https://gitee.com/zqiusen/computer-CPU-simulator
单核:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define CMD_LEN 32
#define MEM_SIZE 32768
#define REG_LEN 2
#define CODE_GROUP 4
#define DATA_GROUP 2
#define OUT_LINES 16
#define CODE_LINE 8
#define DATA_LINE 16
#define EIGHTBYTE 256
typedef struct reg
{
	short genReg[9];//寄存器1到8
	short ir[2];//指令寄存器
	short ip;//程序计数器
	short flag;//标志寄存器
	short numReg;//立即数寄存器
}Register;
short* Init(Register* Reg);//主存初始化
void ReadCmdFile(short* memory);
short byte_to_short(char* s, int start);//把从start处后8位得字符串翻译成short型整数
void Getcmd(short* memory, Register* Reg);//取指令
short State_trans(short* memory, Register* Reg);
void Data_transfer(short* memory, Register* Reg);
void Arith_add(short* memory, Register* Reg);//加法
void Arith_sub(short* memory, Register* Reg);//减法
void Arith_multiply(short* memory, Register* Reg);//乘法
void Arith_div(short* memory, Register* Reg);//除法
void And_oper(short* memory, Register* Reg);//与
void Or_oper(short* memory, Register* Reg);
void Not_oper(short* memory, Register* Reg);
void Compare(short* memory, Register* Reg);
void Jump(short* memory, Register* Reg);
void Input(short* memory, Register* Reg);
void Output(short* memory, Register* Reg);
void PutReg(Register* Reg);
void Outmemory(short* memory);
int main()
{
	int stop = 0;
	Register Reg;//寄存器
	short* memory = Init(&Reg);//初始化内存和寄存器
	ReadCmdFile(memory);
	while (!stop)
	{
		Getcmd(memory, &Reg);
		stop = State_trans(memory, &Reg);
	}
	Outmemory(memory);
	free(memory);
	return 0;
}
short* Init(Register* Reg)
{
	int i = 0;
	short* p = (short*)malloc(sizeof(short) * MEM_SIZE);
	for (i = 0; i < MEM_SIZE; i++)
	{
		p[i] = 0;
	}
	Reg->flag = 0;
	for (i = 0; i < 9; i++)
	{
		Reg->genReg[i] = 0;
	}
	Reg->ip = 0;
	Reg->ir[0] = 0;
	Reg->ir[1] = 0;
	Reg->numReg = 0;
	return p;
}
short byte_to_short(char* s, int start)//把从start处后8位得字符串翻译成short型整数
{
	int i = 0, j = 7;
	short sum = 0;
	for (i = start; i < start + 8; i++)
	{
		sum += (s[i] - '0') * pow(2, j);
		j--;
	}
	return sum;
}
void ReadCmdFile(short* memory)
{
	FILE* fp = fopen("dict.dic", "r");
	char s[CMD_LEN + 1] = "";
	int i = 0;
	while (fscanf(fp, "%s", s))
	{
		if (feof(fp))
			break;
		memory[i++] = byte_to_short(s, 0);
		memory[i++] = byte_to_short(s, 8);
		memory[i++] = byte_to_short(s, 16);
		memory[i++] = byte_to_short(s, 24);
	}
}
void Getcmd(short* memory, Register* Reg)//取指令
{
	Reg->ir[0] = memory[Reg->ip];
	Reg->ir[1] = memory[Reg->ip + 1];
	if (memory[Reg->ip + 2] >= 128)//立即数有可能是负数
		Reg->numReg = (memory[Reg->ip + 2] - 256) * EIGHTBYTE + memory[Reg->ip + 3];
	else Reg->numReg = memory[Reg->ip + 2] * EIGHTBYTE + memory[Reg->ip + 3];
	Reg->ip += 4;
}
short State_trans(short* memory, Register* Reg)
{
	int type = Reg->ir[0];
	int stopflag = 0;
	switch (type)
	{
	case 0://停机
		stopflag = 1;
		break;
	case 1:
		Data_transfer(memory, Reg);
		break;
	case 2:
		Arith_add(memory, Reg);
		break;
	case 3:
		Arith_sub(memory, Reg);
		break;
	case 4:
		Arith_multiply(memory, Reg);
		break;
	case 5:
		Arith_div(memory, Reg);
		break;
	case 6:
		And_oper(memory, Reg);
		break;
	case 7:
		Or_oper(memory, Reg);
		break;
	case 8:
		Not_oper(memory, Reg);
		break;
	case 9:
		Compare(memory, Reg);
		break;
	case 10:
		Jump(memory, Reg);
		break;
	case 11:
		Input(memory, Reg);
		break;
	case 12:
		Output(memory, Reg);
		break;
	}
	PutReg(Reg);
	if (stopflag)
		return 1;
	else return 0;
}
void PutReg(Register* Reg)
{
	printf("ip = %hd\n", Reg->ip);
	printf("flag = %hd\n", Reg->flag);
	printf("ir = %hd\n", Reg->ir[0] * EIGHTBYTE + Reg->ir[1]);
	printf("ax1 = %hd ax2 = %hd ax3 = %hd ax4 = %hd\n", Reg->genReg[1], Reg->genReg[2], Reg->genReg[3], Reg->genReg[4]);
	printf("ax5 = %hd ax6 = %hd ax7 = %hd ax8 = %hd\n", Reg->genReg[5], Reg->genReg[6], Reg->genReg[7], Reg->genReg[8]);
}
void Outmemory(short* memory)
{
	int i, j, count = 0, sum;
	printf("\ncodeSegment :\n");
	for (i = 0; i < 16; i++)
	{
		for (j = 0; j < 8; j++)
		{
			sum = memory[count] * 16777216 + memory[count + 1] * 65536 + memory[count + 2] * 256 + memory[count + 3];
			printf("%d ", sum);
			count += 4;
		}
		printf("\n");
	}
	printf("\ndataSegment :\n");
	count = 16384;
	for (i = 0; i < 16; i++)
	{
		for (j = 0; j < 16; j++)
		{
			sum = memory[count] + memory[count + 1] * 256;//特别诡异的地方
			printf("%d ", sum);
			count += 2;
		}
		printf("\n");
	}
}
void Data_transfer(short* memory, Register* Reg)
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0)//立即数->R
	{
		Reg->genReg[Dreg] = Reg->numReg;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M->R
	{
		Reg->genReg[Dreg] = memory[Reg->genReg[Sreg]];
	}
	else if (Sreg >= 5 && Dreg >= 5)//M->M
	{
		memory[Reg->genReg[Dreg]] = memory[Reg->genReg[Sreg]];
	}
	else if (Sreg <= 4 && Dreg >= 5)//R->M
	{
		memory[Reg->genReg[Dreg]] = Reg->genReg[Sreg];
	}
	else if (Sreg <= 4 && Dreg <= 4)//R->R
	{
		Reg->genReg[Dreg] = Reg->genReg[Sreg];
	}
}
void Arith_add(short* memory, Register* Reg)//加法
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数->R
	{
		Reg->genReg[Dreg] += Reg->numReg;
	}
	else if (Sreg == 0 && Dreg >= 5)//立即数->M
	{
		memory[Reg->genReg[Dreg]] += Reg->numReg;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M->R
	{
		Reg->genReg[Dreg] += memory[Reg->genReg[Sreg]];
	}
	else if (Sreg >= 5 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] += memory[Reg->genReg[Sreg]];
	}
	else if (Sreg <= 4 && Dreg >= 5)//R->M
	{
		memory[Reg->genReg[Dreg]] += Reg->genReg[Sreg];
	}
	else if (Sreg <= 4 && Dreg <= 4)//R->R
	{
		Reg->genReg[Dreg] += Reg->genReg[Sreg];
	}
}
void Arith_sub(short* memory, Register* Reg)//减法
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数->R
	{
		Reg->genReg[Dreg] -= Reg->numReg;
	}
	else if (Sreg == 0 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] -= Reg->numReg;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M->R
	{
		Reg->genReg[Dreg] -= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg >= 5 && Dreg >= 5)//M->M
	{
		memory[Reg->genReg[Dreg]] -= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg <= 4 && Dreg >= 5)//R->M
	{
		memory[Reg->genReg[Dreg]] -= Reg->genReg[Sreg];
	}
	else if (Sreg <= 4 && Dreg <= 4)//R->R
	{
		Reg->genReg[Dreg] -= Reg->genReg[Sreg];
	}
}
void Arith_multiply(short* memory, Register* Reg)//乘法
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数->R
	{
		Reg->genReg[Dreg] *= Reg->numReg;
	}
	else if (Sreg == 0 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] *= Reg->numReg;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M->R
	{
		Reg->genReg[Dreg] *= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg >= 5 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] *= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg <= 4 && Dreg >= 5)//R->M
	{
		memory[Reg->genReg[Dreg]] *= Reg->genReg[Sreg];
	}
	else if (Sreg <= 4 && Dreg <= 4)//R->R
	{
		Reg->genReg[Dreg] *= Reg->genReg[Sreg];
	}
}
void Arith_div(short* memory, Register* Reg)//除法
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数->R
	{
		Reg->genReg[Dreg] /= Reg->numReg;
	}
	else if (Sreg == 0 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] /= Reg->numReg;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M->R
	{
		Reg->genReg[Dreg] /= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg >= 5 && Dreg >= 5)
	{
		memory[Reg->genReg[Dreg]] /= memory[Reg->genReg[Sreg]];
	}
	else if (Sreg <= 4 && Dreg >= 5)//R->M
	{
		memory[Reg->genReg[Dreg]] /= Reg->genReg[Sreg];
	}
	else if (Sreg <= 4 && Dreg <= 4)//R->R
	{
		Reg->genReg[Dreg] /= Reg->genReg[Sreg];
	}
}
void And_oper(short* memory, Register* Reg)//与
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数 && R
	{
		if (Reg->genReg[Dreg] && Reg->numReg)
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
	else if (Sreg == 0 && Dreg >= 5)//立即数 && M
	{
		if (memory[Reg->genReg[Dreg] && Reg->numReg])
			memory[Reg->genReg[Dreg]] = 1;
		else memory[Reg->genReg[Dreg]] = 0;
	}
	else if (Sreg >= 5 && Dreg <= 4)//M && R
	{
		if (Reg->genReg[Dreg] && memory[Reg->genReg[Sreg]])
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
	else if (Sreg >= 5 && Dreg >= 5)//M && M
	{
		if (memory[Reg->genReg[Dreg]] && memory[Reg->genReg[Sreg]])
			memory[Reg->genReg[Dreg]] = 1;
		else memory[Reg->genReg[Dreg]] = 0;
	}
	else if (Sreg <= 4 && Dreg >= 5)
	{
		if (memory[Reg->genReg[Dreg]] && Reg->genReg[Sreg])
			memory[Reg->genReg[Dreg]] = 1;
		else memory[Reg->genReg[Dreg]] = 0;
	}
	else if (Sreg <= 4 && Dreg <= 4)//R && R
	{
		if (Reg->genReg[Dreg] && Reg->genReg[Sreg])
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
}
void Or_oper(short* memory, Register* Reg)
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)//立即数 && R
	{
		if (Reg->genReg[Dreg] || Reg->numReg)
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
	else if (Sreg == 0 && Dreg >= 5)//立即数 && M
	{
		if (memory[Reg->genReg[Dreg] || Reg->numReg])
			memory[Reg->genReg[Dreg]] = 1;
		else memory[Reg->genReg[Dreg]] = 0;
	}
	else if (Sreg >= 5)//M && R
	{
		if (Reg->genReg[Dreg] || memory[Reg->genReg[Sreg]])
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
}
void Not_oper(short* memory, Register* Reg)
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0)//
	{
		if (!Reg->genReg[Dreg])
			Reg->genReg[Dreg] = 1;
		else Reg->genReg[Dreg] = 0;
	}
	else if (Sreg >= 5)
	{
		if (!memory[Reg->genReg[Sreg]])
			memory[Reg->genReg[Sreg]] = 1;
		else memory[Reg->genReg[Sreg]] = 0;
	}
}
void Compare(short* memory, Register* Reg)
{
	short Sreg = Reg->ir[1] % 16;
	short Dreg = Reg->ir[1] / 16;
	if (Sreg == 0 && Dreg <= 4)
	{
		if (Reg->genReg[Dreg] == Reg->numReg)
			Reg->flag = 0;
		else if (Reg->genReg[Dreg] > Reg->numReg)
			Reg->flag = 1;
		else if (Reg->genReg[Dreg] < Reg->numReg)
			Reg->flag = -1;
	}
	else if (Sreg == 0 && Dreg >= 5)
	{
		if (memory[Reg->genReg[Dreg]] == Reg->numReg)
			Reg->flag = 0;
		else if (memory[Reg->genReg[Dreg]] > Reg->numReg)
			Reg->flag = 1;
		else Reg->flag = -1;
	}
	else if (Sreg >= 5)
	{
		if (Reg->genReg[Dreg] == memory[Reg->genReg[Sreg]])
			Reg->flag = 0;
		else if (Reg->genReg[Dreg] > memory[Reg->genReg[Sreg]])
			Reg->flag = 1;
		else if (Reg->genReg[Dreg] < memory[Reg->genReg[Sreg]])
			Reg->flag = -1;
	}
	else if (Sreg <= 4)
	{
		if (Reg->genReg[Dreg] == Reg->genReg[Sreg])
			Reg->flag = 0;
		else if (Reg->genReg[Dreg] > Reg->genReg[Sreg])
			Reg->flag = 1;
		else  Reg->flag = -1;
	}
}
void Jump(short* memory, Register* Reg)
{
	int state = Reg->ir[1];
	if (state == 0)//无条件跳转
	{
		Reg->ip += Reg->numReg - 4;
	}
	else if (state == 1)
	{
		if (Reg->flag == 0)
			Reg->ip += Reg->numReg - 4;
	}
	else if (state == 2)
	{
		if (Reg->flag == 1)
			Reg->ip += Reg->numReg - 4;
	}
	else if (state == 3)
	{
		if (Reg->flag == -1)
			Reg->ip += Reg->numReg - 4;
	}
}
void Input(short* memory, Register* Reg)
{
	short Dreg = Reg->ir[1] / 16;
	printf("in:\n");
	if (Dreg <= 4)
		scanf("%hd", &Reg->genReg[Dreg]);
	else scanf("%hd", &memory[Reg->genReg[Dreg]]);
}
void Output(short* memory, Register* Reg)
{
	short Dreg = Reg->ir[1] / 16;
	printf("out: ");
	if (Dreg <= 4)
		printf("%hd\n", Reg->genReg[Dreg]);
	else printf("%hd\n", memory[Reg->genReg[Dreg]]);
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值