计算机体系结构,4 路缓存 hit/replacement 混乱
Computer architecture, 4-way cache hit/replacement confustion
我正在尝试在 verilog 中实现 4 路缓存,但我对缓存查找方案有些困惑。假设我有以下规格:
C = ABS
C = 1KB
A = 4
B = 128 bits (4 DWORD)
S = C/AB = (8192)/(4*128) = 16
offset = lg(B) = 7 bits
index = lg(S) = 4 bits
tag = 32 - offset - index = 21 bits
C: Capacity in data arrays
A: Way-Associativity
B: Block Size (Cacheline)
How many bytes in a block
S: Number of Sets:
A set contains blocks sharing the same index
在我的记忆中我有:
H 0000_0000 0000 0000 0000 0000 0000 0000 0|000 0|000 0000
E 0000_0004
L 0000_0008
L 0000_000C
O 0000_0010 0000 0000 0000 0000 0000 0000 0|000 0|001 0000
0000_0014
W 0000_0018
O 0000_001C
R 0000_0020 0000 0000 0000 0000 0000 0000 0|000 0|010 0000
L 0000_0024
D 0000_0028
! 0000_002C
假设我是一个新的开始,我在地址 0x0000_0000 请求加载字,因为我的缓存是空的,我将 HELL
写入索引 0 上的缓存行之一4个数组。
然后我在地址0x0000_0010请求另一个加载字,此时我很困惑。
我的问题是,由于我的标签和索引相同,因此命中,但我的缓存行中没有 O
一词。在这种情况下我的缓存应该做什么?我是否踢出 HELL
并在同一个数组中写入 O WO
?如果是这样,我应该如何区分这两个地址,因为我们只查看标记和索引位?
我的另一种想法是,既然它是命中的,那么缓存不应该因为我们找到了匹配项而被驱逐。但是那场比赛没有我要求的实际词。所以如果我不做替换这个逻辑是错误的,但是我的缓存是命中的。我刚刚进入了逐出和缓存命中之间的循环逻辑。
更新后,问题变得清晰:B
应该是以字节为单位的大小,但您使用了以位为单位的大小。地址中正确的偏移位数是 log2(16) = 4。如果将图中的 |
分隔符移动到正确的位置,一切都会正常进行:您会看到每个 16B 块都有一个比上一个高 1 的索引。
H 0000_0000 0000 0000 0000 0000 0000 0000|0000|0000
E 0000_0004
L 0000_0008
L 0000_000C
O 0000_0010 0000 0000 0000 0000 0000 0000|0001|0000
0000_0014
...
我还注意到你的地址是前 36 位,多了一个 0000
块。我也仔细检查了索引位的数量:4 个索引位意味着您的 16 组 4 种方式中的每一种。 16 * 4 * 16B = 1024B,所以这适合您的 1kiB 缓存。
您遇到了与 相同的问题,多个内存块进入同一缓存行,但原因不同。这表明您遇到了严重错误,因为一个缓存行必须始终足够大以保存具有相同标记+索引位的地址中的所有数据。
我正在尝试在 verilog 中实现 4 路缓存,但我对缓存查找方案有些困惑。假设我有以下规格:
C = ABS
C = 1KB
A = 4
B = 128 bits (4 DWORD)
S = C/AB = (8192)/(4*128) = 16
offset = lg(B) = 7 bits
index = lg(S) = 4 bits
tag = 32 - offset - index = 21 bits
C: Capacity in data arrays
A: Way-Associativity
B: Block Size (Cacheline)
How many bytes in a block
S: Number of Sets:
A set contains blocks sharing the same index
在我的记忆中我有:
H 0000_0000 0000 0000 0000 0000 0000 0000 0|000 0|000 0000
E 0000_0004
L 0000_0008
L 0000_000C
O 0000_0010 0000 0000 0000 0000 0000 0000 0|000 0|001 0000
0000_0014
W 0000_0018
O 0000_001C
R 0000_0020 0000 0000 0000 0000 0000 0000 0|000 0|010 0000
L 0000_0024
D 0000_0028
! 0000_002C
假设我是一个新的开始,我在地址 0x0000_0000 请求加载字,因为我的缓存是空的,我将 HELL
写入索引 0 上的缓存行之一4个数组。
然后我在地址0x0000_0010请求另一个加载字,此时我很困惑。
我的问题是,由于我的标签和索引相同,因此命中,但我的缓存行中没有 O
一词。在这种情况下我的缓存应该做什么?我是否踢出 HELL
并在同一个数组中写入 O WO
?如果是这样,我应该如何区分这两个地址,因为我们只查看标记和索引位?
我的另一种想法是,既然它是命中的,那么缓存不应该因为我们找到了匹配项而被驱逐。但是那场比赛没有我要求的实际词。所以如果我不做替换这个逻辑是错误的,但是我的缓存是命中的。我刚刚进入了逐出和缓存命中之间的循环逻辑。
更新后,问题变得清晰:B
应该是以字节为单位的大小,但您使用了以位为单位的大小。地址中正确的偏移位数是 log2(16) = 4。如果将图中的 |
分隔符移动到正确的位置,一切都会正常进行:您会看到每个 16B 块都有一个比上一个高 1 的索引。
H 0000_0000 0000 0000 0000 0000 0000 0000|0000|0000
E 0000_0004
L 0000_0008
L 0000_000C
O 0000_0010 0000 0000 0000 0000 0000 0000|0001|0000
0000_0014
...
我还注意到你的地址是前 36 位,多了一个 0000
块。我也仔细检查了索引位的数量:4 个索引位意味着您的 16 组 4 种方式中的每一种。 16 * 4 * 16B = 1024B,所以这适合您的 1kiB 缓存。
您遇到了与