实验二存贮层次模拟器.docx
《实验二存贮层次模拟器.docx》由会员分享,可在线阅读,更多相关《实验二存贮层次模拟器.docx(10页珍藏版)》请在冰豆网上搜索。
实验二存贮层次模拟器
实验二:
存贮层次模拟器
计算机系统结构课程
实验指导书
2011——2012学年
第1学期
姓名:
邱宗玉
学号:
201017617
专业:
计算机科学与技术
班级:
176班
指导教师:
孙全红
教研室:
计算机系统结构教研室
2011年10月18日
实验二:
存贮层次模拟器
学时:
2学时
设计):
设计实验类型:
(综合/
一、实验目的与要求
使学生清楚认识cache-主存层次结构,熟练掌握常用的几种存储地址映象与变换方法,以及FIFO、LRU等替换算法的工作全过程。
要求用程序实现任意地址流在存储层次上的命中情况,实验结束后提交源程序和实验说明书。
二、实验内容
在模拟器上实现在任意地址流下求出在Cache—主存存贮层次上的命中率。
三、实验步骤
1(Cache—主存:
映像方式可以选择全相联、直接映象、组相联方式;替换算法一般使用LRU
算法。
2(要求主存容量、Cache大小、块大小以及组数等可以输入修改。
3(求出命中率;显示替换的全过程;任选一种高级语言来做。
4(要有简洁、易于操作的界面。
四、实验仪器设备
计算机(装有常用编程环境,如C、VC++等)
五、考核方式
1(平时考勤占10%。
(两次上机时间,一次不到扣5分)
2(最终源程序运行情况、提交的源程序和实验说明书占90%。
六、实验源代码及其运行结果
源代码:
#include
#include//组映射地址流映射的组查找返回组号
intGroupfind(inttemp,intc1,intg){
typedefstructCache{//Cacheinti;
intgm;//组号temp=temp%c1;//主存页地址在
intgbm;//组内块号cache中偏移量
intbd;//块内地址i=temp/g;//求得主存页所在组号
};returni;
Cachec[50];
}
intcount[50];//计数器//初始化Cache
intd[50];//地址流voidinitC(intg,intc1){
intj=0;intn=0;inti=0;if(c[j].bd>=0)
for(;ic[i].bd=-1;//块内地址初始为if(j==i)count[j]=0;
-1}
c[i].gbm=j;//组内块号初始化}
0~p/g-1voidprint0(inttemp,intc1){
c[i].gm=n;//组号初始化0~g-1for(intk=0;k<=c1+1;k++)
count[i]=0;printf("|----");
if(j==c1/g-1){printf("|\n");
j=0;printf("|%4d|",temp);
if(n==g-1)n=0;for(k=0;kelsen++;",c[k].bd);}
}elsej++;printf("命中|\n");}}
}voidprint2(inttemp,intc1){
for(intk=0;k<=c1+1;k++)
printf("|----");//查找组相连中计数器值最大的数组下printf("|\n");
标,全相连时g=1printf("|%4d|",temp);intFind(intj,intg,intc1){for(k=0;k",c[k].bd);}intmax,k=j;
printf("调入|max=count[j];\n");
for(intl=j;lif(count[l]>max)voidprint3(inttemp,intc1){
for(intk=0;k<=c1+1;k++){max=count[l];k=l;}
printf("|----");}
returnk;printf("|\n");
}printf("|%4d|",temp);
for(k=0;k标,没空位返回-1printf("替换|\n");intisfull(inti,intc1,intg){//数}
组号voidprint4(intc1){
intflag=-1;for(intk=0;k<=c1+1;k++)
for(intl=i;l
if(c[l].bd==-1)printf("|\n");
{flag=l;break;}printf("|地址|");
}for(inth=0;hreturnflag;printf("块%2d|",h);}}
printf("过程
//LRU算法计数器计数|");printf("\n");}voidaddcount(inti,intc1){
for(intj=0;jvoidprint1(inttemp,intc1,intg,int}
p){
其与fifo算法for(intj=0;jif(temp==-1)break;差不多,只需在命中时将命中页计数器值清零
int//全相连LRU1,Cache组值g=1flag=0;if(temp>=p){printf("%d块号越界~voidLRU1(intc1,intg,intp,inty){
\n",temp);}inttemp,k=0;floatsum=0,num=0;
intprint4(c1);
i1=Groupfind(temp,c1,g);//计算组号for(inti=0;i//printf("-%d",i1);intf=0;
if(c[j].gm==i1){//查找到输if(d[i]>=p){printf("%d块号入块组号与Cache组号相同时越界~\n",d[i]);i++;}
if(temp>=p){printf("%dif(d[i]==-1)break;//地址流块号越界~\n",temp);}结束跳出for1
for(intj=0;jflag=isfull(j,c1,g);//Cache是否有空if(d[i]==c[j].bd)//命中位{f=1;addcount(j,c1);
if(flag>=0){//if3块内地print0(d[i],c1);址为空i++;num++;sum++;
c[flag].bd=temp;//break;
将该块调进该空位上}
addcount(flag,c1);//计数器计数}//for2
print2(temp,c1);if(f==0){//if1不命中:
调进,
}//if3替换
else{//Cache无空位intf2=0;
for(int
if(temp>=p){printf("%d块号越界~j=0;jintif(d[i]==-1)break;if(d[i]>=p){printk=Find(j,g,c1);//找最近未使用的块的数组f("%d块号越界~\n",d[i]);i++;}下标
intif(c[j].bd==-1){c[j].bd=d[i];q=c[k].bd;if(temp==-1)break;addcount(j,c1);//计
c[k].bd=temp;//替换数器计数
addcount(k,c1);//计f2=1;
数器计数
print3(temp,c1);print2(d[i],c1);i++;sum++;
break;}//调进
}}//for3
break;
}if(f2==0){if(d[i]>=p){printf("%d块
}号越界~
\n",d[i]);i++;}if(d[i]==-1)break;
intq=0;//查看整j=0;jint
k=Find(q,g,c1);if(c[j].bd==-1){c[j].bd=d[i];
q=c[k].bd;f2=1;
c[k].bd=d[i];//替换
print3(d[i],c1);i++print2(d[i],c1);i++;sum++;
;sum++;break;}//调进
}}//for3
if(f2==0){
}//if1
}//for1if(d[i]==-1)break;if(d[i]>=p){print
for(k=0;k<=c1+1;k++)f("%d块号越界~\n",d[i]);i++;}
if(d[i]>=p){printf("|----");
printf("|\n");printf("\n命中率
为:
%f\n",num/sum);
}if(d[i]==-1)break;
//直接LRU2其中不需要组值、计数器来i++;}
参与运算,是替换唯一映像intk=d[i]/c1;//
voidLRU2(intc1,intp,inty){替换唯一映像数组下标
inttemp,k=0;floatsum=0,num=0;c[k].bd=d[i];//替换
print4(c1);print3(d[i],c1);i++
for(inti=0;iintf=0;}
if(d[i]>=p){printf("%d块号
越界~\n",d[i]);i++;}}//if1
if(d[i]==-1)break;//地址流}//for1
结束跳出for1for(k=0;k<=c1+1;k++)
for(intj=0;jif(d[i]==c[j].bd)//命中printf("|\n");printf("\n命中
{f=1;率为:
%f\n",num/sum);
}print0(d[i],c1);
i++;num++;sum++;//组相连LRU3
break;voidLRU3(intc1,intg,intp,inty){
}inttemp,k=0;floatsum=0,num=0;
print4(c1);
}//for2for(inti=0;iif(f==0){//if1不命中:
调进,intf=0;
替换if(d[i]>=p){printf("%d块号
int越界~\n",d[i]);i++;}f2=0;if(d[i]==-1)break;if(d[i]==-1)break;//地址流
if(d[i]>=p){printf("%d结束跳出for1
块号越界~\n",d[i]);i++;}for(intj=0;jfor(int
if(d[i]==c[j].bd)//命中scanf("%d",&group);
{f=1;addcount(j,c1);intp=m_num/p_num;//内存块总个数
intc1=c_num/p_num;print0(d[i],c1);
i++;num++;sum++;printf("请输入块号流以-1结束(0~%d):
break;",p-1);
}inti=0;
while(i>=0){
}//for2scanf("%d",&q);
if(f==0){//if1不命中:
调进,d[i]=q;
替换if(q==-1){d[i]=q;break;}
temp=d[i];i++;
}
inty=i;//记录输入的地址流总个数print1(temp,c1,g,p);i++;sum++;
//initM(group,p);//初始化主存
}//if1printf("使用全相连(按1),使用直接映
}//for1射(按2),使用组相连(按3):
");
for(k=0;k<=c1+1;k++)scanf("%d",&q);
printf("|----");if(q==1){
printf("|\n");printf("\n命中率group=1;
为:
%f\n",num/sum);initC(group,c1);}LRU1(c1,group,p,y);
}
if(q==2){
voidmain(){initC(group,c1);intm_num,c_num,group,p_num,q;LRU2(c1,p,y);printf("请输入Cache大小:
");}
scanf("%d",&c_num);if(q==3){
printf("请输入块大小:
");
scanf("%d",&p_num);initC(group,c1);printf("请输入内存大小(Cache的整数LRU3(c1,group,p,y);
倍):
");}
scanf("%d",&m_num);}
printf("Cache分组数为:
");
运行界面如下:
七、实验心得
通过本次实验对主存-cache之间的两级映射有了进一步的认识,对它们之间的三种映射方式:
全相联、组相联及直接映射方式,有了深入的理解,体会到了对不同的映射方式采用lru替换算法内存的使用情况,会计算采用不同算法的命中率。