⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipelinedoc.cpp

📁 计算机体系结构中关于通用5级流水线的模拟实现程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// PipelineDoc.cpp : implementation of the CPipelineDoc class
//

#include "stdafx.h"
#include "Pipeline.h"

#include "PipelineDoc.h"
#include "DataSet.h"

#include<stdio.h>
#include<string.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPipelineDoc

IMPLEMENT_DYNCREATE(CPipelineDoc, CDocument)

BEGIN_MESSAGE_MAP(CPipelineDoc, CDocument)
	//{{AFX_MSG_MAP(CPipelineDoc)
	ON_COMMAND(ID_STEP, OnStep)
	ON_COMMAND(ID_DataSet, OnDataSet)
	ON_COMMAND(ID_RESET, OnReset)
	ON_COMMAND(ID_Delay, OnDelay)
	ON_COMMAND(ID_Flush, OnFlush)
	ON_COMMAND(ID_Taken, OnTaken)
	ON_COMMAND(ID_NotTaken, OnNotTaken)
	ON_COMMAND(ID_Forward, OnForward)
	ON_COMMAND(ID_NoForward, OnNoForward)
	ON_UPDATE_COMMAND_UI(ID_Delay, OnUpdateDelay)
	ON_UPDATE_COMMAND_UI(ID_Flush, OnUpdateFlush)
	ON_UPDATE_COMMAND_UI(ID_Forward, OnUpdateForward)
	ON_UPDATE_COMMAND_UI(ID_NoForward, OnUpdateNoForward)
	ON_UPDATE_COMMAND_UI(ID_NotTaken, OnUpdateNotTaken)
	ON_UPDATE_COMMAND_UI(ID_Taken, OnUpdateTaken)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPipelineDoc construction/destruction

CPipelineDoc::CPipelineDoc()
{
	// TODO: add one-time construction code here
	clear();
}

CPipelineDoc::~CPipelineDoc()
{
}

BOOL CPipelineDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}

BOOL CPipelineDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
//	TRACE("Enter doucument!");
	if(!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
//获得新打开文件的文件名
	GoodFile=readfile(lpszPathName);

	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CPipelineDoc serialization

void CPipelineDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

int CPipelineDoc::chartoint(char *str) 
{//字符串变整数
	int Int_val=0,flag=1;
	if(*str=='-')
	{	flag=0;str++; }
	while(*str)
	{
		Int_val=10*Int_val+(*str)-'0';
		str++;
	}
	if(flag==1)
		return Int_val;
	else
		return -Int_val;
}

void CPipelineDoc::uptolow(char *str) 
{//大写转成小写
	int i=0;
	while(str[i])
	{
		if(str[i]>='A'&&str[i]<'Z')
			str[i]+=32;
		i++;
	}
}

void CPipelineDoc::standard(char *str) 
{//删除多余的空格和tab
	bool flag=false;
	int i=0,j=0;
	char temp[30];
	while(str[i])
	{
		if(str[i]!=' '&&str[i]!='\t')
		{
				temp[j]=str[i];
				i++,j++;
		}
		else
		{
			if(flag==false)
			{
				flag=true;
				temp[j]=' ';
				j++;
			}
			i++;
		}
	}
	temp[j]=0;
	strcpy(str,temp);
} 

bool CPipelineDoc::readfile(LPCTSTR filename)
{//按行读入文件,并调用translate转化成二进制代码
	char buffer[30],temp;
	int i,j=0,N_im=0;
	FILE *fp;
	CString str="error:no such file";

	clear();
	if((fp=fopen(filename,"r"))==NULL)
	{
		AfxMessageBox(str);     //打开文件出错,显示出错信息
		return false;
	}
	while(1)
	{
		i=0;
		temp=getc(fp);
		while(temp==' '||temp=='\t'||temp=='\n')
			temp=getc(fp);//继续读取
		if(temp==EOF)
			break;
		while(temp!='\n'&&temp!=EOF)
		{
			buffer[i++]=temp;
			temp=getc(fp);
			if(i>=29)
				break; //读完一行
		}
		buffer[i]=0;
		standard(buffer);//删除多余的空格和tab
		uptolow(buffer);
		//读入一行到buffer经过规整化后,传入translate
		if(!translate(&IM[N_im],buffer))
		{
			str="error:illeage instruction";
			AfxMessageBox(str);
			for(i=0;i<=N_im;i++)
			{//非法语句时,清空已经读入的语句
				IM[i]=0;
				attr[i][0]='\0';
			}
			return false;
		}
		else
		{
			strcpy(attr[N_im],buffer);
			N_im++;
		}
	}

	fclose(fp);
	return true;
}

bool CPipelineDoc::translate(unsigned long *im,char *str)
{//把读入的一条指令转化为二进制代码
	//指令集
	char *instr[22]={ "stall","add","sub","and","or","xor","mut","div",
				"addi","subi","andi","ori","xori","muti","divi",
				"lw","sw","beqz","bnez","j","jr","trap" };
	//寄存器集
	char *reg_smb[32]={ "$zero","$at","$v0","$v1","$a0","$a1","$a2","$a3",
				"$t0","$t1","$t2","$t3","$t4","$t5","$t6","$t7",
				"$s0","$s1","$s2","$s3","$s4","$s5","$s6","$s7",
				"$t8","$t9","hi","lo","$gp","$fp","$sp","$ra"};
	char temp[8],i=0,j=0,t,k,l;
	unsigned long change=0; //中间变量,用以给内存单元赋值
	//读入命令字段
	while(str[i]==' '||str[i]=='\t')
		i++;
	while(str[i]!=' '&&str[i]!='\t')
	{
		temp[j]=str[i];
		i++;j++;
		if(j>=7)
			break;
	}
	temp[j]=0;
	//判断是指令类型,或者非法指令
	for(t=0;t<22;t++)
	{
		if(!strcmp(temp,instr[t]))
			break;
	}
	if(t>=22)//指令不在指令集内,非法
		return false;
	change=t;
	change=change<<26;
	temp[j]=' ';temp[j+1]=0; j=0;
	*im=change;
	if(t==21)//trap指令
		return true;
	if(t>=1&&t<=5)
	{//"add","sub","and","or","xor"
		for(k=0;k<3;k++)
		{//后面有三个寄存器
			while(str[i]!=','&&str[i]!='\0')
			{
				if(str[i]!=' '&&str[i]!='\t')
				{
					temp[j++]=str[i]; i++;
				}
				else
					i++;
				if(j>=7)
					break;
			}
			temp[j]=0;
			for(l=0;l<32;l++)
			{
				if(!strcmp(temp,reg_smb[l]))
					break;
			}
			if(l>=32)
				return false;
			change=l;
			switch(k)
			{
			case 0:
				change=change<<11;
				break;
			case 1:
				change=change<<21;
				break;
			case 2:
				change=change<<16;
				break;
			}
			*im=*im|change;
			j=0;i++;
		}
	}
	if(t>=6&&t<=7)
	{//"mut","div"
		for(k=0;k<2;k++)
		{//两个寄存器
			while(str[i]!=','&&str[i]!='\0')
			{
				if(str[i]!=' '&&str[i]!='\t')
				{
					temp[j++]=str[i]; i++;
				}
				else
					i++;
				if(j>=7)
					break;
			}
			temp[j]=0;

			for(l=0;l<32;l++)
			{
				if(!strcmp(temp,reg_smb[l]))
					break;
			}
			if(l>=32)
				return false;
			change=l;
			switch(k)
			{
			case 0:
				change=change<<21;
				break;
			case 1:
				change=change<<16;
				break;
			}
			*im=*im|change;
			j=0;i++;
		}
	}
	if(t>=8&&t<=12)
	{//"addi","subi","andi","ori","xori"
		for(k=0;k<3;k++)
		{//两个寄存器,一个数字
			while(str[i]!=','&&str[i]!='\0')
			{
				if(str[i]!=' '&&str[i]!='\t')
				{
					temp[j++]=str[i]; i++;
				}
				else
					i++;
				if(j>=7)
					break;
			}
			temp[j]=0;
			if(k<2)
			{
				for(l=0;l<32;l++)
				{
					if(!strcmp(temp,reg_smb[l]))
						break;
				}
				if(l>=32)
					return false;
				change=l;
			}
			switch(k)
			{
			case 0:
				change=change<<16;
				temp[j]=',';temp[j+1]=0;
				break;
			case 1:
				change=change<<21;
				break;
			case 2://立即数
				change=chartoint(temp);//运用转换函数把字符变成整数
				change=change&65535;//保证正负号不便
				break;
			}
			*im=*im|change;
			j=0;i++;
		}
	}
	if(t>=13&&t<=14||t>=17&&t<=18)
	{//"muti","divi","beqz","bnez"
		for(k=0;k<2;k++)
		{//一个寄存器,一个数字
			while(str[i]!=','&&str[i]!='\0')
			{
				if(str[i]!=' '&&str[i]!='\t')
				{
					temp[j]=str[i]; i++;j++;
				}
				else
					i++;
				if(j>=7)
					break;
			}
			temp[j]=0;
			if(k<1)
			{//寄存器
				for(l=0;l<32;l++)
				{
					if(!strcmp(temp,reg_smb[l]))
						break;
				}
				if(l>=32)
					return false;
				change=l;
			}
			switch(k)
			{
			case 0:
				change=change<<21;
				break;
			case 1://数据
				change=chartoint(temp);
				change=change&65535;
				break;
			}
			*im=*im|change;
			j=0;i++;
		}
	}
	if(t>=15&&t<=16)
	{//	"lw","sw"
		for(k=0;k<3;k++)
		{//两个寄存器和一个offset
			while(str[i]!=','&&str[i]!='\0'&&str[i]!='('&&str[i]!=')')
			{
				if(str[i]!=' '&&str[i]!='\t')
				{
					temp[j]=str[i]; i++;j++;
				}
				else
					i++;
				if(j>=7)
					break;
			}

			temp[j]=0;
			if(k==0||k==2)
			{
				for(l=0;l<32;l++)
				{
					if(!strcmp(temp,reg_smb[l]))
						break;
				}
				if(l>=32)
					return false;
				change=l;
			}
			switch(k)
			{
			case 0:
				change=change<<16;
				break;
			case 1:
				change=chartoint(temp);
				change=change&65535;
				break;
			case 2:
				change=change<<21;
			}
			*im=*im|change;
			j=0;i++;
		}
	}
	if(t>=19&&t<=20)
	{//j 、jr指令
		while(str[i]!='\0')
		{
			if(str[i]!=' '&&str[i]!='\t')
			{
				temp[j]=str[i]; i++;j++;
			}
			else
				i++;
			if(j>=7)
				break;
		}
		temp[j]=0;

		switch(t)
		{
			case 19://直接地址,为正数
				change=chartoint(temp);
				break;
			case 20://寄存器
				for(l=0;l<32;l++)
				{
				if(!strcmp(temp,reg_smb[l]))
					break;
				}
				if(l>=32)
					return false;
				change=l;
				change=change<<21;
				break;
		}
//		*im=*im|change;
	}
	return true;
}

void CPipelineDoc::IF_STEP()
{
	if(data_stall)				//如果有data_stall                                 
	{
		data_stall--;			//一个周期data_stall完成
		states.normal[0]=0;		//将接口参数设为stall状态
		return;					//返回(不执行本步操作)
	}
	else
		states.normal[0]=1;		//没有将接口参数设为normal状态
	if_id.IR=IM[pc/4];	        //基本流水线操作
	states.pc=pc;	            //设置接口参数pc(表示当前指令在指令内存的位置)

	if(((FUNC(id_ex.IR)==17)&&id_ex.cond)||((FUNC(id_ex.IR)==18)&&!id_ex.cond)) //跳转成功
	{
		if_id.NPC=id_ex.ALUOutput;		//修改NPC值和PC值
		pc=id_ex.ALUOutput;
		if(branching==PREDICTED_UNTAKEN)//predicted_untaken
		{
			states.instruction[states.number]=states.pc/4;//将被cancel指令在IM中位置保存
			states.number++;			//将已被取进来的指令数++
			if_id.IR=0;					//取指错误,插入空指令,表明指令被cancel了
		}
		if((FUNC(id_ex.IR)==17)||(FUNC(id_ex.IR)==18))	//predicted_taken|flush
			if(branching==PREDICTED_TAKEN||branching==FLUSH)   		
				if_id.IR=0;		//取指错误,插入空指令,表明指令被cancel了
	}
	else
	{
		if_id.NPC=pc+4;		//保存pc值,跳转指令用来计算目的地址							
		pc=pc+4;	        //基本流水线操作									
	}
	if(if_id.IR)			//如果指令被正常取指,设置相应的接口值
	{	
		states.instruction[states.number]=states.pc/4;//将指令在IM中位置保存
		states.number++;	//将已被取进来的指令数++
	}
	if(FUNC(if_id.IR)==21)  //如果指令为trap,设置相应的接口值
	{	
		states.instruction[states.number]=states.pc/4;//将指令在IM中位置保存
		return;
	}
	
}

void CPipelineDoc::IDD_STEP()
{	
	if(data_stall)              //如果有data_stall
	{
		states.normal[1]=0;		//将接口参数设为stall状态
		return;					//返回(不执行本步操作)
	}
	else
		states.normal[1]=1;		//没有将接口参数设为normal状态
	id_ex.IR=if_id.IR;			//基本流水线操作
	if(!FUNC(id_ex.IR))			//当前续指令被cancel
	{
		states.normal[1]=2;		//将接口参数设为cancel状态
		return;					//返回(不执行本步操作)
	}
	else
		states.normal[1]=1;		//没有将接口参数设为normal状态	
	fetch_a();
	fetch_b();					
	id_ex.Imm=IMM(id_ex.IR);    //符号扩展!
	if(FUNC(id_ex.IR)==19)		//j
		pc=IMM(id_ex.IR);		//计算j的跳转地址
	if(FUNC(id_ex.IR)==20)		//计算jr的跳转地址
		pc=REG[RS(id_ex.IR)];
	id_ex.NPC=if_id.NPC;
	id_ex.ALUOutput=4*((id_ex.NPC-4)/4+(short)IMM(id_ex.IR));   //计算beqz和bnez的跳转地址
	if(id_ex.A)                 //beqz和bnez跳转条件的设置
		id_ex.cond=0;			
	else
		id_ex.cond=1;
}

void CPipelineDoc::EX_STEP()    //流水线第三步
{
	if(data_stall)				//如果有data_stall,
	{	
		states.normal[2]=0;     //将接口参数设为stall状态
		return;					//返回(不执行本步操作)
	}
	else
		states.normal[2]=1;		//没有将接口参数设为normal状态
	ex_mem.IR=id_ex.IR;			//基本流水线操作
	if(!FUNC(ex_mem.IR))        //当前续指令被cancel
	{	
		states.normal[2]=2;		//将接口参数设为cancel状态
		return;					//返回(不执行本步操作)
	}
	else
		states.normal[2]=1;	    //没有将接口参数设为normal状态
	switch(FUNC(ex_mem.IR))     //根据指令的func code执行操作
	{
	case 1:  //add
		ex_mem.ALUOutput=id_ex.A+id_ex.B;
		break;
	case 2:  //sub
		ex_mem.ALUOutput=id_ex.A-id_ex.B;
		break;
	case 3:  //and
		ex_mem.ALUOutput=id_ex.A&id_ex.B;
		break;
	case 4:	 //or
		ex_mem.ALUOutput=id_ex.A|id_ex.B;
		break;
	case 5:  //xor
		ex_mem.ALUOutput=id_ex.A^id_ex.B;
		break;
	case 6:  //mult ,不要求,没有测试
		REG[27]=id_ex.A*id_ex.B;
		break;
	case 7:  //div,不要求,没有测试
		REG[26]=id_ex.A/id_ex.B;
		REG[27]=id_ex.A%id_ex.B;
		break;
	case 8:  //addi
		ex_mem.ALUOutput=id_ex.A+id_ex.Imm;
		break;
	case 9:  //subi
		ex_mem.ALUOutput=id_ex.A-id_ex.Imm;
		break;
	case 10: //andi
		ex_mem.ALUOutput=id_ex.A&id_ex.Imm;
		break;
	case 11: //ori
		ex_mem.ALUOutput=id_ex.A|id_ex.Imm;
		break;
	case 12: //xori
		ex_mem.ALUOutput=id_ex.A^id_ex.Imm;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -