概述
本次更新将 Linux 内核仿真推进至用户态 init。核心改动集中在中断精确化:WB 边界实时中断判定、外部中断统一走 ESTAT/ECFG 屏蔽路径、硬件中断线接入、TVAL 读回修正,以及 difftest StoreEvent 物理地址与异常门控的多处修复。涉及 6 个文件,净变更 +93 / -111 行。
修改内容
1. WB
边界实时中断判定:wb_int_live
文件:core_top.v:1721-1740
问题:原设计在 ID 段采样中断状态并经流水线携带至
WB(wb_has_int)。当 csrxchg 在流水线中使能 IE
后,当前正在提交的指令过 ID 时 IE 尚未更新,导致 DUT 晚于 NEMU
认中断——NEMU 在 IE 使能后第一条指令即取中断,DUT 却执行了它,era 保持为
0。
修复:在 WB 边界按当前 CSR
状态实时判定中断,取代流水线携带的 wb_has_int:
1 | wire wb_int_live = wb_valid & ~wb_is_ertn & ~idle_wait_r & ~wb_is_idle_commit & ~wb_dram_we |
~wb_dram_we:不在正在提交的 Store 上取中断。Store 的访存副作用在 EXE2 已发起、到 WB 已写入 SRAM 不可撤销;若此拍 squash 该指令,DUT 内存已变但 difftest 不把该 Store 应用到 NEMU → 内存失配。改为让 Store 完整提交、中断推迟到下一条指令边界(精确中断合法)。~wb_is_ertn:ertn 提交拍 IE 仍为旧值,显式排除。~idle_wait_r:idle 等待/唤醒走idle_wake专路。
trap_unit 的中断注入改为
.wb_has_int((wb_int_live | idle_wake) && csr_crmd_ie)。
2. Store 异常阻断移除中断标记
文件:core_top.v:1279-1296
问题:mem_trap_pending 和
exe2_self_trap 原先包含 mem_has_int /
exe2_has_int,会在中断挂起时抑制 EXE2/MEM 阶段的 Store
物理写。但中断在 WB 边界由 wb_int_live 精确判定,且被
~wb_dram_we 推迟到 Store 之后——若上游仍用流水线中断标记抑制
Store 写,会造成”Store
提交但内存未写”的失配(观测:sc.w @a07b5618 被中断,DUT
mutex=0 而 REF 仍锁定)。
修复:从 mem_trap_pending 和
exe2_self_trap 中移除 mem_has_int /
exe2_has_int,只保留同步异常(ALE/TLB/ADEF/SYS/BRK/INE)的阻断:
1 | assign mem_trap_pending = !mem_need_cancel && !mem_is_ertn && |
3. 外部中断统一屏蔽路径
文件:interrupt.v:19-28
问题:原实现中
has_external_int = |ext_intrpt 直接 OR 进中断输出,绕过了
ECFG.LIE 屏蔽——即使该硬件中断在 ECFG 中被关闭也会触发,违反手册;且与
ESTAT 路径重复计数。
修复:移除独立的外部中断路径,统一走
ESTAT.IS & ECFG.LIE 屏蔽:
1 | wire [12:0] int_masked = csr_estat_is & csr_ecfg_lie; |
4. 硬件中断线接入 ESTAT
文件:core_top.v:1854-1860
问题:hw_int_in 硬连
8'b0,导致所有外设硬件中断(UART/MAC/DMA 等,经 SoC
intrpt 端口送入)永远无法被记录到 ESTAT,CPU
无法响应外设中断。
修复:将 8 条硬件中断线(HWI0..HWI7)直接接自顶层
intrpt 端口,接入 CSR.ESTAT.IS[9:2]:
1 | assign hw_int_in = intrpt; |
5. TVAL 读回修正
文件:csr.v:976-986
问题:原实现
csr_tval = timer_cnt - 1。到期那一拍
timer_cnt == 0、ESTAT.TI 置起,此时 TVAL 应读回 0;但
timer_cnt - 1 回绕成 0xFFFFFFFF,经 difftest
同步进 NEMU 后,NEMU 自主计时器在到期边沿看到”离到期还差
~4G”,把定时中断推迟很久,导致 DUT 比 REF
提前数千条指令响应定时中断。
修复:改为直接读 timer_cnt,与手册
7.6.3 一致:
1 | assign csr_tval = timer_cnt; |
6. CSR
读状态门控:wb_res_from_csr
文件:core_top.v:2619-2625
问题:wb_csr_rstat 原先只检查
wb_csr_num == 14'h5(ESTAT),但 wb_csr_num
对任意指令都取 inst[23:10]。非 CSR 指令(如
bgeu 0x6c0016d7,该字段恰为 0x5)会被误判为读 ESTAT,把
rf_wdata 当成 ESTAT 值灌进 NEMU,污染 NEMU
的硬件中断位。
修复:加 wb_res_from_csr
门控,确保只在真正的 CSR 读指令上同步 ESTAT:
1 | assign wb_csr_rstat = wb_res_from_csr && (wb_csr_we == 1'b0) && (wb_csr_num == 14'h5) && wb_valid; |
7. StoreEvent 物理地址修正
文件:core_top.v:2639-2647、Mem_reg.v、Wb_reg.v
问题:wb_store_paddr 原先在 WB 用 CSR
重算,只覆盖 direct/DMW0/DMW1 分支,漏了 TLB 映射(fallback 误用虚地址
wb_data_addr)。用户态首个 TLB 翻译的 Store 上报
paddr = vaddr = 0x24558c,与 NEMU
正确翻译的物理地址失配。
修复:新增 exe2_data_paddr →
mem_data_paddr → wb_data_paddr
物理地址流水线(经 Mem_reg.v、Wb_reg.v
传递),直接取 EXE2 阶段 TLB/DMW 翻译后的 data_addr:
1 | assign wb_store_paddr = wb_data_paddr; |
物理写内存本就用 data_addr,此修复仅纠正 difftest
上报,不改变 FPGA/流片访存行为。
8. rdcntvl/vh.w 计数器同步
文件:core_top.v:2687-2692
问题:cmt_stable_counter 直接送 live
csr_timer_64(WB 拍),而 DUT 寄存器写入的是 ID
拍采样、经流水线携带的 wb_res_of_cnt。NEMU 会比 DUT 快
ID→WB 的流水线深度(实测 +4)。
修复:按读取半字用 wb_res_of_cnt
重建,令 NEMU 读回与 DUT 寄存器一致:
1 | cmt_stable_counter <= (wb_res_from_cnt & (wb_inst[14:10]==5'h18)) ? {csr_timer_64[63:32], wb_res_of_cnt} : |
9. StoreEvent/LoadEvent 异常门控
文件:core_top.v:2693-2699
问题:Faulting Store(如 st.w 触发
PIS,wb_ex=1)的物理 SRAM 写已被
data_side_effect_block 压制,NEMU 也因取异常不写内存;但
StoreEvent 仍按 wb_is_store 上报,给 NEMU 强灌一次不存在的
Store,造成内存失配。
修复:与 cmt_valid 用同一异常门控,加
!wb_ex:
1 | cmt_inst_ld_en <= wb_is_load && wb_valid && !wb_ex && !idle_freeze; |
10. 调试日志清理
文件:core_top.v、csr.v、tlb.v
移除全部 $display
调试语句:[CSR-EX]、[CSR-ERTN]、[TLBIDX-WR]、[TLBIDX-CHG]、[TLB-WR]、[TLB-RACC]、[TLB-E-CHG]、[TLB-E-WR]、[TLB-INV]、[TLB-RST]、[TLB-INIT]、[MEM-ST]、[EX]、[N53_ALEDBG]。
亟待解决的问题
TLB 与 Cache 粒度不对齐
当前 TLB 页粒度为 4KB(PS=12),而 D-Cache 行粒度为
32B。当 TLB 访问一个不对齐的虚拟地址(跨页边界)时,D-Cache
可能只完成部分行的写入后就触发 TLB
异常。此时中断响应需要完整的流水线冲刷,但 Cache
中残留的脏行可能导致中断处理程序读取到不一致的数据。
修改文件清单
| 文件 | 变更 |
|---|---|
core_top.v |
wb_int_live 实时中断判定、Store
异常阻断移除中断标记、hw_int_in
接入、wb_csr_rstat 门控、wb_store_paddr
修正、cmt_stable_counter 重建、StoreEvent
异常门控、调试日志清理 |
csr.v |
TVAL 读回修正(timer_cnt)、调试日志清理 |
interrupt.v |
外部中断统一走 ESTAT/ECFG 屏蔽路径 |
tlb.v |
调试日志清理 |
Mem_reg.v |
新增 mem_data_paddr 物理地址传递 |
Wb_reg.v |
新增 wb_data_paddr 物理地址传递 |