[代码阅读]gem5 classic cache初步(2)

本文详细解析了经典缓存文件(Cache.cc, cache.hh, cache_impl.hh等),特别是Lru.cc中的基本功能和cache_impl.hh中的实现细节。通过分析缓存模块的起点和流程,包括面向CPU和内存的操作端口,以及缓存同步问题,揭示了缓存操作的内在逻辑和关键步骤。

下面的分析主要集中classic cache有关的文件:

Cache.cc, cache.hh, cache_impl.hh,以及tag中的lru.cc,lru.hh等文件。

 

Lru.cc中的内容不复杂,我们先来分析,主要完成的功能是:

insertBlock, findVictim等相关容易掌握的函数,这里不再作深入探讨;

 

主要的问题在于cache.hh, cache.cc以及cache_impl.hh等部分,其中的cache_impl.hh部分是实现cache具体操作的主要部分,其中只有功能模块的定义,没有关于调用过程的信息,为了把握其中的相关信息,我们开启其中的debug功能,生成相关的trace:

 

     0: system.cpu0.icache: ReadReq (ifetch) 1cb60 miss

  1000: system.l2: ReadReq (ifetch) 1cb40 miss

 41000: system.l2: Handling response to 1cb40

 41000: system.l2: Block for addr 1cb40 being updated in Cache

 41000: system.l2: Block addr 1cb40 moving from state 0 to 7

 52000: system.cpu0.icache: Handling response to 1cb40

 52000: system.cpu0.icache: Block for addr 1cb40 being updated in Cache

 52000: system.cpu0.icache: Block addr 1cb40 moving from state 0 to 7

 54000: system.cpu0.icache: ReadReq (ifetch) 1cb64 hit

 55000: system.cpu0.icache: ReadReq (ifetch) 1cb64 hit

 

根据上述的部分trace内容,我们再回到cache_impl.hh中的源代码,知道处理流程与代码中模块的对应关系,但是上面的trace内容少了些,因此我们打算在源代码中再增加一些DPRINTF语句来便于更好的追踪,经过自己增加额外的DPRINTF语句后,我们分析得出cache模块操作的两个起点在于如下:

 

1.      面向cpu;cpu_side_port:

CpuSidePort::recvTiming(…){

myCache->timingAccess(pkt);

}                              

 

2.      面向mem:

MemSidePort::recvTiming(){

myCache->handleResponse(pkt);

}

上述的两个端口就决定了我们的分析切入点,那接下来要分析的事情就变得很简单了:从这两个起点入手,一步步地跟踪分析即可。另外还需要考虑的就是缓存同步问题,相应的分析入口就在MemSidePort::recvTiming(){}中的myCache->snooptiming(pkt)。

 


### 配置与使用 gem5 的 L3 缓存 gem5 是一种模块化的离散事件仿真器,用于模拟计算机系统的各个方面。L3 缓存在多核处理器架构中扮演重要角色,通常作为共享缓存层来减少内存访问延迟并提高性能。 #### 定义系统结构 为了在 gem5 中配置 L3 缓存,首先需要定义整个系统的层次结构。这可以通过创建多个 CPU 核心、私有 L1 和 L2 缓存以及一个共享的 L3 编程实现[^4]。以下是典型的设置方法: ```python from m5.objects import * # 创建两个简单的原子核心 cpu1 = AtomicSimpleCPU() cpu2 = AtomicSimpleCPU() # 为每个 CPU 添加私有的 L1 缓存控制器 l1cache_cpu1 = Cache(size='32kB', assoc=8, tag_latency=2, data_latency=2) l1cache_cpu2 = Cache(size='32kB', assoc=8, tag_latency=2, data_latency=2) # 将 L1 缓存连接到各自的 CPU cpu1.addPrivateSplitL1Caches(l1cache_cpu1, None) cpu2.addPrivateSplitL1Caches(l1cache_cpu2, None) # 设置共享的 L2 缓存 l2cache = Cache(size='2MB', assoc=16, tag_latency=20, data_latency=20) # 连接 L1 到 L2 缓存 bus_to_l2 = Bus(width=16) l1cache_cpu1.connectBus(bus_to_l2) l1cache_cpu2.connectBus(bus_to_l2) l2cache.cpu_side = bus_to_l2.master # 建立 L3 缓存 l3cache = Cache(size='16MB', assoc=16, tag_latency=50, data_latency=50) # 使用总线将 L2 缓存连接至 L3 缓存 bus_to_mem = Bus(width=64) l2cache.mem_side = bus_to_mem.slave l3cache.cpu_side = bus_to_mem.master # 最终将 L3 缓存连接到主存储器 root_system = System(mem_mode='timing', mem_ranges=[AddrRange('512MB')]) root_system.physmem = SimpleMemory(range=root_system.mem_ranges[0]) l3cache.mem_side = root_system.physmem.port ``` 上述代码片段展示了如何构建一个多级缓存体系结构,在此结构中,L3 缓存充当所有 CPU 共享的最后一级高速缓存[^4]。 #### 调整参数 可以根据具体需求调整 L3 缓存大小 (`size`)、关联度 (`assoc`) 及其他属性如 `tag_latency` 或 `data_latency` 来优化性能表现[^5]。 #### 启动仿真 完成配置之后,通过运行以下命令可以启动仿真实验: ```bash build/X86/gem5.opt configs/example/fs.py --num-cpus=2 --caches --l2cache --l3cache-size="16MB" ``` 该命令指定了双核处理单元,并启用了各级缓存支持,其中特别设置了 L3 缓存容量为 16 MB[^6]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值