📄 pipelinedoc.cpp
字号:
// 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 + -