# MVP TODO - Unity 虚拟地址寻址模拟

此为 MVP 实现，时间要求紧，不需要太考虑代码结构，需要跨脚本访问的内容全用单例也没问题

## 0. 需求冻结（已确认）

- [x] 模式：单次地址翻译可视化 + 批量访问统计
- [x] 系统位数：仅支持 `32 / 48 / 64`
- [x] 页大小输入：仅支持 `2^n KB`
- [x] 访问次数 `N`：可配置
- [x] TLB：全相联 + LRU，条目数可配置，默认 `16`
- [x] 页表：固定二级页表（稀疏结构）
- [x] 物理内存输入：`MB`（自动换算帧数）
- [x] 缺页替换：FIFO
- [x] 指标：TLB 命中率 / 页表命中率 / 缺页次数 / 平均访问开销
- [x] 交互：单步 / 连续播放 / 重置
- [x] 可视化：表格高亮 + 日志时间线 + 简单流程动画
- [x] 技术栈：Unity 2022 + C#

## 1. 总体分步计划

1. Step 1：参数与核心数据模型
2. Step 2：地址生成与拆分
3. Step 3：TLB（LRU）实现
4. Step 4：二级页表与缺页/FIFO
5. Step 5：翻译引擎（单步状态机）
6. Step 6：统计模块
7. Step 7：UI 绑定与流程动画
8. Step 8：联调、测试、验收

## 2. Step 1 - 参数与核心数据模型

### TODO

- [x] 创建脚本目录：`Assets/Scripts/Core`、`Assets/Scripts/Simulation`、`Assets/Scripts/UI`
- [x] 新建 `SimulationConfig.cs`：定义可输入参数
- [x] 新建 `ConfigValidator.cs`：参数合法性校验
- [x] 新建 `AddressParts.cs`：保存 `VPN / offset / L1Index / L2Index`
- [x] 新建 `SimulationState.cs`：保存当前轮次、当前虚拟地址、是否缺页等

### 输入字段（MVP）

- [x] `vaBits`：`32|48|64`
- [x] `pageSizeKB`：`2^n`
- [x] `physicalMemoryMB`：正整数
- [x] `tlbEntries`：正整数，默认 `16`
- [x] `accessCount`：正整数
- [x] `pageFaultPenalty`：默认 `100`（抽象开销单位）

### 校验规则

- [x] `pageSizeKB` 必须是 2 的幂
- [x] `offsetBits = log2(pageSizeBytes)` 且 `offsetBits < vaBits`
- [x] `frameCount = floor(physicalMemoryBytes / pageSizeBytes)` 且 `frameCount >= 1`
- [x] 非法输入返回明确错误文本（用于 UI 提示）

### 完成标准

- [x] 给定任意合法参数，能计算全部派生参数并通过校验
- [x] 任意非法输入都能得到可读错误信息

## 3. Step 2 - 地址生成与拆分

### TODO

- [x] 新建 `AddressGenerator.cs`：生成 `[0, 2^vaBits - 1]` 范围虚拟地址
- [x] 新建 `AddressTranslatorUtils.cs`：拆分 `VPN + offset`
- [x] 实现二级页表索引位拆分

### 拆分规则

- [x] `vpnBits = vaBits - offsetBits`
- [x] `l1Bits = ceil(vpnBits / 2)`
- [x] `l2Bits = floor(vpnBits / 2)`
- [x] 从 `VPN` 拆出 `L1Index` 和 `L2Index`

### 完成标准

- [x] 控制台可打印每次地址拆分结果
- [x] 32/48/64 三种位数下拆分结果均正确

## 4. Step 3 - TLB（全相联 + LRU）

### TODO

- [ ] 新建 `TlbEntry.cs`：`VPN -> PFN` 映射及有效位
- [ ] 新建 `TlbCache.cs`：查询、更新、淘汰
- [ ] 使用 `Dictionary + LinkedList` 实现 O(1) 级 LRU

### 行为要求

- [ ] `Lookup(vpn)`：命中返回 PFN，未命中返回失败
- [ ] `InsertOrUpdate(vpn, pfn)`：已存在则更新并置为最近使用
- [ ] 超出容量时淘汰最久未使用项

### 完成标准

- [ ] 构造用例可验证 LRU 淘汰顺序正确
- [ ] 连续访问时命中统计准确

## 5. Step 4 - 二级页表 + 缺页 + FIFO

### TODO

- [ ] 新建 `TwoLevelPageTable.cs`：`Dictionary<L1, Dictionary<L2, PTE>>`
- [ ] 新建 `PageTableEntry.cs`：`PFN / present / dirty(可选)`
- [ ] 新建 `PhysicalMemoryManager.cs`：空闲帧管理 + FIFO 队列
- [ ] 缺页时分配空闲帧；无空闲帧时 FIFO 淘汰
- [ ] 淘汰后同步页表项状态（`present = false`）

### 行为要求

- [ ] 页表命中：TLB 未命中后，页表中有 `present = true` 映射
- [ ] 缺页：页表不存在或 `present = false`
- [ ] 装入页面后写回页表并更新 TLB

### 完成标准

- [ ] 能稳定运行大量访问（例如 `N=10000`）无崩溃
- [ ] FIFO 次序可从日志中验证

## 6. Step 5 - 翻译引擎（单步状态机）

### TODO

- [ ] 新建 `TranslatorEngine.cs`
- [ ] 定义步骤枚举：
- [ ] `GenerateVA`
- [ ] `SplitVA`
- [ ] `LookupTLB`
- [ ] `LookupPageTable`
- [ ] `HandlePageFault`
- [ ] `ComposePA`
- [ ] `Finalize`
- [ ] 提供 `StepOnce()` 与 `RunOneAccess()` 两种执行接口

### 完成标准

- [ ] 单步执行能暂停在每个阶段并暴露当前状态
- [ ] 一次完整访问流程结果与预期一致

## 7. Step 6 - 统计模块

### TODO

- [ ] 新建 `StatsCollector.cs`
- [ ] 累计：`totalAccess`、`tlbHit`、`pageTableHit`、`pageFault`
- [ ] 计算：`tlbHitRate`、`pageTableHitRate`、`avgCost`

### 开销模型（MVP）

- [ ] TLB 命中：`+1`
- [ ] TLB miss + 页表命中：`+4`
- [ ] 缺页：`+4 + pageFaultPenalty`

### 完成标准

- [ ] 指标在单步和批量模式下都持续更新
- [ ] 批量完成后给出最终汇总

## 8. Step 7 - UI 绑定与流程动画

### TODO

- [ ] 新建主场景 `Main.unity`
- [ ] 参数面板：位数/页大小/物理内存/TLB条目/N/开销参数
- [ ] 控制按钮：`单步`、`连续播放`、`暂停`、`重置`
- [ ] 流程节点 UI：当前步骤高亮（颜色 + 轻动画）
- [ ] 表格区：TLB、页表关键条目、FIFO 队列
- [ ] 日志时间线：每次访问的关键事件文本
- [ ] 指标区：四项核心指标实时显示

### 完成标准

- [ ] UI 上可完整观察一次访问的每个阶段
- [ ] 连续播放期间 UI 不冻结，可暂停/恢复

## 9. Step 8 - 联调、测试、验收

### 测试清单

- [ ] 参数边界：最小/最大可接受输入
- [ ] 位数覆盖：32/48/64 各跑一轮
- [ ] 页大小覆盖：多个 `2^n KB` 值
- [ ] 小样本可视化：`N=10`
- [ ] 大样本稳定性：`N=10000`
- [ ] TLB 容量边界：`1`、`16`、大值
- [ ] 物理内存极小场景：高缺页率验证 FIFO

### 验收标准

- [ ] 功能覆盖需求冻结清单
- [ ] 四项指标数值可解释且趋势合理
- [ ] 单步、连续播放、重置均可稳定使用
- [ ] 控制台无持续异常错误

## 10. 预计工时（MVP）

- [ ] Step 1-2：4-6 小时
- [ ] Step 3-4：6-10 小时
- [ ] Step 5-6：3-5 小时
- [ ] Step 7：6-8 小时
- [ ] Step 8：2-4 小时
- [ ] 合计：约 21-33 小时（约 3-4.5 天）

## 11. 首日执行建议（直接开工）

- [x] 先完成 Step 1（参数模型 + 校验）
- [x] 紧接 Step 2（地址拆分）
- [ ] 当天收尾前完成 Step 3（TLB LRU 最小可运行）
