传送门:官方教学
理解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中的元素不会根据其键值或映射值按任何特定顺序排序,而是根据其哈希值组织到桶中,以允许通过键值直接快速访问各个元素(常量的平均时间复杂度)。可以参考博客。