如何编程模拟计算机中的高速缓存

1. 实验要求
2. 编程
2.1 读取文件
2.2 高速缓存定义结构体
2.3 初始化cache
2.4 解析输入的指令
2.5 lru策略
2.6 更新高速缓存cache
2.7 完整代码
3. 测试结果
1. 实验要求
  1.编程模拟cahce的命中,不命中,替换等行为。
  2.编写的程序必须对任意s,e和b正确工作。
  3.本实验不涉及真实的数据读写,不需要考虑block的细节,每行只有一个block。
  4.编写的程序要能读取指定文件内的指令,根据不同的指令完成不同的动作,下面为指令内容示例。
i 0400d7d4,8      #m 0421c7f0,4      # 修改access cache, 即读写access cache两次,0421c7f0:修改的地址,8:修改的长度l 04f6b868,8      # 读access cache,04f6b868:读取的地址,8:读取长度s 7ff0005c8,8     # 写access cache,0421c7f0:写的地址,8:写的长度  
2. 编程
  考虑模拟一个cache的行为需要用到哪些变量?
计算机中的高速缓存模型
  cache有组数s、一组包含的行数e,存储块的字节大小b,cache的容量c=s×e×b。
  地址的构成:标识位t、组索引s、块偏移b(前面说了,不需要管块偏移)。
  下面我们开始编写代码。
2.1 读取文件
  getopt()该函数能够帮助程序分析c语言命令行程序输入的参数。
int getopt(int argc,char * const argv[ ],const char * optstring);  
  重点说下getopt()函数。前两个形参是main函数传入的参数,即我们输入的命令行,第三个形参是 optstring“选项字符串”,即标识哪些字母表示了操作。
  如acd::e,字母后带一个冒号(例中的a、b)表明这个操作带参数,字母后的内容需要读取,存放到它内部变量 extern char * optarg中。
  字母不带冒号(例中的c、e)表明该操作不带参数,后面输入的内容仍看作操作符处理。字母后带两个冒号(例中的d)表明该操作后参数是可选的,但是要求如果带参数时参数与操作符不能有空格,如-d123是对的,而-d 123会报错。当读取了全部的输入的命令后 getopt()返回-1。
while((opt = getopt(argc,argv,sb)) !=-1){           //解析命令行参数  switch(opt){  case 's':   s=atoi(optarg);   break;  case 'e':   e=atoi(optarg);   break;  case 'b':   b=atoi(optarg);   break;  case 't':   filepath = optarg;   break;  } }  
   fscanf函数,该函数能够帮助用户处理文本文件中输入的格式化数据。
int fscanf(file *stream, char *format[,argument...]);  
  stream-这是指向 file 对象的指针,该 file 对象标识了流。
  format-这是 c 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符和format 说明符。
2.2 高速缓存定义结构体
  实验要求中说明了,不需要处理b,只需认为每行中有一个block。因此cache_line结构体中包括有效位,标记位,时间戳三个变量就够了。stamp记录的是block 的使用时间,每被使用一次,block++。因此,stamp越大表明该block越是最近被使用。具体代码如下。
typedef struct{ int valid_bits; unsigned  tag; int stamp;}cache_line;  
2.3 初始化cache
  定义一个cache[s] [e]大小的二维数组。这样cache就模拟好了。
void init(){ cache = (cache_line**)malloc(sizeof(cache_line*)*s);             //malloc开辟空间 for(int i=0;i   首先需要对读取的地进有分析,低b位表示 block偏移,本实验中不需要计算block偏移。中间s位是 set index位,表示对那个行操作。其余t位是tag位。用于标明对应的line是否有效。我们需要对得到的地址进行如下操作,解析出t和s。
unsigned s_address =(address>>b) & ((0xffffffff)>>(32-s));                //索引位 unsigned t_address = address>>(s+b);                                     //标记位  
2.5 lru策略
  替换策略使用的是lru的缓存替换策略。如果该set存满了,我每次要找到stamp最小的替换。为了方便,我把stamp初始化为0,之后每个操作+1. 当stamp= 0的时候就代表不valid。
void time(){ for(int i=0;i 2.6 更新高速缓存cache
  cache的容量有限,当满的时候需要替换行,先遍历当前组,判断它满了没有,如何判断是否满,可以遍历所有的行,只要有一个有效位为0,(有效位的作用是说明该行是否存储了数据,通俗的理解就是是否为空)则该组未满。
for(int i=0;i 2.7 完整代码
/* * @description: 编程模拟cache * @version: v1.0 * @autor: 嵌入式与linux那些事 * @date: 2021-1-1 2012 * @lasteditors: 嵌入式与linux那些事 * @lastedittime: 2021-1-1 2258 */#include cachelab.h#include #include #include #include #include typedef struct{ int valid_bits; unsigned  tag; int stamp;}cache_line;char* filepath = null;int s,e,b,s;                          // s 表示组 ,e表示行,每一行有 2^b位 ,s = 2^s 组int hit=0,miss=0,eviction=0;cache_line** cache = null;void init(){ cache = (cache_line**)malloc(sizeof(cache_line*)*s);             //malloc开辟空间 for(int i=0;i>(32-s));           //从地址分解出索引位 unsigned t_address = address>>(s+b);                                 //从地址分解出标记位 //判断tag为是否相等,是否命中    for(int i=0;itag ==t_address){   cache[s_address][i].stamp = 0;       //被使用了   hit++;   return;  } }    //更新高速缓存cache for(int i=0;i 3. 测试结果
hnu的自动评分系统会测试我们编写的代码是否可以通过所有的测试用例,和reference simulator的对比表明,结果完全相同。测试通过!
image-20201231160527635


电池维护保养小常识
覆铜板 (CCL) 材料的拉伸测试及其测试流程介绍
IntelCorei5-8500处理器评测 平民级的法拉利已经到来
传感器让油烟机更加智能,减少患癌风险
怎么选购空调稳压器
如何编程模拟计算机中的高速缓存
优秀软件测试工程师应具备哪些能力
未来医疗技术的新科技
魅族Pro7什么时候上市?魅族Pro7最新消息:魅族Pro7发布会前瞻,魅族Pro7背部装了个冰箱,清凉一夏?
电装传感技术跨界赋能,构建可持续发展食品价值链
这五大解决方案,已然成了罗姆未来重中之重
容易被ChatGPT取代的十种行业
音响系统中干扰声和啸叫声产生的原因及排除方法
6v蓄电池充电器电路图(七款蓄电池充电器电路图详解)
KT6368A的HID蓝牙双模版本_蓝牙键盘鼠标扫码枪方案介绍
Secure Thingz携手河洛半导体共同打造以网络安全为中心的编程
!! 矢量阻抗分析仪 P6418 探头 16034E 夹具
馈线的种类及工作参数是什么?
海龟机器人DIY图解
带STK IC的汽车低音炮放大器电路图