Situation(背景)
AnxChip 是一个基于 LoongArch32(LA32R)指令集自行设计的六级流水线 CPU,面向龙芯杯(NSCSCC)竞赛与 Linux 内核仿真。项目从零开始完成微架构设计、RTL 编码、功能验证到 Linux 启动,历时数月迭代。
Task(任务)
- 设计并实现完整支持 LA32R 指令集的六级流水线处理器
- 支持虚拟内存(TLB)、Cache(I/D-Cache)、异常中断、特权指令
- 通过 Chiplab 仿真环境的 NEMU difftest 全部功能测试
- 推进 Linux 内核仿真至用户态 init
- 目标主频 70–75MHz
Action(行动)
微架构设计
六级流水线:IF → ID → EXE1 → EXE2 → MEM → WB
| 流水级 | 核心职责 |
|---|---|
| IF | PC 生成、I-Cache 取指、BTB 分支预测 |
| ID | 译码、寄存器读取、冒险检测、分支判定 |
| EXE1 | ALU 运算、单周期 32×32 乘法、TLB 查找 |
| EXE2 | 数据地址计算、D-Cache 读写、Store 提交 |
| MEM | D-Cache 响应处理、AXI 总线访问 |
| WB | 指令提交、CSR 写入、异常仲裁、中断响应 |
存储子系统: - 2 路组相联 I-Cache / D-Cache(各
16KB),阻塞式状态机 - D-Cache 采用 Write-Back 策略 - 16 项全相联 TLB,3
端口并行查找(I-TLB / D-TLB / TLBSRCH) - AXI4 总线接口(I/D 共享
sram_axi_bridge)
冒险处理: - RAW:4 级转发(EXE1 / EXE2 / MEM / WB → ID)+ Load-Use 停顿 - 控制冒险:BTB 预测 + 分支冲刷 - 结构冒险:I/D Cache AXI 仲裁
验证方法
采用 Verilator + NEMU difftest 协同仿真:DUT(RTL)与 REF(NEMU 参考模型)逐指令比对,任何寄存器、内存、CSR 状态差异即刻报错定位。
关键技术挑战与解决
1. I-Cache 一致性与 RAW 冒险
I-Cache 响应重放导致取指空洞,配合 RAW
转发路径的时序窗口产生数据不一致。通过修复 I-Cache
状态机保持逻辑(S_HIT_RESP / S_REF_RESP
无请求时保持)和转发 MUX 时序解决。
2. LAB15 流水线挂死
pc_reg.v 中分支重定向嵌套在
casez(if_allow_in) 内,当 IF 阶段因 I-Cache Miss 停顿时
pc_br_taken 脉冲被错过。将分支重定向移出 casez
作为独立优先级分支修复。
3. LAB19 IDLE 等待中断
LoongArch 语义下 IDLE 执行后处理器停止取指进入等待态,被中断唤醒后在
idle+4 处响应。原设计把 IDLE 当 NOP
直接穿过。最终方案:捕获 idle_era_r = wb_pc + 4,通过
idle_freeze 冻结流水线,idle_wake
唤醒当拍注入中断并显式上报 difftest。
4. 中断精确化
从 ID 段采样中断改为 WB
边界实时判定(wb_int_live),解决 csrxchg 使能
IE 后中断响应延迟问题。对 Store
指令延迟中断到下一条指令边界(~wb_dram_we),避免”Store
已写内存但中断未同步至 NEMU”的失配。
5. 外部中断通路
修复硬件中断线硬连 0
的缺陷(hw_int_in = intrpt),统一外部中断走 ESTAT.IS &
ECFG.LIE 屏蔽路径,修正 TVAL 读回在到期边沿的回绕 bug。
6. Linux 启动推进
修复 PGD 系列 CSR(PGDL/PGDH/PGD)、TLBIDX 可写域掩码、SAVE2/SAVE3 拷贝粘贴 bug、TVAL 只读同步机制等问题后,Linux 内核仿真推进至用户态 init。
性能优化
- S_LOOKUP 状态分离:I-Cache Tag 查找与命中处理分离,缩短关键路径
- Block RAM
映射:
(* ram_style = "block" *)综合 pragma 引导 Cache 存储体映射到块 RAM - 分支重定向收窄:fall-through 分支不再触发无谓冲刷
Result(结果)
| 里程碑 | 状态 |
|---|---|
| 全部 58 个功能测试点(func_lab1–lab19 + func_advance) | ✅ 通过 |
| 性能测试(coremark 等) | ✅ 70MHz 全部通过 |
| Linux 内核仿真 | ✅ 推进至用户态 init |
| func_advance | difftest 零失配(仅 n1 时序自检未过,preld=NOP 合法) |
最终规格:
| 参数 | 值 |
|---|---|
| 指令集 | LoongArch32 (LA32R) |
| 流水线深度 | 6 级 |
| 主频 | 70MHz |
| I-Cache | 16KB,2 路组相联 |
| D-Cache | 16KB,2 路组相联,Write-Back |
| TLB | 16 项全相联,3 端口并行 |
| 总线 | AXI4(I/D 共享 bridge) |
| 分支预测 | BTB |
项目仓库
RTL 源码已开源:GitHub - SerenaLina/AnxChips
仓库包含全部 Verilog 源文件(rtl/*.v),涵盖
core_top.v(顶层)、icache_two_way.v、dcache_two_way.v、tlb.v、csr.v、interrupt.v、trap_unit.v、pc_reg.v、alu.v
等模块。