概述
本次更新修复了 func_lab19 中的 IDLE 等待中断挂死问题,并修正了 CACOP Hit 型指令的 IPE 误触发。成果:func_lab19 修复通过(END by Syscall,132811 条指令),func_lab15 无回归,func_advance difftest 零失配。
核心改动集中在 core_top.v 的 IDLE 等待中断状态机与
Wb_reg.v 的 WB 保持逻辑,涉及 2 个文件。
修改内容
1. IDLE 等待中断 FSM(核心修复)
文件:core_top.v:1319-1343
问题:LoongArch 语义中,执行 IDLE
后处理器核停止取指进入等待态,被 ECFG 使能的中断唤醒后在 IDLE
的下一条指令处响应中断,即 era = idle + 4。DUT 原来把 IDLE
当 NOP 直接穿过,导致 NEMU 停在 idle 等待中断时,DUT 已冲到 eentry,且
era 存成了 0。
首次尝试通过 mem_ready_go = 0 将 idle+4 停在 WB,但审查
Wb_reg.v 发现:当 mem_ready_go === 1'b0
时,Wb_reg 走 else
分支插入气泡(wb_pc <= 0,全清),导致 WB 变成气泡 →
wb_valid = 0 → 中断落在气泡上 →
era = 0、difftest 收不到异常事件、NEMU 永远停在 idle。
进一步追踪证实:idle 提交那拍 MEM
已是气泡(mem_pc = 0),即 idle+4 在提交 idle
时早已不在流水线中——根本无法靠”停在 WB”拿到 era。
修复:不依赖 WB 内容,改为捕获 idle+4 + 唤醒当拍注入:
1 | // ---- IDLE 等待中断 FSM ---- |
idle_wait_r:idle 提交后置 1 进入等待;中断挂起或异常时清 0。idle_era_r:idle 提交当拍捕获wb_pc + 4(此拍wb_pc = idle_pc)。idle_freeze:等待期通过wb_allow_in = ~idle_freeze回压上游、停止取指,令整条流水线停顿(NEMU 也停在 idle,保持同步)。idle_wake:被使能中断唤醒的当拍,将idle_era_r喂给 CSR 的.wb_pc,使csr_era_pc <= idle + 4。
2. 唤醒当拍中断注入
文件:core_top.v:1717-1719
问题:唤醒当拍 WB
是气泡(wb_valid = 0),正常的中断检测路径无法触发。
修复:在 trap_unit 的中断注入端口将
idle_wake 与正常 wb_has_int 合并:
1 | .wb_has_int((wb_has_int | idle_wake) && csr_crmd_ie), |
唤醒当拍在 WB(气泡)处置起 INT,触发 wb_ex → 跳
eentry、存 era、更新 crmd/prmd/estat。
3. Difftest 异常事件上报
文件:core_top.v:2712-2718
问题:唤醒当拍 WB
是气泡(wb_valid = 0),difftest 默认不上报异常事件,导致
NEMU 不会调用 raise_intr 唤醒,双方失配。
修复:在 cmt 块中显式上报唤醒事件:
1 | cmt_pc <= idle_wake ? idle_era_r : debug0_wb_pc; |
唤醒当拍
cmt_ex = 1、cmt_pc = idle + 4、cmt_ecode = 0(INT),difftest
据此调用 raise_intr 唤醒 NEMU,双方保持同步。
4. Wb_reg 保持分支
文件:Wb_reg.v:5, 171-172
问题:原 Wb_reg.v 在
mem_ready_go === 1'b0 时走 else
分支插入气泡(全清零),无法在 idle 等待期间保持 WB 内容。
修复:新增 wb_hold 输入端口,在
rst/wb_ex 之后、mem_ready_go latch 之前加入保持分支:
1 | input wire wb_hold, // idle 等待期间保持 WB 内容 |
由 idle_freeze
驱动(core_top.v:1472: .wb_hold(idle_freeze))。等待期 WB
寄存器保值,不产生气泡、不 latch 上游。同时把 mem_ready_go
中误加的 (idle_freeze) ? 1'b0 :
改回——该写法只会插气泡而非保持。
5. CACOP Hit 型 IPE 误触发修复
文件:core_top.v:1301-1304
问题:pc = 0x1c07543c 的
cacop 0x10(Hit 型)在 PLV3 被误判为
IPE。依据龙芯特权手册:Hit 型
cacop(code[4:3] == 2'b10)任意特权级可执行;仅 Store Tag /
Index 型(code[4:3] == 00/01)需 PLV0,否则 IPE。
修复:在 wb_priv_inst 的 cacop 项加
& (wb_inst[4:3] != 2'b10),把 Hit 型排除出 IPE
判定:
1 | // 注意:Hit 类 cacop(code[4:3]==2'b10)允许任意特权级执行, |
修复后 func_lab19 从 121500 推进到 132140 条,再由 idle FSM 通关。
func_advance 状态
func_advance 在本次修复后 difftest 与 golden
model(NEMU)零失配,一路跑到 syscall。仅剩子测试 n1
的片内时序自检未过(TEST_NUM = 6,score = 5,HIT
BAD TRAP)。
n1 是纯 cache 时序微基准:将 0xd0100000 设为
cached,执行 cacop 0x11(Hit-Invalidate)+
preld 预取后,计时一次 cached load 并要求快于 uncached
平均。因 preld 目前为 NOP,被计时的 load 是冷 miss,慢于
uncached → 失败。preld = NOP 对 Linux
合法(架构上合法),经确认暂不实现。
验证
| 程序 | 结果 | 指令数 |
|---|---|---|
| func_lab19 | END by Syscall ✅ | 132811 |
| func_lab15 | END by Syscall(无回归)✅ | 132056 |
| func_advance | difftest 零失配;HIT BAD TRAP 仅因 n1 时序自检 | 1398 |
修改文件清单
| 文件 | 变更 |
|---|---|
core_top.v |
IDLE 等待中断 FSM(idle_era_r 捕获 +
csr_wb_pc_eff + idle_wake 注入 + difftest
上报)、CACOP Hit 型 IPE 排除、Wb_reg 接
wb_hold、mem_ready_go 还原 |
Wb_reg.v |
新增 wb_hold 输入端口与保持分支 |