Categories: 硬件设计.

概述

本次更新修复了 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ---- IDLE 等待中断 FSM ----
wire wb_is_idle_commit = wb_valid & (wb_inst[31:15]==17'h0C91) & ~wb_ex & ~wb_need_cancel;
wire idle_int_pending = |(csr_estat_is & csr_ecfg_lie);
reg idle_wait_r;
reg [31:0] idle_era_r;

always @(posedge clk) begin
if (rst) idle_wait_r <= 1'b0;
else if (idle_int_pending) idle_wait_r <= 1'b0; // 被中断唤醒
else if (wb_ex) idle_wait_r <= 1'b0; // 异常冲刷
else if (wb_is_idle_commit) idle_wait_r <= 1'b1; // idle 提交,进入等待
end

always @(posedge clk) begin
if (rst) idle_era_r <= 32'b0;
else if (wb_is_idle_commit) idle_era_r <= wb_pc + 32'd4; // 捕获 idle+4
end

wire idle_freeze = idle_wait_r & ~idle_int_pending; // 冻结流水线
wire idle_wake = idle_wait_r & idle_int_pending; // 唤醒当拍
wire [31:0] csr_wb_pc_eff = idle_wake ? idle_era_r : wb_pc;
  • 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
2
3
cmt_pc    <= idle_wake ? idle_era_r : debug0_wb_pc;
cmt_ex <= (wb_valid && wb_ex) || idle_wake;
cmt_ecode <= idle_wake ? 6'h00 : wb_ecode; // 唤醒为中断 INT(0)

唤醒当拍 cmt_ex = 1cmt_pc = idle + 4cmt_ecode = 0(INT),difftest 据此调用 raise_intr 唤醒 NEMU,双方保持同步。


4. Wb_reg 保持分支

文件Wb_reg.v:5, 171-172

问题:原 Wb_reg.vmem_ready_go === 1'b0 时走 else 分支插入气泡(全清零),无法在 idle 等待期间保持 WB 内容。

修复:新增 wb_hold 输入端口,在 rst/wb_ex 之后、mem_ready_go latch 之前加入保持分支:

1
2
3
4
5
6
7
8
input wire wb_hold,        // idle 等待期间保持 WB 内容

// ...

end else if(wb_hold) begin
// idle 等待中断:保持 WB 现有内容,不 latch 上游、不产生气泡
end else if(!(mem_ready_go===1'b0))begin
// 正常 latch

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 = 0x1c07543ccacop 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
2
3
4
5
6
7
// 注意:Hit 类 cacop(code[4:3]==2'b10)允许任意特权级执行,
// 仅 Store Tag / Index 类(code[4:3]==00/01)需 PLV0。
wire wb_priv_inst = (wb_inst[31:24] == 8'h04)
| ((wb_inst[31:22] == 10'h018) & (wb_inst[4:3] != 2'b10))
| (wb_inst[31:15] == 17'h0C91)
| (wb_inst[31:26]==6'h01 & wb_inst[25:22]==4'h9 & wb_inst[21:20]==2'h0
& (wb_inst[19:15]==5'h10 | wb_inst[19:15]==5'h13));

修复后 func_lab19 从 121500 推进到 132140 条,再由 idle FSM 通关。


func_advance 状态

func_advance 在本次修复后 difftest 与 golden model(NEMU)零失配,一路跑到 syscall。仅剩子测试 n1 的片内时序自检未过(TEST_NUM = 6score = 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_regwb_holdmem_ready_go 还原
Wb_reg.v 新增 wb_hold 输入端口与保持分支