在做计算机体系结构的时候,模拟器是一个重要且又有效的工具。其中gem5集成了gem和m5的优点,使用起来比较简单和方便。其中包括了se模式和fs模式,se模式是在gem5运行我们已经编译好的程序,可以获取cache,cpu状态等数据,fs模式下可以模拟操作系统,我们可以将我们自己修改的linux内核加载到哥们上运行。下面介绍了使用gem5的se模式,运行编译好的ARM可执行文件。获取访存的trace,然后我们可以通过这些trace模拟cache,并以此获取cache命中率等数据信息。
首先使用gem5运行已经编译好的可执行文件,以hello为例
build/ARM/gem5.opt configs/example/se.py -c hello
build/ARM/gem5.opt --outdir=memaccess --debug-flags=MemoryAccess --debug-file=memoryaccess.out configs/example/se.py -c hello
此处为MemoryAccess的trace,我们还可以获得 MMC 和 DRAM的trace
Memoryaccess.out :(此文件相对较大,打开比较慢)
分成两部分:
第一部分:0---------------------------------0,tick 不增。
0 Tick:
此处显示的内容是把 hello 二进制程序“加载”到 gem5 的内存当中。
第二部分: 0--500--1000---------------------------end
0-500-1000,以 interval=500cycles 递增。此时就是实际程序逐条指令执行的过程。其中包括的信息和容易可以读懂。
在获取了该可执行文件的trace之后,也就知道了程序运行过程中具体的执行顺序,同时也知道了每一步具体执行的内存内容,包括IFetche读取指令,Write写数据,Read读数据等。
其中也包括了具体操作的物理地址。
下面就是cache模拟器的编写,我们使用4路组相连,blocksize默认大小为32Bytes,共4个组,下面是具体代码
#include<iostream>
#include<cstdlib>
#include<string.h>
#include<string>
#include<math.h>
#include<fstream>
using namespace std;
typedef struct Cache
{
int index;
int time;
int dirty;
}cache_t;
int sets;
int a;
int blockSize;
string l;
cache_t **i_cache,**d_cache;
string fileName;
int i_num,wd_num,d_num,rd_num,i_hit,wd_hit,rd_hit;
int stringToInt(string a)
{
int res = 0,now = 1;
for(int i=a.size()-1;i>=0;i--)
{
if(a[i]>='a')
res += (10+a[i]-'a')*now;
else
res += (a[i]-'0')*now;
now *= 16;
}
return res;
}
void simu_i_cache(int sets1,int a1,int blockSize1,string l1,string fileName1)
{
sets = sets1;
a = a1;
blockSize = blockSize1;
l = l1;
fileName = fileName1;
i_cache = new cache_t*[sets];
d_cache = new cache_t*[sets];
for(int i=0;i<sets;i++)
{
i_cache[i] = new cache_t[a];
memset(i_cache[i],-1,a*sizeof(cache_t));
d_cache[i] = new cache_t[a];
memset(d_cache[i],-1,a*sizeof(cache_t));
}
}
int findSet(int addr)
{
int res = addr>>(int)(log(blockSize)/log(2));
res %= sets;
return res;
}
int findIndex(int addr)
{
int res = addr>>(int)(log(blockSize)/log(2));
res = res>>(int)(log(sets)/log(2));
return res;
}
bool visitICache(int addr)
{
int mySet = findSet(addr);
int myIndex = findIndex(addr);
for(int i=0;i<a;i++)
{
if(i_cache[mySet][i].index == myIndex)
{
return true;
}
}
int maxTime=-1,insertIndex=-1,minTime = 1000000000;;
for(int i=0;i<a;i++)
{
if(minTime>i_cache[mySet][i].time)
{
minTime = i_cache[mySet][i].time;
insertIndex = i;
}
if(maxTime<i_cache[mySet][i].time)
maxTime = i_cache[mySet][i].time;
}
i_cache[mySet][insertIndex].index = myIndex;
i_cache[mySet][insertIndex].time = maxTime+1;
return false;
}
bool visitDCache(int addr)
{
int mySet = findSet(addr);
int myIndex = findIndex(addr);
for(int i=0;i<a;i++)
{
if(d_cache[mySet][i].index == myIndex)
{
return true;
}
}
int maxTime=-1,insertIndex=-1,minTime = 1000000000;;
for(int i=0;i<a;i++)
{
if(minTime>d_cache[mySet][i].time)
{
minTime = d_cache[mySet][i].time;
insertIndex = i;
}
if(maxTime<d_cache[mySet][i].time)
maxTime = d_cache[mySet][i].time;
}
d_cache[mySet][insertIndex].index = myIndex;
d_cache[mySet][insertIndex].time = maxTime+1;
return false;
}
void readFile()
{
ifstream fin(fileName.c_str());
int type;
string number;
while(fin >> type >> number)
{
int addr = stringToInt(number);
switch(type)
{
case 0:
i_num++;
if(visitICache(addr))
i_hit++;
break;
case 1:
d_num++;
rd_num++;
if(visitDCache(addr))
rd_hit++;
break;
case 2:
d_num++;
wd_num++;
if(visitDCache(addr))
wd_hit++;
break;
default:
cout << "error"<< endl;
}
}
cout << "instruction hit ratio "<<(double)i_hit/i_num << endl;
cout << "write data hit ratio "<<(double)wd_hit/wd_num << endl;
cout << "read data hit ratio "<<(double)rd_hit/rd_num << endl;
}
int main()
{
simu_i_cache(4,8,32,"LRU","output.txt");
readFile();
}trace色输入文件是output.txt.即通过gem5模拟出来的trace。不过考虑到trace比较大,对trace做了预处理
output.txt实例
0 0xa94 1 0xa94 0 0xa98 0 0xa98 0 0xa9c 0 0xa9c 0 0xaa0 0 0xaa0 1 0x5edd4 0 0xaa4 0 0xaa4 0 0xaa8 0 0xaa8 0 0xaac 0 0xaac 2 0x5edd4 0 0xab0 0 0xab4
原文地址:http://blog.csdn.net/gaoxiang__/article/details/41494189