专栏中心

EEPW首页 > 专栏 > 简单CPU模拟器的设计与实现

简单CPU模拟器的设计与实现

发布人:aiwangxin 时间:2007-12-03 来源:工程师 发布文章

 

简单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 括号

专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

贸泽EIT系列新一期,探索AI如何重塑日常科技与用户体验

智能计算 2026-04-20

锂电池的充电特点和 TI 最新充电管理技术

视频 2010-03-18

海光信息:以芯片内生安全与万卡算力底座,重塑 AI 时代算力安全新格局

为中国市场度身定制的RF 收发器 – CC1100E

视频 2010-03-18

尼得科车载既存事业本部将携下一代出行技术亮相 2026北京国际汽车展览会

时钟解决方案 CDCM6100x

视频 2010-03-18

模拟器件 - 时 钟: EMI 降低

视频 2010-03-18

传联电代工2D NAND有「三大关卡」 缺人、缺技术、缺设备

网络与存储 2026-04-20

Hubble 与 InPlay 推出 1 美元级全球资产追踪方案 无需 RFID

AMD 发布锐龙 AI 400/PRO 400 系列 完善桌面 + 移动 AI PC 布局

消费电子 2026-04-20

可编程,低成本音频 DSP TAS3K系列

视频 2010-03-18

零跑汽车携手QNX打造科技豪华旗舰SUV D19,正式投产计划于2026年4月启动

算力爆发遇上电源革新,大联大世平集团携手晶丰明源线上研讨会解锁应用落地

台积电1纳米以下程震撼曝光 揭秘第一家签约大户

EDA/PCB 2026-04-20

Vishay的新款薄形IHLP电感为商业应用节省空间并提高效率

元件/连接器 2026-04-20
更多 培训课堂
更多 焦点
更多 视频

技术专区