基于gem5模拟trace的cache模拟器的实现

在做计算机体系结构的时候,模拟器是一个重要且又有效的工具。其中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

为了获取运行的trace,需要添加一些运行的参数

     build/ARM/gem5.opt --outdir=memaccess --debug-flags=MemoryAccess --debug-file=memoryaccess.out configs/example/se.py -c hello

命令参数解析:

--outdir=memaccess 指明生成的 memory-access trace 文件所存放的文件夹。

--debug-flags=MemoryAccess 指 明 要 获 得 什 么 trace, 我 们 此 处 指 定 要 获 得MemoryAccess 的 trace(注意大小写,否则 gem5 会提示不识别这个 flag)

--debug-file=memoryaccess.out 指 明 trace 文 件 的 名 称 。 此 处 为memoryaccess.out

此处为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

其中0代表代码读,1表示数据读,2表示数据写,后面是物理地址的16进制表示

时间: 2024-10-09 14:32:42

基于gem5模拟trace的cache模拟器的实现的相关文章

Java Cache模拟器(图形界面)

一.设计思路 (说明,本文来自于<计算机体系结构--量化研究方法>的课程实验) 1.综述 我沿用了助教给的Java模版,完成了基本要求:设置Cache总大小和块大小.设置映射机制.设置替换策略.设置写策略,也完成了所有较高要求:能把Cache分为数据Cache和指令Cache.能设置预取策略.能设置写不命中调块策略并且有UI界面. 在设计上我充分利用了面向对象的设计思路,把各个逻辑部件都封装成内部类,模拟各种行为的方法也封装在内部类的方法中.比较重要的内部类有Instruction类(模拟数据

JAVA学习第六十课 — UDP协议 &amp;基于多线程模拟简单的QQ聊天程序

UDP传输 UDP有发送端和接受端,有两大类,DatagramSocket.DatagramPacket 建立发送端和接收端 建立数据包 调用Socket的接收发送方法 关闭Socket 注意:发送端和接收端是两个独立的运行程序 UDP发送端演示 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号. public static voi

[Tizen开发]基于Tizen平台的终端开发模拟器1 - Web

1.  官方 模拟器 Tutorials https://01.org/web-simulator/ 2. 最新版本发布于 2013.05 I am honored to introduce the Web Simulator for its public release on 01.org. The Web Simulator is a lightweight mobile application development and testing tool for web application

基于PHP的一种Cache回调与自动触发技术

背景 在PHP中使用Memcache或者Redis时,我们一般都会对Memcache和Redis封装一下,单独完成写一个Cache类,作为Memcache活着Redis的代理,且一般为单例模式.在业务代码中,使用Cache类时,操作的基本的示例代码如下 // cache 的 key $key = 'this is key'; $expire = 60;// 超时时间 // cache 的实例 $cache = Wk_Cache::instance(); $data = $cache->fetch

基于nodejs模拟浏览器post请求爬取json数据

今天想爬取某网站的后台传来的数据,中间遇到了很多阻碍,花了2个小时才请求到数据,所以我在此总结了一些经验. 首先,放上我所爬取的请求地址http://api.chuchujie.com/api/?v=1.0: 下面我们开始爬取数据. 一.写一个基于nodejs的爬虫 1.引入所需模块 这里需要引入http模块(nodejs用来向浏览器发送http请求的模块)和querystring模块(把前台传过来的对象形式的参数转化成字符串形式): var http = require("http"

基于puppeteer模拟登录抓取页面

关于热图 在网站分析行业中,网站热图能够很好的反应用户在网站的操作行为,具体分析用户的喜好,对网站进行针对性的优化,一个热图的例子(来源于ptengine) 上图中能很清晰的看到用户关注点在那,我们不关注产品中热图的功能如何,本篇文章就热图的实现做一下简单的分析和总结. 热图主流的实现方式 一般实现热图显示需要经过如下阶段: 获取网站页面 获取经过处理后的用户数据 绘制热图 本篇主要聚焦于阶段1来详细的介绍一下主流的在热图中获取网站页面的实现方式 使用iframe直接嵌入用户网站 抓取用户页面保

基于cookies模拟登录

cookies是什么 ? cookies是服务器放在用户机器上的一小块信息. cookies用来保存登录信息,这样用户就不用每次从同一台机器访问页面都要再次输入登录信息 cookie的成分 名称.值(必需):域(网站不能访问其他域生成的cookie).路径(将cookie的访问权限控制在服务器中的特定目录).失效日期(规定cookie何时应该删除,默认下关闭浏览器时就会删除cookie,也可以自己设置删除时间).安全标志(true还是false) 如何获取cookies? 通过burpsuite

windows下,python基于SocketServer模拟实现SSH(多线程版)

这两天,学习了python的套接字编程(linux版),我发现好多的资料都是linux的,然而python这个利器显然是跨平台的,所以,我根据linux版的资料来写一点windows的东西,希望对大家有点帮助,另外:本人小菜菜一枚,要是哪里有问题,欢迎指正,谢谢合作. 首先分析一下大概过程: 一.建立连接后,(多个或者一个)客户端将命令行发给服务器: 二.服务器收到命令行后,执行命令: 三.服务器将执行的结果反馈给客户端: 四.多次执行上述过程: 那么,python是怎么解决这几个问题的呢? 一

gem5简介

gem5模拟器提供了四个不同的CPU模型,两个不同的系统模型以及两个不同的内存系统模型,并且支持多种指令集(ARM.ALPHA.MIPS.Power.SPARC和x86),其中可以再ARM.ALPHA和x86三种架构上运行Linux.gem5的许可证是基于BSD的,这就为工业界和学术界的合作搭建了一个好的桥梁.虽然开发一个Full-system的模拟器是很复杂的,但gem5正在借助开源的强大合作力(如mailing lists,wiki,web-based patch reviews,a pub