Appearance
题目
假定主存地址为 32 位,按字节编址,指令 Cache 和数据 Cache 与主存之间均采用 8 路组相联映射方式,直写(WriteThrough)写策略和 LRU 替换算法,主存块大小为 64B,数据区容量各为 32KB。开始时 Cache 均为空。请回答下列问题。
(1) Cache 每一行中标记(Tag)、LRU 位各占几位?是否有修改位?
(2) 有如下 C 语言程序段:
c
for(k = 0; k < 1024; k++)
s[k] = 2 * s[k];若数组 s 及其变量 k 均为 int 型,int 型数据占 4B,变量 k 分配在寄存器中,数组 s 在主存中的起始地址为 008000C0H,则该程序段执行过程中,访问数组 s 的数据 Cache 缺失次数为多少?
(3) 若 CPU 最先开始的访问操作是读取主存单元 00010003H 中的指令,简要说明从 Cache 中访问该指令的过程,包括 Cache 缺失处理过程。
解析
本题考查 8 路组相联 Cache 的字段拆分、循环数组的命中率分析、Cache 缺失处理流程。
回顾本题 Cache 参数:
- 数据区 32KB,主存块 64B,8 路组相联 → 组数 = ;
- 直写策略 → 每次写都同步更新主存 → 不需要脏位 / 修改位;
- LRU 替换 → 8 路要 3 位 LRU 编号()。
(1) Tag / LRU / 是否有修改位 [3 分]
字段宽度推导:
| 字段 | 位数 | 推导 |
|---|---|---|
| 块内偏移 | 6 | |
| Cache 组号 | 6 | |
| Tag | 20 | |
| LRU(8 路) | 3 |
修改位(脏位):无。 直写策略下每次写都立刻同步主存,Cache 行从未"独自更新"过,没有"待写回"的状态,所以不需要脏位。
易错点: 修改位 / 脏位是 回写策略 才需要的;直写策略下省略不必要。LRU 位则与替换算法挂钩,只要不是随机替换或 FIFO 都需要。
(2) 数组 s 访问的数据 Cache 缺失次数 [4 分]
Step 1. 分析数组在内存中的布局。
s 的起始地址 008000C0H,二进制:
低 6 位(块内偏移)= 000000B = 0 → s 起始地址恰在主存块的边界。
Step 2. 算数组占多少个主存块。
数组大小 = ;每块 64B:
每块容纳 个数组元素。
Step 3. 数访问模式与缺失。
循环 s[k] = 2 * s[k] 对每个元素先读再写。按数组下标顺序遍历 → 同一主存块内的 16 个元素被连续访问。
- 块内第 1 个元素(如
s[0]、s[16]、...、s[1008]):首读 miss → 调入整块; - 块内之后的元素(15 个):全部命中(直写策略下"写"也命中,不会再 miss);
每块 1 次 miss,共 64 块:
易错点 1: 直写策略下"写命中"不算 miss,"写缺失"才算(先把块调入,再写)。本题循环每个元素先读再写,读已经把块带进 Cache,写一定命中。
易错点 2: 数组首地址刚好块对齐很关键。如果首地址不在 64B 边界上,第 0 块和最后一块可能多一次 miss(跨块),缺失数变 65。
(3) 读取主存 00010003H 指令的 Cache 访问过程 [3 分]
Step 1. 拆分主存地址。
按 [Tag 20 | 组号 6 | 块内偏移 6] 切:
| 字段 | 二进制 | 值 |
|---|---|---|
| Tag | 0000 0000 0000 0001 0000 | 00010H |
| 组号 | 000000 | 0 |
| 块内偏移 | 000011 | 3 |
Step 2. 查 Cache 第 0 组。
Cache 初始为空,所有有效位 = 0 → 第 0 组全无有效内容 → 访问缺失。
Step 3. 缺失处理流程。
- 从主存读出该块(地址区间
[00010000H, 00010040H),64B); - 找空行存入:第 0 组的 8 行任选一行(都还空着,无须 LRU 替换);
- 填字段:
- Tag 字段 ←
00010H; - 有效位 ← 1;
- LRU 位 ← 标记此行最新使用;
- Tag 字段 ←
- 从该行取出指令:按块内偏移
000011B= 3 → 取该 64B 块的第 3 字节作为指令字节。
编者注(生僻术语): 直写策略下,"写"操作的 Cache miss 处理可能有两种细分:写分配(write-allocate) 与 非写分配(no-write-allocate)。前者把块先调入 Cache 再写,后者直接写主存不动 Cache。题目未指定,按常用约定取写分配。本题循环都是先读再写,无论哪种策略首读都已把块装入。