项目分析文档
一生一芯 (YSYX) 全栈处理器设计项目
一、项目概览
1.1 项目简介
"一生一芯"(One Student One Chip, YSYX) 是由中国科学院大学、中国科学院计算技术研究所主导的开源免费公益性质的处理器芯片设计人才培养项目。目标是让每位参与的学生独立完成一颗 RISC-V 处理器芯片的设计,最终实现流片。
项目官网:https://ysyx.oscc.cc
1.2 合作单位
- 中国科学院大学 (UCAS)
- 中国科学院计算技术研究所 (ICT)
- 鹏城实验室 (PCL)
- 北京开源芯片研究院 (BOSC)
- 上海处理器技术创新中心
- 字节跳动、有道
- 中国开放指令生态联盟 (CRVA)
1.3 项目特色
- 全栈培养:涵盖软件模拟器 → RTL 设计 → SoC 集成 → 流片验证全流程
- 差分测试驱动:用已验证的软件模型作为参考,保证硬件设计正确性
- 开源生态:基于 RISC-V 开放指令集,使用开源 EDA 工具链
- 阶梯式学习:D → C → B 阶段递进,逐步提升设计复杂度
1.4 技术栈总览
| 类别 | 技术 |
|---|---|
| 硬件描述语言 | Verilog, SystemVerilog |
| 编程语言 | C, C++, RISC-V Assembly |
| 处理器架构 | RISC-V (RV32E/RV32IM + Zicsr) |
| 总线协议 | AMBA AXI4, AXI4-Lite |
| 仿真工具 | Verilator (周期精确仿真) |
| EDA 工具 | Yosys (逻辑综合), GTKWave (波形查看) |
| 构建系统 | GNU Make, Kconfig |
| 验证方法 | 差分测试 (DiffTest), 形式验证 (SVA) |
| 调试追踪 | ITRACE, MTRACE, FTRACE, ETRACE, IRINGBUF |
二、D 阶段 — 基础阶段 (NEMU + AM + 迷你处理器)
D 阶段的核心目标是理解计算机系统的完整执行流程:从编写程序到机器码执行,建立软硬件协同的整体认知。
D1: 支持 RV32IM 的 NEMU
目标:实现一个支持 RISC-V 32 位指令集的全系统模拟器
项目中对应的实现
NEMU (NJU Emulator) 是南京大学开发的教学用全系统模拟器,本项目对其进行了完整实现。
核心架构:
nemu/src/
├── cpu/ # CPU 执行核心
│ ├── cpu-exec.c # 指令执行主循环 (取指→译码→执行→更新PC)
│ └── iringbuf.c # 指令环形缓冲 (crash 时回溯)
├── engine/ # 执行引擎 (解释器模式)
├── isa/ # 多 ISA 实现
│ ├── riscv32/ # RV32IM 指令集实现
│ ├── riscv64/ # RV64IM 指令集实现
│ ├── mips32/ # MIPS32 实现
│ └── loongarch32r/ # LoongArch32R 实现
├── memory/ # 物理/虚拟地址管理
│ ├── paddr.c # 物理地址空间
│ └── vaddr.c # 虚拟地址翻译
├── monitor/ # 简易调试器 (sdb)
│ └── sdb/ # 单步、断点、表达式求值、监视点
└── utils/ # 反汇编、日志、计时
实现的 RV32IM 指令:
- R 型:add, sub, sll, slt, sltu, xor, srl, sra, or, and
- R 型 (M 扩展):mul, mulh, mulhsu, mulhu, div, divu, rem, remu
- I 型:addi, slti, sltiu, xori, ori, andi, slli, srli, srai, lb, lh, lw, lbu, lhu, jalr
- S 型:sb, sh, sw
- B 型:beq, bne, blt, bge, bltu, bgeu
- U 型:lui, auipc
- J 型:jal
- 系统指令:ecall, ebreak, csrrw, csrrs, csrrc, mret
调试监视器 (sdb) 功能:
si [N]— 单步执行 N 条指令info r— 查看寄存器状态x N EXPR— 扫描内存p EXPR— 表达式求值w EXPR— 设置监视点d N— 删除监视点
配置管理:使用 Kconfig (Linux 内核配置系统) 管理编译选项,支持 menuconfig 交互式配置。
关键技术点:
- 解释器模式逐条执行 guest 指令
- 支持构建为共享库 (.so),作为差分测试的 Golden Reference
- Kconfig 管理多 ISA/多功能的条件编译
D2: 程序的机器级表示
目标:理解 C 程序如何被编译为机器码,掌握 ABI、调用约定、内存布局
项目中对应的实现
- 交叉编译工具链:使用
riscv64-linux-gnu-gcc交叉编译 - 编译选项 (
abstract-machine/Makefile):CC = $(CROSS_COMPILE)gcc CFLAGS += -O2 -Wall -Werror -fno-builtin -fno-stack-protector - ABI:RV32E 使用
ilp32eABI (16 个寄存器, 简化调用约定) - 链接脚本:
scripts/linker.ld定义内存布局 (text, data, bss, heap 各段地址)
关键技术点:
- 理解 RISC-V 调用约定 (a0-a7 参数, ra 返回地址, sp 栈指针)
- ELF 文件格式解析与加载
- 反汇编工具 (
objdump) 使用
D3: AM 运行时环境
目标:实现硬件抽象层,使应用程序与具体硬件平台解耦
项目中对应的实现
Abstract-Machine (AM) 提供 5 层抽象 API:
应用程序 (am-kernels: CoreMark, 贪吃蛇, NES模拟器...)
│
┌───────▼───────┐
│ Abstract-Machine │ 统一 API 接口
│ (am.h) │
└───────┬───────┘
│
┌───────┬───────┼───────┬───────┬───────┐
▼ ▼ ▼ ▼ ▼ ▼
NEMU NPC ysyxSoC QEMU Spike Native
(模拟器) (RTL) (FPGA) (虚拟机) (参考) (Linux)
五层抽象 API (am/include/am.h):
| 层级 | 名称 | API | 说明 |
|---|---|---|---|
| TRM | 图灵机 | heap, putch(), halt() |
最基本的计算能力 |
| IOE | I/O 扩展 | ioe_init(), ioe_read(), ioe_write() |
设备抽象 |
| CTE | 上下文扩展 | cte_init(), yield(), kcontext() |
中断/异常/上下文切换 |
| VME | 虚拟内存 | vme_init(), map(), protect() |
页表/地址空间 |
| MPE | 多处理 | mpe_init(), cpu_count() |
多核支持 |
NPC 平台配置 (scripts/riscv32e-npc.mk):
COMMON_CFLAGS += -march=rv32e_zicsr -mabi=ilp32e
LDFLAGS += -melf32lriscv
AM_SRCS += riscv/npc/libgcc/div.S # 软件除法
riscv/npc/libgcc/muldi3.S # 软件乘法
klib 最小内核库:提供 memcpy, strlen, printf 等基本函数,不依赖操作系统。
关键技术点:
- 裸金属编程,无 OS 依赖
- 同一份 CoreMark 代码可运行于模拟器/RTL/FPGA
- 启动代码 (RISC-V 汇编) 完成栈初始化和跳转 main
D4: 用 RTL 实现迷你 RISC-V 处理器
目标:用 Verilog 实现最基本的 RISC-V 处理器核,能执行简单程序
项目中对应的实现
NPC (New Processor Core) 的初始版本,实现核心数据通路:
// npc/vsrc/top.v — 顶层模块
module top (
input clock,
input reset
);
// 流水线各级互联信号
wire [31:0] instr; // IFU → IDU
wire [31:0] pc; // BRU → IFU
wire [31:0] rs1, rs2; // RegFile → EXU
wire [31:0] imm; // IDU → EXU
wire [31:0] exu_res; // EXU → LSU/WBU
wire [31:0] lsu_res; // LSU → WBU
...
endmodule
核心模块:
| 模块 | 文件 | 功能 |
|---|---|---|
| RegFile | regfile.v |
16 个通用寄存器 (RV32E) |
| ALU | alu.v |
算术逻辑运算 |
| IDU | idu/idu.v |
指令译码,生成控制信号 |
| EXU | exu.v |
执行运算 |
| BRU | bru.v |
分支跳转决策 |
Verilator 仿真环境 (csrc/main.cpp):
// 主仿真循环
while (!contextp->gotFinish()) {
top->clock = !top->clock;
step_and_dump_wave(); // eval + 时间推进 + VCD 记录
}
关键技术点:
- Verilog RTL 设计基础
- Verilator 将 Verilog 编译为 C++ 进行仿真
- DPI-C 接口打通 Verilog 与 C++ 的数据交互
D5: 设备和输入输出
目标:实现 I/O 设备模拟和硬件外设接口
项目中对应的实现
NEMU 中的设备模拟 (nemu/src/device/):
| 设备 | 文件 | 接口类型 | 功能 |
|---|---|---|---|
| 串口 | serial.c |
MMIO | 字符输出 |
| 定时器 | timer.c |
MMIO | 系统时钟 |
| 键盘 | keyboard.c |
MMIO | 扫描码输入 |
| VGA | vga.c |
MMIO | 帧缓冲显示 |
| 音频 | audio.c |
MMIO | 音频 DMA |
NPC 中的硬件外设 (npc/vsrc/peripheral/):
| 模块 | 接口 | 功能 |
|---|---|---|
axi_lite_uart.v |
AXI-Lite | 串口输出 |
axi_lite_clint.v |
AXI-Lite | 机器定时器 (mtime/mtimecmp) |
关键技术点:
- MMIO (Memory-Mapped I/O) 设备访问方式
- 设备寄存器读写语义
- 中断触发与处理流程
三、C 阶段 — 进阶阶段 (完善处理器 + 系统能力)
C 阶段的核心目标是将处理器从"能跑"提升到"能用",增加异常处理、调试基础设施,支持运行 RT-Thread 等实时操作系统。
C1: 工具和基础设施
目标:搭建完善的开发、调试、验证工具链
项目中对应的实现
差分测试框架 (DiffTest):
┌─────────────┐ 每条指令提交后 ┌─────────────┐
│ NPC │ ──────────────────── ▶ │ NEMU │
│ (DUT) │ │ (.so) │
│ Verilator仿真│ │ 参考模型 │
└──────┬──────┘ └──────┬──────┘
│ │
▼ ▼
DUT 寄存器/PC/CSR REF 寄存器/PC/CSR
│ │
└─────────── 逐一对比 ─────────────────┘
│
┌───────┴───────┐
│ 一致 → 继续 │
│ 不一致 → 报错 + 波形│
└───────────────┘
实现代码 (npc/csrc/):
// difftest.cpp 核心逻辑
bool difftest_check() {
regfile ref = get_ref_regs(); // 从 NEMU .so 获取参考状态
regfile dut = pack_dut_regfile(...); // 从 RTL 获取 DUT 状态
return checkregs(&ref, &dut); // 逐寄存器对比
}
追踪系统 (Kconfig 可配):
| Trace | 启用方式 | 用途 |
|---|---|---|
| ITRACE | CONFIG_ITRACE=y |
打印每条指令的 PC、机器码、反汇编 |
| MTRACE | CONFIG_MTRACE=y |
监控指定地址范围的读写 |
| FTRACE | CONFIG_FTRACE=y |
跟踪函数调用/返回 |
| ETRACE | CONFIG_ETRACE=y |
记录异常触发 |
| IRINGBUF | CONFIG_IRINGBUF=y |
环形缓冲,crash 时打印最近 N 条指令 |
波形调试:
make run WAVE=1 # 生成 VCD 波形
make wave # GTKWave 打开波形查看
关键技术点:
- DPI-C 接口设计 (Verilog 导出信号 → C++ 读取)
- 共享库动态加载 (dlopen/dlsym 加载 NEMU .so)
- 条件编译的宏技巧 (
IFDEF(DIFFTEST_ON, ...))
C2: 支持 RV32E 的单周期 NPC
目标:完成完整的单周期处理器,通过所有 CPU 测试
项目中对应的实现
单周期意味着每条指令在一个时钟周期内完成取指→译码→执行→访存→写回。
处理器数据通路:
┌──────────────────────────────────────────────────┐
│ 一个时钟周期 │
│ │
PC ──▶ IFU(取指) ──▶ IDU(译码) ──▶ EXU(执行) ──▶ WBU(写回) │
│ │ │ │
│ └── Memory ◀──────── LSU(访存) ──┘ │
│ │
└──── BRU(分支) ◀─── zero flag ─────────────────────┘
指令译码 (vsrc/idu/):
idu_normal.v— 处理算术、逻辑、访存、跳转指令idu_system.v— 处理 CSR、ecall、mret、fence.i 等系统指令idu.v— 顶层译码器,合并两部分输出
寄存器堆 (vsrc/regfile.v):
- 16 个 32-bit 通用寄存器 (RV32E 规范)
- 双读端口 + 单写端口
- 零号寄存器硬连线为 0
关键技术点:
- 组合逻辑实现所有指令的执行
- 控制信号 (exu_opt, lsu_opt) 驱动数据通路选择
- am-kernels/tests/cpu-tests 作为正确性回归测试
C3: 调试技巧
目标:掌握硬件调试方法论,能高效定位和修复 RTL bug
项目中对应的实现
多层次调试手段:
| 层级 | 方法 | 工具 |
|---|---|---|
| 行为级 | NEMU 单步调试 | sdb (内置调试器) |
| RTL 级 | 波形分析 | GTKWave + VCD |
| 接口级 | DiffTest 对比 | NEMU .so + DPI-C |
| 统计级 | 性能计数器 | 内置 PFC |
错误定位流程:
- DiffTest 发现寄存器不一致 → 打印出错的指令 PC
- ITRACE/IRINGBUF 查看出错前的指令序列
- GTKWave 查看对应时刻的信号波形
- 定位是译码错误、执行错误还是访存错误
C4: ELF 文件和链接
目标:理解可执行文件格式、符号解析、链接过程
项目中对应的实现
链接脚本 (abstract-machine/scripts/linker.ld):
- 定义
.text(代码段) 起始地址 =0x80000000 - 定义
.data,.bss,_heap_start等段布局 - 导出
_start符号作为入口点
ELF 加载流程:
- 交叉编译生成 ELF → objcopy 转为纯二进制 (.bin)
- 仿真时通过命令行
--img xxx.bin加载到模拟内存 - PC 初始化指向
INST_START(0x80000000)
FTRACE (函数追踪) 利用 ELF 符号表实现函数调用/返回的追踪。
C5: 异常处理和 RT-Thread
目标:实现 RISC-V 特权级架构,支持运行实时操作系统
项目中对应的实现
CSR 寄存器 (vsrc/csrfile.v):
| CSR | 地址 | 功能 |
|---|---|---|
| mtvec | 0x305 | 异常入口地址 |
| mepc | 0x341 | 异常返回地址 |
| mcause | 0x342 | 异常原因码 |
| mstatus | 0x300 | 机器状态 (MIE/MPIE) |
异常处理单元 IRU (vsrc/iru.v):
ecall 触发:
1. mepc ← 当前 PC
2. mcause ← 异常原因 (environment call from M-mode = 11)
3. mstatus.MPIE ← mstatus.MIE; mstatus.MIE ← 0
4. PC ← mtvec
mret 返回:
1. PC ← mepc
2. mstatus.MIE ← mstatus.MPIE
CTE (Context Extension) 在 AM 中的实现:
cte_init()— 注册异常处理函数,设置 mtvecyield()— 触发 ecall,用于上下文切换kcontext()— 创建内核线程上下文
关键技术点:
- RISC-V Machine-mode 特权级
- 异常向量表 (mtvec) 机制
- 支持 RT-Thread yield/调度
四、B 阶段 — 高级阶段 (总线 + SoC + 流水线 + 优化)
B 阶段的核心目标是将处理器从"教学级"提升到"工程级",实现总线互联、SoC 集成、流水线、缓存等高级特性,最终具备流片能力。
B1: 总线
目标:实现标准 AXI4 总线协议,支持多 Master/多 Slave 互联
项目中对应的实现
AXI4 总线子系统 (npc/vsrc/amba/):
┌─────┐ ┌─────┐
│ IFU │ │ LSU │ ← 2 个 AXI Master
│(取指)│ │(访存)│
└──┬──┘ └──┬──┘
│ │
▼ ▼
┌──────────────────────────────┐
│ AXI Interconnect │ (arbiter + demux)
│ axi_demux.sv + arbiter.v │
└──┬────────┬────────┬────────┘
│ │ │
▼ ▼ ▼
┌─────┐ ┌──────┐ ┌──────┐ ┌──────┐
│SRAM │ │ICache│ │CLINT │ │ UART │ ← 多个 AXI Slave
└─────┘ └──────┘ └──────┘ └──────┘
关键模块:
| 模块 | 文件 | 功能 |
|---|---|---|
| AXI Demux | axi_demux.sv |
根据地址将请求分发到不同 Slave |
| Arbiter | arbiter.v |
Round-Robin 仲裁多个 Master 请求 |
| AXI Interconnect | axi_interconnect.v |
完整互联 (N×M 交叉开关) |
| AXI→AXI-Lite 桥 | axi_axil_adapter.v |
协议降级转换 |
| Access Fault | axi_access_fault.v |
总线异常检测 |
| AXI Interface | axi_intf.sv |
SystemVerilog interface 定义 |
AXI4 协议五通道:
- AW (Write Address) — 写地址通道
- W (Write Data) — 写数据通道
- B (Write Response) — 写响应通道
- AR (Read Address) — 读地址通道
- R (Read Data) — 读数据通道
地址解码 (vsrc/libs/addr_decode.sv):
// 内存映射规则
localparam rule_t [NoRules-1:0] addr_map = '{
'{idx: 1, start_addr: 32'h30000000, end_addr: 32'h40000000}, // Flash
'{idx: 0, start_addr: 32'ha0000000, end_addr: 32'hc0000000}, // SDRAM
'{idx: 1, start_addr: 32'h0f000000, end_addr: 32'h10000000} // SRAM
};
关键技术点:
- AXI4 握手协议 (valid/ready 对)
- 突发传输 (burst) 支持
- 写地址/写数据解耦
- 乱序完成 (通过 AXI ID)
B2: SoC 计算机系统
目标:将处理器核集成到完整的 SoC 中,对接真实外设
项目中对应的实现
项目支持两种 SoC 模式:
模式 1:独立仿真 (ARCH=riscv32e-npc)
CPU Core ←→ AXI Bus ←→ DPI-C 内存模型 (C++ 主机内存)
模式 2:ysyxSoC 集成 (ARCH=riscv32e-ysyxsoc)
┌──────────────────────────────────────────────────────┐
│ ysyxSoC │
│ │
│ ┌────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ NPC │←──▶│ AXI Bus │←──▶│ Flash │ │
│ │ CPU │ │ │ │ PSRAM │ │
│ │ Core │ │ │ │ UART16550 │ │
│ └────────┘ │ │ │ SPI │ │
│ └──────────┘ │ GPIO │ │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────┘
内存映射:
| 地址范围 | 外设 | 大小 |
|---|---|---|
0x20000000 – 0x20000FFF |
MROM | 4 KB |
0x0F000000 – 0x0FFFFFFF |
SRAM | 16 MB |
0x30000000 – 0x3FFFFFFF |
Flash | 256 MB |
0x80000000 – 0x9FFFFFFF |
PSRAM/主内存 | 512 MB |
SoC 对接要求:
- 顶层模块暴露标准 AXI4 Master 接口 (
io_master_aw*,io_master_w*,io_master_b*,io_master_ar*,io_master_r*) - 支持条件编译
ifdef YSYXSOC切换 SoC/独立模式 - NVBoard 虚拟 FPGA 验证板
关键技术点:
- 处理器核对外接口标准化 (AXI Master)
- 多模式兼容 (仿真 vs FPGA)
- 启动地址配置 (Flash: 0x30000000 vs RAM: 0x80000000)
B3: 时序分析和优化
目标:确保设计满足时序约束,能在目标频率下正确工作
项目中对应的实现
Yosys 逻辑综合 + STA (Makefile syn 目标):
make syn # 调用 yosys-sta 进行综合
# 目标频率: 100 MHz
# SDC 约束文件: npc/top.sdc
优化手段:
- Valid/Ready 握手协议允许各级独立阻塞,不需要全局 stall
- Spill Register (
libs/spill_register.sv) 用于切断关键路径 - AXI Demux 的
SPILL_AW/SPILL_AR选项插入流水寄存器
关键技术点:
- 静态时序分析 (STA) 概念
- 关键路径识别与优化
- 面积/时序/功耗 trade-off
B4: 性能优化和简易缓存
目标:通过缓存和微架构优化提升处理器性能
项目中对应的实现
指令缓存 ICache (vsrc/peripheral/axi_icache.v):
- AXI4 接口 (上游连接 IFU,下游连接主存)
- 支持
fence.i指令触发缓存无效化 - Cache 命中时单周期返回指令
性能计数器 (csrc/main.cpp):
// 仿真时统计的性能指标
printf("CPU IPC: %f\n", total_inst / (time / 2.0)); // 每周期指令数
printf("CPU CPI: %f\n", (time / 2.0) / total_inst); // 每指令周期数
printf("ICACHE Hit Rate: %f\n", cache_hit_rate); // 缓存命中率
printf("ICACHE AMAT: %f\n", acc_time + (1-hit_rate)*miss_penalty); // 平均访存时间
printf("IDU Cal CPI: %f\n", inst_time[0] / idu_cal_type); // 计算指令 CPI
printf("IDU Mem CPI: %f\n", inst_time[1] / idu_mem_type); // 访存指令 CPI
printf("IDU Jump CPI: %f\n", inst_time[2] / idu_jump_type); // 跳转指令 CPI
性能统计分类:
| 指标 | 含义 |
|---|---|
| IPC | Instructions Per Cycle |
| CPI | Cycles Per Instruction |
| Cache Hit Rate | 缓存命中比例 |
| AMAT | Average Memory Access Time |
| TMT | True Miss Penalty Time |
| Per-type CPI | 按指令类型 (计算/访存/跳转/CSR) 分别统计 |
关键技术点:
- Cache 组织结构 (直接映射/组相联)
- Cache 一致性 (fence.i)
- Amdahl 定律指导优化方向
B5: 流水线处理器
目标:将单周期处理器改造为流水线设计,提升主频和吞吐量
项目中对应的实现
流水线架构 (Valid/Ready 握手):
┌─────┐ valid/ready ┌─────┐ valid/ready ┌─────┐ valid/ready ┌─────┐ valid/ready ┌─────┐
│ IFU │ ────────────▶ │ IDU │ ────────────▶ │ EXU │ ────────────▶ │ LSU │ ────────────▶ │ WBU │
│ │ ◀──────────── │ │ ◀──────────── │ │ ◀──────────── │ │ ◀──────────── │ │
└─────┘ └─────┘ └─────┘ └─────┘ └─────┘
ifu_valid idu_valid exu_valid lsu_valid
idu_ready exu_ready lsu_ready wbu_ready
握手信号 (vsrc/top.v):
// 流水线级间握手
wire ifu_valid, idu_ready; // IFU → IDU
wire idu_valid, exu_ready; // IDU → EXU
wire exu_valid, lsu_ready; // EXU → LSU
wire lsu_valid, wbu_ready; // LSU → WBU
流水线特点:
- 弹性流水线:每级可独立阻塞 (如 ICache Miss 时 IFU 阻塞不影响后级已有数据的处理)
- 无 stall 信号:用 valid/ready 对代替全局 stall,更灵活
- 数据前递隐式:单发射顺序执行,WBU 写回后下一条才读取
与总线的交互:
- IFU 通过 AXI Master 读取指令 (可能多周期等待)
- LSU 通过 AXI Master 读写数据 (可能多周期等待)
- 非访存指令在 LSU 阶段直通 (lsu_opt 为 NOP)
关键技术点:
- 流水线冒险 (数据冒险、控制冒险) 处理
- 分支预测/延迟槽 (当前设计为等待分支决议后更新 PC)
- 流水线刷新 (fence.i / ecall / mret)
五、验证 & 测试生态
5.1 测试程序集 (am-kernels)
| 类别 | 路径 | 说明 |
|---|---|---|
| CPU 测试 | am-kernels/tests/cpu-tests/ |
每条指令的正确性验证 |
| AM 测试 | am-kernels/tests/am-tests/ |
抽象层 API 功能测试 |
| ALU 测试 | am-kernels/tests/alu-tests/ |
运算单元专项测试 |
| CoreMark | am-kernels/benchmarks/coremark/ |
工业标准性能基准 |
| Dhrystone | am-kernels/benchmarks/dhrystone/ |
经典整数性能基准 |
| MicroBench | am-kernels/benchmarks/microbench/ |
微基准测试 |
5.2 演示应用
| 程序 | 说明 | 验证的能力 |
|---|---|---|
| hello | 最简输出 | TRM 基本功能 |
| snake | 贪吃蛇 | IOE 键盘 + VGA |
| typing-game | 打字游戏 | IOE 定时器 + 键盘 |
| litenes | NES 模拟器 | 复杂计算 + 图形 |
| bad-apple | 视频播放 | 大量内存访问 |
| thread-os | 线程 OS | CTE 上下文切换 |
5.3 形式验证
npc/formal/
├── CacheTest.sv # ICache 属性断言
├── Sub.sv # 子模块属性断言
└── axi_ram.v # AXI RAM 模型 (用于形式验证环境)
六、构建命令速查
# === NEMU ===
cd nemu
make menuconfig # 配置编译选项
make # 编译 NEMU
make run # 运行 NEMU
# === NPC ===
cd npc
make # 编译 NPC (Verilator)
make run # 运行仿真
make run DIFFTEST=1 # 启用差分测试
make run WAVE=1 # 记录波形
make run MAXCYCLE=100000 # 限制仿真周期
make wave # GTKWave 打开波形
make syn # Yosys 逻辑综合 + STA
# === AM-Kernels (以 cpu-tests 为例) ===
cd am-kernels/tests/cpu-tests
make ARCH=riscv32e-npc run # 在 NPC 上运行 CPU 测试
make ARCH=riscv32-nemu run # 在 NEMU 上运行 CPU 测试
七、简历描述 (按阶段组织)
综合版 (推荐)
一生一芯 — RISC-V 全栈处理器设计 | Verilog/SV, C/C++, RISC-V Assembly
- 实现全系统指令集模拟器 NEMU,支持 RV32IM/RV64IM/x86/MIPS32,含 MMU、5 种外设模拟、多级调试追踪系统
- 使用 Verilog/SystemVerilog 独立设计 RV32E 多级流水线处理器 (IFU-IDU-EXU-LSU-WBU),采用 Valid/Ready 弹性流水线架构
- 设计完整 AXI4 片上总线系统 (Demux、Arbiter、AXI-Lite Bridge),实现 ICache 及 fence.i 一致性维护
- 实现 RISC-V Machine-mode 特权级 (ecall/mret/CSR),支持运行 RT-Thread RTOS
- 搭建基于 Verilator 的 SoC 仿真平台,实现 DPI-C 差分测试框架 (RTL vs NEMU 逐指令对比)
- 使用 Yosys 完成逻辑综合 (100MHz 目标),通过性能计数器分析 IPC/CPI/Cache AMAT 指导优化
- 设计 Abstract-Machine 硬件抽象层,成功运行 CoreMark/Dhrystone 基准测试及 NES 模拟器
突出 D 阶段 (偏系统软件)
- 实现支持多 ISA 的全系统模拟器,采用 Kconfig 管理编译配置,含解释器引擎、设备模型、简易调试器
- 设计 Abstract-Machine 五层硬件抽象 (TRM/IOE/CTE/VME/MPE),实现同一应用在模拟器/RTL/FPGA 间无缝迁移
突出 C 阶段 (偏验证调试)
- 搭建差分测试框架,通过 DPI-C 接口实现 RTL 与软件参考模型的逐指令状态校验
- 实现多层追踪系统 (ITRACE/MTRACE/FTRACE/IRINGBUF),支持高效硬件 bug 定位
突出 B 阶段 (偏芯片设计)
- 设计完整 AXI4 总线互联 (多 Master 仲裁、地址解码、协议桥接),支持 SoC 集成
- 实现 ICache 并通过 fence.i 维护一致性,优化后 CPI 显著降低
- 完成 Yosys 逻辑综合与 STA,达到 100MHz 时序收敛
八、面试技术要点
处理器设计
| 问题 | 要点 |
|---|---|
| 为什么用 RV32E? | 16 寄存器,面积小,复杂度低,适合教学迭代 |
| Valid/Ready vs 全局 Stall? | 弹性流水线,各级独立阻塞,天然支持不等延迟 |
| AXI4 为什么分五通道? | 读写解耦、突发传输、乱序完成、工业标准 |
| ICache fence.i 怎么做? | 收到 fence.i 时无效化所有 cache line |
| 差分测试的局限? | 需要参考模型,时序行为无法覆盖,仅验证功能正确性 |
系统软件
| 问题 | 要点 |
|---|---|
| NEMU 如何支持多 ISA? | 分层设计,ISA 相关代码隔离在 src/isa/ 目录 |
| AM 如何实现平台无关? | 编译时选择 $ARCH,链接不同的平台实现代码 |
| ecall 的完整流程? | mepc←PC, mcause←原因, mstatus 保存中断状态, PC←mtvec |
验证方法
| 问题 | 要点 |
|---|---|
| DiffTest 如何同步? | 每条指令提交 (commit) 后对比,确保一一对应 |
| 波形调试 vs printf? | 波形可看并行信号时序关系,printf 只能看串行事件 |
| 形式验证 vs 仿真? | 仿真覆盖常见路径,形式验证穷举状态空间,互补 |
参考来源:一生一芯官网 | OSCPU GitHub | 项目源码分析
文档生成时间:2026 年 6 月

浙公网安备 33010602011771号