Categories: 硬件设计.

概述

本次更新将 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
2
wire wb_int_live = wb_valid & ~wb_is_ertn & ~idle_wait_r & ~wb_is_idle_commit & ~wb_dram_we
& (|(csr_estat_is & csr_ecfg_lie)) & csr_crmd_ie;
  • ~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_pendingexe2_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_pendingexe2_self_trap 中移除 mem_has_int / exe2_has_int,只保留同步异常(ALE/TLB/ADEF/SYS/BRK/INE)的阻断:

1
2
3
4
5
6
7
8
9
assign mem_trap_pending = !mem_need_cancel && !mem_is_ertn &&
(mem_ex_adef || mem_ex_brk || mem_ex_ine ||
mem_ex_ale || mem_is_syscall ||
(mem_inst_tlb_ex != 2'b0) || (mem_data_tlb_ex != 3'b0));

assign exe2_self_trap = !exe2_need_cancel && !exe2_is_ertn &&
(exe2_ex_adef || exe2_ex_brk || exe2_ex_ine ||
exe2_ex_ale || exe2_is_syscall ||
(exe2_inst_tlb_ex != 2'b0) || (data_tlb_ex != 3'b0));

3. 外部中断统一屏蔽路径

文件interrupt.v:19-28

问题:原实现中 has_external_int = |ext_intrpt 直接 OR 进中断输出,绕过了 ECFG.LIE 屏蔽——即使该硬件中断在 ECFG 中被关闭也会触发,违反手册;且与 ESTAT 路径重复计数。

修复:移除独立的外部中断路径,统一走 ESTAT.IS & ECFG.LIE 屏蔽:

1
2
3
wire [12:0] int_masked = csr_estat_is & csr_ecfg_lie;
wire has_masked_int = |int_masked;
wire has_int = csr_crmd_ie && has_masked_int;

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-2647Mem_reg.vWb_reg.v

问题wb_store_paddr 原先在 WB 用 CSR 重算,只覆盖 direct/DMW0/DMW1 分支,漏了 TLB 映射(fallback 误用虚地址 wb_data_addr)。用户态首个 TLB 翻译的 Store 上报 paddr = vaddr = 0x24558c,与 NEMU 正确翻译的物理地址失配。

修复:新增 exe2_data_paddrmem_data_paddrwb_data_paddr 物理地址流水线(经 Mem_reg.vWb_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
2
3
cmt_stable_counter <= (wb_res_from_cnt & (wb_inst[14:10]==5'h18)) ? {csr_timer_64[63:32], wb_res_of_cnt} :
(wb_res_from_cnt & (wb_inst[14:10]==5'h19)) ? {wb_res_of_cnt, csr_timer_64[31:0]} :
csr_timer_64;

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
2
cmt_inst_ld_en <= wb_is_load && wb_valid && !wb_ex && !idle_freeze;
cmt_inst_st_en <= (wb_is_store && wb_valid && !wb_ex && !idle_freeze) ? (...) : 8'b0;

10. 调试日志清理

文件core_top.vcsr.vtlb.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 物理地址传递