当前位置: 首页 > 工具软件 > SimpleCache > 使用案例 >

浅谈gem5的SimpleCache实现

鞠凌龙
2023-12-01

传送门:官方教学
理解SimpleCache需要先学会SimMemory的创建。(即上一章)。接下来是对于SimpleCache实现的一些理解。

定义部分

  • system = Param.System(Parent.any, "The system this cache is part of")实现的cache需要与整个系统连接,而要获取连接的系统就是通过Parent.any这个默认值。它可以向上递归的查找cache连接的系统传递给参数system。(需要引入from
    m5.proxy import *). 之后使用system来获取参数,如blockSize(params->system->cacheLineSize()),.
  • cpu_side = VectorSlavePort("CPU side port, receives requests")
    对于cpu的连接使用Vector可以连接多个端口。参数(PortID idx)用于区分不同的端口.而被定义为Vector的端口自动具有port_xxx_side_connection_count变量。然后for循环根据连接数量放进cpuPorts中。
  • 对于getPort部分:最近的gem5中可以直接引入mem/port.hh然后统一写到getPort函数中。

SimpleCache的处理逻辑

  • handleRequest :主要有两个功能,第一是记录正在等待的端口,第二是模拟延迟:不需要tutoria里面的accessEvent类封装,可以直接使用之前用到的EventFunctionWrapper。在函数体里面调用accessTiming(pkt). ***sendResponse***则只需要向对应的端口发送pkt就行。
  • accessTiming:通过accessFunctional()函数判断是否Hit,如果hit则直接Response。如果miss,则判断数据包是否是地址对齐且请求的大小等于一个块大小。如果是,则直接通过memSide转发给Memory,如果不是,则需要创造新的PacketPtr,将之前的pkt保存起来,然后向内存请求。
  • 缓存功能:通过std::unordered_map<Addr, uint8_t*> cacheStore;缓存数据和地址。这里直接是使用find()查找有没有这个地址的数据,而不是比较Tag段。另外使用当前存储的数据条目是否多于指定容量,如果多了就需要逐出。uint8_t是unsigned char 别名,8位数据。

Packet类

构造函数:

Packet(const RequestPtr &_req, MemCmd _cmd)
Packet(const RequestPtr &_req, MemCmd _cmd, int _blkSize, PacketId _id = 0)
Packet(const PacketPtr pkt, bool clear_flags, bool alloc_data)

包括一个RequestPtr类和MemCmd类。

对于PacketPtr中的地址可以通过,getAddr()得到,对于块地址可以通过getBlockAddr():如一块为8B则将低三位地址清零就可以得到块地址。通过getSize()获得一个请求包需要请求的字节。
在请求的接收者正在生成响应的情况下,它可以选择将请求数据包重用于其响应,以节省调用delete和new调用的开销(使用makeResponse() )

unordered_map

在内部,std::unordered_map中的元素不会根据其键值或映射值按任何特定顺序排序,而是根据其哈希值组织到桶中,以允许通过键值直接快速访问各个元素(常量的平均时间复杂度)。可以参考博客

 类似资料: