ysyxSoC
内容涵盖了 SoC 集成、AM 运行时环境移植、链接脚本精髓、启动加载器实现以及 UART 驱动开发的完整链路。
ysyxSoC 核心开发链路小结
一、SoC 集成与总线架构 (Diplomacy)
- 核心工具:基于 Rocket-Chip 的
Diplomacy框架,以 Chisel 语言实现。 - 优势:将设备接入 AXI Xbar 从传统 Verilog 的数百行端口声明,简化为仅需 2 行 Chisel 代码(
LazyModule+.node连接)。 - 关键地址映射:
- MROM:
0x2000_0000 ~ 0x2000_0fff(4KB,只读,存放启动代码)。 - SRAM:
0x0f00_0000 ~ 0x0f00_1fff(8KB,可读写,存放堆、栈、全局变量)。虽预留 16MB 地址空间,但物理仅实现 8KB,访问空洞会触发 Access Fault。
- MROM:
二、AM (抽象机) 运行时环境移植
为 riscv32e-ysyxsoc 构建 AM 后端,核心在于 TRM (图灵机) 的实现:
| API | 实现方案 |
|---|---|
putch(ch) |
轮询 UART16550 的 LSR 寄存器,等待发送队列空闲后写入 THR 寄存器。 |
halt(code) |
内嵌 ebreak 指令,让仿真环境捕获并退出。 |
heap_start/end |
返回 SRAM 中堆区的边界地址。 |
三、链接脚本精髓:VMA 与 LMA 的分离
为了支持全局变量写入(MROM 只读,SRAM 可写),必须利用链接器的 VMA(运行地址) 与 LMA(加载地址) 机制。
核心语法
.data : {
_sdata = .; /* VMA (SRAM) */
*(.data)
_edata = .;
} > SRAM AT> MROM /* VMA 在 SRAM,LMA 紧跟 MROM 代码之后 */
_sdata_lma = LOADADDR(.data); /* 导出 LMA 供启动代码使用 */
Bootloader 任务(start.S 中执行)
- 清空
.bss段(确保未初始化全局变量为 0)。 - 从
_sdata_lma(MROM 源)拷贝.data段到_sdata(SRAM 目标)。 - 设置栈指针
sp = _stack_top(SRAM 末端)。 - 跳转
main()。
四、UART16550 串口驱动(解决“16字符”魔咒)
现象:未初始化时,无论字符串多长,终端最多只显示 16 个字符(对应 FIFO 深度)。
1. 串口初始化 (uart_init)
- 设置波特率除数:
Divisor = UART_CLK / (16 * BaudRate)。 - 配置线路参数:设置为 8N1(8 位数据、无校验、1 位停止位)。
- 启用 FIFO:清空收发 FIFO,设置触发阈值。
2. 带流控的 putch
轮询 LSR (线路状态寄存器) 的 THRE (Bit 5) 位,确保发送保持寄存器(FIFO)有空位再写入,实现软硬件速度匹配,彻底杜绝丢字符。
void putch(char ch) {
while (((*(volatile uint8_t *)UART_LSR) & LSR_THRE) == 0);
*(volatile uint8_t *)UART_THR = ch;
}
五、验证与调试工具链
| 测试程序 | 验证目标 |
|---|---|
dummy |
验证最小系统取指与 ebreak 停机。 |
mem-test |
验证 8/16/32 位访存、字节选通 (WSTRB) 及小端序正确性。 |
hello |
验证串口输出与 FIFO 流控机制。 |
fib / microbench |
验证栈帧、函数调用及全局变量读写。 |
DiffTest 重新同步
- NEMU 需新增
mrom和sram物理内存数组。 - 仿真启动时调用
difftest_memcpy将 MROM 镜像同步至 NEMU。 - SRAM 无需手动同步:因 DiffTest 逐指令执行,写操作(
sb/sh/sw)会自动同步两边状态。
Access Fault 异常(建议实现)
捕获 AXI 返回的 SLVERR / DECERR(如访问 SRAM 空洞),强制 PC 跳转至复位地址(0x20000000),防止“静默死机”,便于调试。
六、编译与链接优化
- 死代码消除:利用
-ffunction-sections+--gc-sections,未被调用的函数(如未使用的printf)不会占用宝贵的 MROM 空间。 - 查看内存布局:使用
--print-map选项确认.data的 VMA 与 LMA 是否分离正确。
总结
当前 ysyxSoC 已具备一个完整最小系统所需的所有要素:
- 存储:MROM (代码) + SRAM (数据)。
- 启动:Bootloader 自动搬运数据段。
- 输出:基于中断/轮询的 UART 驱动(支持 8N1 任意波特率)。
- 调试:DiffTest + Access Fault 异常 + Verilator 波形追踪。
下一步可考虑引入更大容量的 PSRAM 或 XIP Flash,以运行更复杂的程序(如操作系统引导)。

浙公网安备 33010602011771号