我一直在尝试提取应用程序访问的物理地址以分析行命中。
在此过程中,我遵循了此页面,由于版本更改而几乎没有变化。
我将 CacheConfig.py 修复为:
system.monitor2 = CommMonitor()
system.monitor2.trace = MemTraceProbe(trace_file = "CT_mon2.trc.gz")
system.monitor2.slave = system.l2.mem_side
system.membus.slave = system.monitor2.master
system.l2.cpu_side = system.tol2bus.master
并运行代码:
build/X86/gem5.opt --debug-flag=CommMonitor configs/example/se.py --caches --l2cache --l2_size=2MB --mem-type=DDR4_2400_16x4 -c tests/test-progs/mm/bin/x86/linux/mm --cpu-type=TimingSimpleCPU
mm 是简单矩阵乘法的二进制:
// C program to multiply two square matrices.
#include <stdio.h>
#define N 4
// This function multiplies mat1[][] and mat2[][],
// and stores the result in res[][]
void multiply(int mat1[][N], int mat2[][N], int res[][N])
{
int i, j, k;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
res[i][j] = 0;
for (k = 0; k < N; k++)
res[i][j] += mat1[i][k]*mat2[k][j];
}
}
}
int main()
{
int mat1[N][N] = { {1, 1, 1, 1},
{2, 2, 2, 2},
{3, 3, 3, 3},
{4, 4, 4, 4}};
int mat2[N][N] = { {1, 1, 1, 1},
{2, 2, 2, 2},
{3, 3, 3, 3},
{4, 4, 4, 4}};
int res[N][N]; // To store result
int i, j;
multiply(mat1, mat2, res);
printf("Result matrix is \n");
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
printf("%d ", res[i][j]);
printf("\n");
}
return 0;
}
解码“CT_mon2.trc.gz”后,内存轨迹如下:
5,u,15360,64,256,11500
6,u,183808,64,2,101000
5,u,18816,64,256,187000
6,u,183744,64,2,285000
5,u,18880,64,256,357000
6,u,171072,64,3,438000
6,u,171648,64,3,526000
6,u,172032,64,3,601000
6,u,174528,64,3,689000
5,u,18944,64,256,765000
第三个表示物理地址。
我感到困惑的是“u”部分。从解码阶段开始,任何未读(r)或写(w)的内容都标记为“u”。
通过调试,命令会以“UpgradeFailResp”和“ReadCleanReq”重复。
我期待有读取和写入的跟踪,但我不确定这里发生了什么。
谁能告诉我我错过了什么?
或者更好的获取物理地址的方法将会有很大的帮助。
谢谢, 朱利
5,u,15360,64,256,11500
您可以从util文件夹中的数据包解码脚本中找到这些数字的含义。例如,5 表示主(端口)id。 “u”表示既没有读也没有写命令。
如果您想了解 command 本身,一种可能的方法是编辑处理定时请求和响应的 gem5/src/mem/comm_monitor.cc 。例如:
DPRINTF(CommMonitor, "cmd: %s, cmdIndex: %d, addr: %lld masterId: %d \n", pkt->cmdString(),pkt->cmdToIndex(),pkt->getAddr(), pkt->masterId());
pkt->cmdString()
显示命令,或者您可以简单地使用pkt->print()
来查看数据包信息。您可以调查 packet.cc 了解更多信息。
每次更改 src 文件夹中的任何内容时,都需要重建 gem5。
您会看到超出读取和写入的流量的原因与 CommMonitor 的放置有关。 在您的系统中,membus 可能是一致性点,因此您将获得由 L2 缓存生成的各种流量,这些流量旨在与其他 L2 缓存(如果存在)进行缓存一致性操作。如果您将 CommMonitor 移动到一致性点以下,例如在 membus 和内存控制器之间,您应该只能看到读取和写入流量。
我也遇到过这个问题
我阅读了decode_packet_trace.py的源代码, 如果cmd为1或4,则表示ReadReq或WriteReq; 如果cmd为30或32,则表示MemRead或MemWrite。 然而,decode_packet_trace.py仅将ReadReq和WriteReq标记为'r'/'w', 但 MemRead 和 MemWrite 被标记为“u”。
考虑到您将监视器放置在 membus 上, 所有痕迹都是 MemRead/MemWrite,因此它们都标记为“u”。
您可以更正decode_packet_trace.py来纠正这个问题。