# MVP TODO - Unity 虚拟地址寻址模拟 此为 MVP 实现,时间要求紧,不需要太考虑代码结构,需要跨脚本访问的内容全用单例也没问题 ## 0. 需求冻结(已确认) - [x] 模式:单次地址翻译可视化 + 批量访问统计 - [x] 计算机位数:固定 `32-bit` - [x] 虚拟地址有效位:固定 `24-bit` - [x] 页大小:固定 `4 KB` - [x] 访问次数 `N`:可配置 - [x] TLB:固定 `8` 条全相联 + LRU - [x] 页表:固定二级页表(稀疏结构) - [x] 物理内存:固定 `1 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] `machineBits`:固定 `32` - [x] `vaBits`:固定 `24` - [x] `pageSizeKB`:固定 `4` - [x] `physicalMemoryMB`:固定 `1` - [x] `tlbEntries`:固定 `8` - [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] 固定 24 位 VA 场景下拆分结果正确 ## 4. Step 3 - TLB(全相联 + LRU) ### TODO - [x] 新建 `TlbEntry.cs`:`VPN -> PFN` 映射及有效位 - [x] 新建 `TlbCache.cs`:查询、更新、淘汰 - [x] 使用 `Dictionary + LinkedList` 实现 O(1) 级 LRU ### 行为要求 - [x] `Lookup(vpn)`:命中返回 PFN,未命中返回失败 - [x] `InsertOrUpdate(vpn, pfn)`:已存在则更新并置为最近使用 - [x] 超出容量时淘汰最久未使用项 ### 完成标准 - [x] 构造用例可验证 LRU 淘汰顺序正确 - [x] 连续访问时命中统计准确 ## 5. Step 4 - 二级页表 + 缺页 + FIFO ### TODO - [x] 新建 `TwoLevelPageTable.cs`:`Dictionary>` - [x] 新建 `PageTableEntry.cs`:`PFN / present / dirty(可选)` - [x] 新建 `PhysicalMemoryManager.cs`:空闲帧管理 + FIFO 队列 - [x] 缺页时分配空闲帧;无空闲帧时 FIFO 淘汰 - [x] 淘汰后同步页表项状态(`present = false`) ### 行为要求 - [x] 页表命中:TLB 未命中后,页表中有 `present = true` 映射 - [x] 缺页:页表不存在或 `present = false` - [x] 装入页面后写回页表并更新 TLB ### 完成标准 - [x] 能稳定运行大量访问(例如 `N=10000`)无崩溃 - [x] FIFO 次序可从日志中验证 ## 6. Step 5 - 翻译引擎(单步状态机) ### TODO - [x] 新建 `TranslatorEngine.cs` - [x] 定义步骤枚举: - [x] `GenerateVA` - [x] `SplitVA` - [x] `LookupTLB` - [x] `LookupPageTable` - [x] `HandlePageFault` - [x] `ComposePA` - [x] `Finalize` - [x] 提供 `StepOnce()` 与 `RunOneAccess()` 两种执行接口 ### 完成标准 - [x] 单步执行能暂停在每个阶段并暴露当前状态 - [x] 一次完整访问流程结果与预期一致 ## 7. Step 6 - 统计模块 ### TODO - [x] 新建 `StatsCollector.cs` - [x] 累计:`totalAccess`、`tlbHit`、`pageTableHit`、`pageFault` - [x] 计算:`tlbHitRate`、`pageTableHitRate`、`avgCost` ### 开销模型(MVP) - [x] TLB 命中:`+1` - [x] TLB miss + 页表命中:`+4` - [x] 缺页:`+4 + pageFaultPenalty` ### 完成标准 - [x] 指标在单步和批量模式下都持续更新 - [x] 批量完成后给出最终汇总 ## 8. Step 7 - UI 绑定与流程动画 ### TODO - [ ] 新建主场景 `Main.unity` - [ ] 参数面板:固定规格展示(位数/页大小/物理内存/TLB)+ 可调参数(N/开销/地址模式) - [ ] 控制按钮:`单步`、`连续播放`、`暂停`、`重置` - [ ] 流程节点 UI:当前步骤高亮(颜色 + 轻动画) - [ ] 表格区:TLB、页表关键条目、FIFO 队列 - [ ] 日志时间线:每次访问的关键事件文本 - [ ] 指标区:四项核心指标实时显示 ### 字段绑定对照(Step 7) - [ ] `SimulationUiController.configInputView` -> 挂有 `SimulationConfigInputView` 的对象 - [ ] `SimulationUiController.controlView` -> 挂有 `SimulationControlView` 的对象 - [ ] `SimulationUiController.dashboardView` -> 挂有 `SimulationDashboardView` 的对象 - [ ] `SimulationUiController.tablesView` -> 挂有 `SimulationTablesView` 的对象 - [ ] `SimulationUiController.traceView` -> 挂有 `SimulationTraceView` 的对象(拆分/分支解释) - [ ] `SimulationUiController.compactEventView` -> 主视图短事件流(建议 5-8 条) - [ ] `SimulationUiController.detailTimelineView` -> 详细日志时间线(可放在抽屉中) - [ ] `SimulationUiController.processHeaderView` -> 流程主标题与当前事件 - [ ] `SimulationUiController.flowAnimator` -> 挂有 `StepFlowAnimator` 的对象 - [ ] `SimulationUiController.detailDrawerView` -> 挂有 `SimulationDetailDrawerView` 的对象 - [ ] `SimulationUiController.playIntervalSeconds` -> 连续播放间隔秒数 - [ ] `SimulationConfigInputView.fixedCoreSpecText` -> 固定核心规格说明文本(32位机/24位VA/4KB页/1MB物理内存/TLB 8条全相联) - [ ] `SimulationConfigInputView.machineBitsInput` -> 计算机位数显示输入框(只读,固定32) - [ ] `SimulationConfigInputView.vaBitsDropdown` -> 虚拟地址位数下拉(只读,固定24) - [ ] `SimulationConfigInputView.pageSizeKBInput` -> 页大小 KB 输入框(只读,固定4) - [ ] `SimulationConfigInputView.physicalMemoryMBInput` -> 物理内存 MB 输入框(只读,固定1) - [ ] `SimulationConfigInputView.tlbEntriesInput` -> TLB 条目数输入框(只读,固定8) - [ ] `SimulationConfigInputView.accessCountInput` -> 访问次数 N 输入框 - [ ] `SimulationConfigInputView.pageFaultPenaltyInput` -> 缺页惩罚输入框 - [ ] `SimulationConfigInputView.addressModeDropdown` -> 地址模式下拉(Random/SequentialArrayLoop) - [ ] `SimulationConfigInputView.arrayLengthBytesInput` -> 数组总长度(bytes) - [ ] `SimulationConfigInputView.arrayElementBytesInput` -> 数组元素大小(bytes) - [ ] `SimulationConfigInputView.arrayBaseAddressInput` -> 数组基址(十进制) - [x] `SimulationControlView.stepButton` -> `单步` 按钮 - [x] `SimulationControlView.playButton` -> `连续播放` 按钮 - [x] `SimulationControlView.pauseButton` -> `暂停` 按钮 - [x] `SimulationControlView.resetButton` -> `重置` 按钮 - [x] `SimulationDashboardView.stateSummaryText` -> 当前步骤/地址拆分/命中状态文本 - [x] `SimulationDashboardView.statsText` -> 统计指标文本 - [x] `SimulationDashboardView.errorText` -> 参数错误提示文本 - [x] `SimulationTablesView.tlbText` -> TLB 表格文本区 - [x] `SimulationTablesView.pageTableText` -> 页表关键条目文本区 - [x] `SimulationTablesView.fifoText` -> FIFO 队列文本区 - [ ] `SimulationTraceView.splitTraceText` -> 地址拆分可视化文本 - [ ] `SimulationTraceView.pageTableTraceText` -> 多级页表查询路径文本 - [ ] `SimulationTraceView.decisionReasonText` -> 当前分支原因文本 - [ ] `SimulationTraceView.pathSummaryText` -> 当前访问路径摘要文本 - [x] `SimulationTimelineView.logContainer` -> 日志内容容器(建议 VerticalLayoutGroup) - [x] `SimulationTimelineView.logItemPrefab` -> 单条日志 TMP_Text 预制体 - [x] `SimulationTimelineView.logScrollRect` -> 日志滚动视图 - [x] `SimulationTimelineView.maxLogEntries` -> 日志最大保留条数(建议 `200`) - [x] `SimulationProcessHeaderView.currentStepText` -> 当前步骤文本(流程主区) - [x] `SimulationProcessHeaderView.currentEventText` -> 当前关键事件文本(流程主区) - [x] `SimulationDetailDrawerView.drawerRoot` -> 细节抽屉根节点 - [x] `SimulationDetailDrawerView.dashboardTabRoot` -> Dashboard 页签内容根节点 - [x] `SimulationDetailDrawerView.tablesTabRoot` -> Tables 页签内容根节点 - [x] `SimulationDetailDrawerView.eventsTabRoot` -> Events 页签内容根节点(detailEventFlow) - [x] `SimulationDetailDrawerView.openOnStart` -> 抽屉是否默认展开 - [x] `SimulationDetailDrawerView.dashboardTabButton` -> Drawer 内 Dashboard Tab 按钮 - [x] `SimulationDetailDrawerView.tablesTabButton` -> Drawer 内 Tables Tab 按钮 - [x] `SimulationDetailDrawerView.eventsTabButton` -> Drawer 内 Events Tab 按钮 - [x] `SimulationDetailDrawerView.closeDrawerButton` -> Drawer 内关闭按钮 - [ ] 主界面 Info 按钮 -> `SimulationUIController.OpenDetailDrawer()` - [ ] `StepFlowAnimator.stepNodes(7项)` -> `GenerateVA/SplitVA/LookupTLB/LookupPageTable/HandlePageFault/ComposePA/Finalize` 节点 - [ ] `StepFlowAnimator.stepNodes[].target` -> 节点 `RectTransform` - [ ] `StepFlowAnimator.stepNodes[].canvasGroup` -> 节点 `CanvasGroup` - [ ] `StepFlowAnimator.stepNodes[].background` -> 节点背景 `Image` - [ ] `StepFlowAnimator.accessPulseTarget` -> 完整访问完成时做脉冲动画的容器节点 ### 完成标准 - [ ] UI 上可完整观察一次访问的每个阶段 - [ ] 连续播放期间 UI 不冻结,可暂停/恢复 ## 9. Step 8 - 联调、测试、验收 ### 测试清单 - [ ] 参数边界:最小/最大可接受输入 - [ ] 固定规格回归:`32位机 + 24位VA + 4KB页 + 1MB物理内存` - [ ] 固定规格下参数覆盖:访问次数 / 缺页惩罚 / 地址生成模式 - [ ] 小样本可视化:`N=10` - [ ] 大样本稳定性:`N=10000` - [ ] TLB 固定容量验证:`8` 条全相联 + LRU 顺序正确 - [ ] 物理内存极小场景:高缺页率验证 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(地址拆分) - [x] 当天收尾前完成 Step 3(TLB LRU 最小可运行)