"); //-->
简单CPU模拟器的设计
一.实验目的:
了解CPU结构,了解掌握指令集,清楚了解指令执行过程,熟悉相关CPU设计技术,为研究和工作打下基础。
二.设计思路:
基本理论:
CPU的硬件执行过程是可以对应到软件过程的,即用语言模拟实现CPU的功能与结构,软件与硬件是等价的。
设计之前准备:
首先熟悉了CPU的指令集以及指令执行过程中相关部件的运行情况,分析指令流程图;了解硬件结构,如PC寄存器,寄存器堆,状态寄存器,存储器,然后设置相关对应变量。
程序思路:
1.CPU的一个执行周期由一个循环结构来实现,一个周期又分为取指,译码,执行,访存,写回。
2.在取指阶段,根据PC所示地址,从指令存储器取指令,送往取指阶段的IF_Inst变量,同时PC=PC+1; 之后,为了不让流水线中的后来指令覆盖前面的指令,指令依次传往ID_Inst,EX_Inst,MA_Inst,WB_Inst.
3.在译码阶段采用“按位与”的方法取操作数和操作码.
4.在执行阶段根据译码阶段取的操作数和操作码执行加,减,乘,除以及进位操作.
5.将执行过程中改变的寄存器或标志位写回,判断是否(半)进(借)位,是否溢出,结果是否为0.
6.访问存储器,存取数据到数据存储器,利用counter变量控制访问内存所用周期数.
7.由C语言库中文件输入/输出函数读入指令与数据分别到各自存储器(Harvard结构),输出标志位寄存器的值.
三.程序源代码
#include "stdio.h"
#include "stdlib.h"
///开始主函数
void main()
{short int InstrRAM[1000];///指令存储器
short int DataRAM[1000];///数据存储器
int nextpc=0;///定义各pc
int IF_pc=0;
int ID_pc=0;
int EX_pc=0;
int MA_pc=0;
int WB_pc=0;
int time=0;
short int regist[32]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};///定义r0~r31共32个寄存器
short int srregist[8]={0,0,0,0,0,0,0,0};///定义程序状态寄存器,分别表示C,Z,N,V,S,H,T,I
char sr[8]={'C','Z','N','V','S','H','T','I'};
short int re_resou_no,re_dest_no;///定义源操作数寄存器号和目的操作数寄存器号
int relativeadress; ///定义rjmp brim相对地址
short int data_pc=0;///定义数据寄存器指针pc
int mul_EX_data;
int true_add=0;
int true_sub=0;
int true_mul=0;
int true_rjmp=0;
int true_brmi=0;
int true_mov=0;
int true_ldi=0;
int true_ld=0;
int true_st=0;
int true_nop=0;///控制变量
int i,j=0;
short int resoudata,destindata;
short int IF_Inst,ID_Inst,EX_Inst,MA_Inst,WB_Inst;
int done=0;
int counter=0;
int n=0;
FILE *f;
///读取指令到存储器
f=fopen("instruction.data","rb");
if (f==NULL)
printf("wrong\n\n\n");
fread(InstrRAM,1,100,f);
fclose(f);
///读取数据到存储器
f=fopen("data.data","rb");
if (f==NULL)
printf("wrong\n\n\n");
fread(DataRAM,1,100,f);
fclose(f);
f=fopen("everytime.txt","w");
fclose(f);
f=fopen("DataRAM.txt","w");
fclose(f);
///周期循环开始
while(done==0)
{
time++;
//////IF stage
if(n%5==0)
{//if
IF_pc=nextpc;
nextpc++;
IF_Inst=InstrRAM[IF_pc];
n++;}//if IF stage end
//////ID stage ///true_add=true_sub=true_mul=true_rjmp=true_brmi=true_mov=true_ldi=true_ld=true_st=true_nop=0;
if(n%5==1){//if
ID_Inst=IF_Inst;
ID_pc=IF_pc;
if ((ID_Inst&0xffff)==0xffff)///判断是否取指到末尾
{done=1;}
else ///翻译指令代码开始v
{
///adddecode 0000 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if((ID_Inst&0xfc00)==0x0c00)
{
re_dest_no=ID_Inst&0x01f0;
re_dest_no>>=4;
re_resou_no=ID_Inst&0x000f;
i=ID_Inst&0x0200;
i>>=5;
re_resou_no=re_resou_no+i;
destindata=regist[re_dest_no];
resoudata=regist[re_resou_no];
true_add=1;
}
///subdecode 000110rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if((ID_Inst&0xfc00)==0x1800)
{re_dest_no=ID_Inst&0x01f0;
re_dest_no>>=4;
re_resou_no=ID_Inst&0x000f;
i=ID_Inst&0x0200;
i>>=5;
re_resou_no=re_resou_no+i;
destindata=regist[re_dest_no];
destindata=regist[re_dest_no];
resoudata=regist[re_resou_no];
true_sub=1;
}
///muldecode 1001 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if((ID_Inst&0xfc00)==0x9c00)
{re_dest_no=ID_Inst&0x01f0;
re_dest_no>>=4;
re_resou_no=ID_Inst&0x000f;
i=ID_Inst&0x0200;
i>>=5;
re_resou_no=re_resou_no+i;
destindata=regist[re_dest_no];
resoudata=regist[re_resou_no];
true_mul=1;
}
///rjmpdecode 1100 kkkk kkkk kkkk relativeadress
if((ID_Inst&0xf000)==0xc000)
{relativeadress=ID_Inst&0x0fff;
ID_pc=ID_pc+relativeadress+1;
true_rjmp=1;
}
///brmidecode 1111 00kk kkkk k010 relativeadress
if((ID_Inst&0xfc07)==0xf002)
{relativeadress=ID_Inst&0x03f8;
relativeadress>>=3;
ID_pc=ID_pc+relativeadress+1;
true_brmi=1;
}
///movdecode 0010 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if((ID_Inst&0xfc00)==0x2c00)
{re_dest_no=ID_Inst&0x01f0;
re_dest_no>>=4;
re_resou_no=ID_Inst&0x000f;
i=ID_Inst&0x0200;
i>>=5;
re_resou_no+=i;
resoudata=regist[re_resou_no];
true_mov=1;
}
//ldidecode 1110 kkkk dddd kkkk re_resou_no,re_dest_no resoudata,destindata
if((ID_Inst&0xf000)==0xe000)
{re_dest_no=ID_Inst&0x00f0;
re_dest_no>>=4;
if(re_dest_no<16)
re_dest_no+=16;
resoudata=ID_Inst&0x0f00;
resoudata>>=4;
destindata=ID_Inst&0x000f;
resoudata+=destindata;
if(resoudata>0x00ff)
{printf("The input number is out of capacity!!please input another resourcedata!!");
break;}
true_ldi=1;
}
//lddecode 1001 000d dddd 1100 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if((ID_Inst&0xfe0f)==0x900c)
{re_dest_no=ID_Inst&0x01f0;
re_dest_no>>=4;
data_pc=regist[27]+regist[26];
resoudata=DataRAM[data_pc];
true_ld=1;
}
//stdecode 1001 001r rrrr 1100 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if((ID_Inst&0xfe0f)==0x920c)
{re_resou_no=ID_Inst&0x01f0;
re_resou_no>>=4;
data_pc=regist[27]+regist[26];
true_st=1;
}
//nopdecode 0000 0000 0000 0000 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if((ID_Inst&0xffff)==0x0000)
{for(i=0;i<20000;i++);
true_nop=1;}
n++;}
}
//////EX stage true_add=true_sub=true_mul=true_rjmp=true_brmi=true_mov=true_ldi=true_ld=true_st=true_nop=0;
if(n%5==2)
{
EX_Inst=ID_Inst;
EX_pc=ID_pc;
///add EX 0000 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if(true_add==1){
regist[re_dest_no]=resoudata+destindata;
if(regist[re_dest_no]>0x00ff)
{printf("The sub is out of capacity!!please input another resourcedata!!");
break;}
}
///sub EX ///subdecode 000110rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if(true_sub==1){
regist[re_dest_no]=destindata-resoudata;
true_sub=1;}
///mul EX ///muldecode 1001 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata mul_EX_data; r1:r0;
if(true_mul==1){
mul_EX_data=resoudata*destindata;
regist[0]=mul_EX_data&0x0000ffff;
mul_EX_data=mul_EX_data&0xffff0000;
regist[1]=mul_EX_data>>16;
}
///rjmp EX ///rjmpdecode 1100 kkkk kkkk kkkk kkkk relativeadress
if(true_rjmp==1){
IF_pc=ID_pc;
n=0;}
///brmi EX ///brmidecode 1111 00kk kkkk k010 relativeadress short int srregist[8];///定义程序状态寄存器,分别表示C,Z,N,V,S,H,T,I
if(true_brmi==1){
if(srregist[2]==1)
{IF_pc=ID_pc;
n=0;
}
}
///mov EX ///movdecode 0010 11rd dddd rrrr re_resou_no,re_dest_no resoudata,destindata
if(true_mov==1){
regist[re_dest_no]=resoudata;}
///ldi EX //ldidecode 1110 kkkk dddd kkkk re_resou_no,re_dest_no resoudata,destindata
if(true_ldi==1){
regist[re_dest_no]=resoudata;}
///nop EX //nopdecode 0000 0000 0000 0000 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if(true_nop==1){
for(i=0;i<20000;i++);}
n++;}//////EX stage
//////MA stage
if(n%5==3)
{MA_Inst=EX_Inst;
MA_pc=EX_pc;
while(counter<5)
{counter++;
}
if(counter==5)////
{///ld EX //lddecode 1001 000d dddd 1100 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if(true_ld==1){
regist[re_dest_no]=resoudata;}
///st EX //stdecode 1001 001r rrrr 1100 re_resou_no,re_dest_no resoudata,destindata DataRAM data_pc regist[32];
if(true_st==1){
DataRAM[data_pc]=regist[re_resou_no];
}
}///if
counter=0;
n++;}//////MA stage end
//////WB stage reset the srregist[8]中各位的标志值
if(n%5==4) //////short int srregist[8];///定义程序状态寄存器,分别表示C,Z,N,V,S,H,T,I
{ ///sub effect srregistz : c n v h s z: 0标志位 c:无符号溢出 n:负数标志 v:有符号溢出 h:半进位标志 s:n^v;
WB_Inst=MA_Inst;
WB_pc=MA_pc;
if(true_add==1){
regist[re_dest_no]=resoudata+destindata;
if(regist[re_dest_no]==0) srregist[1]=1;
if(regist[re_dest_no]<0) srregist[2]=1;
if((resoudata>=0)&&(destindata>=0)&&(regist[re_dest_no]<0)) srregist[3]=1;
if((resoudata<=0)&&(destindata<=0)&&(regist[re_dest_no]>0)) srregist[3]=1;
if(((resoudata&0x00ff)+(destindata&0x00ff))>=0x0100) srregist[5]=1;
srregist[4]=srregist[2]^srregist[3];
}
///sub effect srregistz : c n v h s
if(true_sub==1){
regist[re_dest_no]=destindata-resoudata;
if(regist[re_dest_no]==0) srregist[1]=1;
if(regist[re_dest_no]<0) srregist[2]=1;
if((resoudata<=0)&&(destindata>=0)&&(regist[re_dest_no]<0)) srregist[3]=1;
if((resoudata>=0)&&(destindata<=0)&&(regist[re_dest_no]>0)) srregist[3]=1;
if((destindata&0x00ff)<(resoudata&0x00ff)) srregist[5]=1;
srregist[4]=srregist[2]^srregist[3];}
///mul effect srregist :z c
if(true_mul==1){
if(mul_EX_data==0) srregist[2]=1;
if(mul_EX_data>=0x0100) srregist[0]=1;}
n++;}/////WB stage end
///输出部分的程序代码
for(j=0;j<=7;j++)
printf("sr%d:%d\n\n",j, srregist[j]);
for(j=0;j<32;j++)
printf("r%d:%hx\n\n",j, regist[j]);
true_add=0;
true_sub=0;
true_mul=0;
true_rjmp=0;
true_brmi=0;
true_mov=0;
true_ldi=0;
true_ld=0;
true_st=0;
true_nop=0;
f=fopen("everytime.txt","a");
fprintf(f,"第%d周期:\n\n",time);
for(j=0;j<=7;j++)
{fprintf(f,"%c:%d ",sr[j],srregist[j]);}
fputs("\n\n",f);
for(j=0;j<=31;j++)
{fprintf(f,"r%d:%hx ",j,regist[j]);
if(j%15==0) fputs("\n\n",f);}
fputs("\n\n",f);
fclose(f);
///fwrite(vol(array),sizeof(float),Size,fp);*********binary
///fprintf(FILE *f,格式,参数列表);
///fputc(c,FILE *f);
}///while end
f=fopen("DataRAM.txt","a");
for(j=0;j<=1000;j++)
{fprintf(f,"%hx ",DataRAM[j]);
if((DataRAM[j]&0xffff)==0xffff)
break;
}
fclose(f);
}///main 括号
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。