一、项目背景
Abstract Machine(简称AM)是香山(XiangShan)项目中编写软件测试用例使用的软件库,作为香山高性能 RISC-V 处理器项目的重要组成部分,AM 通过将 API 端口的抽象,使软件程序映射到处理器的指定架构上执行。
二、总体开发框架介绍
该项目将 C 源码和架构实现 api 解耦,通过预定义 ABI ,实现一套程序在不同架构运行。(1)程序框架
▲
多平台支持:支持香山处理器的多种配置(DDR、Flash 启动)以及其他 RISC-V 平台(NEMU、果壳、香山)
▲
灵活的架构配置:采用分层配置系统,通过ISA-PLATFORM格式实现架构解耦
▲
完整的工具链集成:支持 GNU 工具链和扩展指令集( Zba、 Zbb、Zbc 等加密扩展)
▲
模块化设计:清晰的源码组织结构,便于扩展和维护
▲
自动化构建:提供完整的 Makefile 构建系统,支持依赖管理和增量编译
nexus-am/├── am/ # AM核心框架│ ├── arch/ # 架构配置文件│ │ ├── riscv64-xs.mk│ │ ├── riscv64-xs-flash.mk│ │ └── isa/│ │ └── riscv64.mk│ └── src/ # 平台相关源码│ ├── xs/ # 香山平台实现│ ├── nemu/ # NEMU仿真器支持│ └── noop/ # NOOP处理器支持├── apps/ # 应用程序示例│ └── coremark/├── libs/ # 库支持│ └── klib/ # 内核库├── Makefile.check # 环境检查├── Makefile.compile # 编译规则└── Makefile.app # 应用构建模板
(2)使用场景
(3)核心功能
Abstract Machine 是一个最小化、模块化、机器无关的硬件抽象层,它只提供实现操作系统所需的最基本机制:
- 物理内存和直接执行("图灵机")
- 基本的输入输出设备模型(I/O扩展)
- 中断/异常和处理器上下文管理(上下文扩展)
- 虚拟内存和保护(虚拟内存扩展)
- 多处理器支持(多处理扩展)
三、源码解析
(1)核心 api 实现
本节主要介绍核心 api 的实现位置,实现基础的处理器交互功能 api 如下:
1 TRM (Turing Machine) - 图灵机扩展
最基础的计算环境,提供:
putch(): 输出单个字符到调试终端
halt(): 停止执行
// 示例:最简单的AM程序#include <am.h>int main(const char *args) {putch('H');putch('i');putch('!');putch('\n');halt(0);return 0;}
putch(char ch): 向调试终端输出单个字符,是最基本的输出方式
halt(int code): 停止程序执行,参数为退出码
TRM 还提供了堆区的起始和结束地址,让程序可以使用动态内存分配。halt()的实现通过调用nemu_trap()宏来触发一个内联汇编指令,实现验证环境中程序的自定义终止。
2 IOE (I/O Extension) - 输入输出扩展
提供基本的设备抽象:
- 键盘输入
- 显示输出
- 时钟计时器
- 音频设备
IOE 提供了基本的设备抽象,包括键盘输入、显示输出、时钟计时器和音频设备。例子如下
// 设备抽象示例typedef struct {int width, height; // 屏幕尺寸} GPU_Config;// 键盘输入示例bool keyboard_check() {AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);if (ev.keydown) {printf("Key %d pressed\n", ev.keycode);return true;}return false;}// 时钟读取示例uint64_t get_time() {AM_TIMER_UPTIME_T uptime =io_read(AM_TIMER_UPTIME);return uptime.us; // 返回微秒级时间}
3 CTE (Context Extension) - 上下文扩展
处理中断、异常和系统调用:
- 中断/异常处理机制
- 上下文切换
- 系统调用接口
// 中断处理器注册bool cte_init(Context *(*handler)(Event ev, Context *ctx)) {// 注册中断处理函数// handler: 用户提供的中断处理函数// ev: 事件类型(中断、异常、系统调用等)// ctx: 保存的上下文信息user_handler = handler;return true;}// Context结构体包含了所有寄存器状态typedef struct Context {uintptr_t gpr[32]; // 通用寄存器 (RISC-V)uintptr_t mcause; // 异常原因uintptr_t mstatus; // 状态寄存器uintptr_t mepc; // 异常PC} Context;// 事件处理示例Context* event_handler(Event ev, Context *ctx) {switch (ev.event) {case EVENT_SYSCALL:// 处理系统调用break;case EVENT_TIMER:// 处理时钟中断break;case EVENT_EXTERNAL:// 处理外部中断break;}return ctx;}
4 MPE (Multiprocessing Extension) - 多处理器扩展
支持多核处理器:
- 多处理器初始化
- 处理器间通信
- 共享内存管理
// 初始化多处理器环境void _mpe_init(void (*entry)()) {// entry: 每个处理器初始化后要执行的入口函数}// 获取CPU总数int _ncpu() {return num_cpus; // 返回系统中CPU的总数}// 获取当前CPU IDint _cpu() {return hart_id; // 返回当前处理器的ID(从0开始)}// 原子交换操作intptr_t _atomic_xchg(intptr_t *addr, intptr_t newval) {// 原子地将*addr的值替换为newval// 返回原来的值}// 原子加法操作intptr_t _atomic_add(intptr_t *addr, intptr_t adder) {// 原子地将*addr增加adder// 返回原来的值}// 同步屏障void _barrier() {// 等待所有处理器都到达这里}
四、总结
AM 采用了极简主义设计理念,只提供实现操作系统所需的最基本机制。其作用在:
(1)设计理念
▲
最小化依赖:每个扩展都是独立的,可按需使用
▲
机器无关性:统一的 API 接口,屏蔽底层硬件差异
▲
模块化架构:从简单到复杂的递进式功能扩展
(2)技术价值
▲
降低开发门槛:开发者无需关心底层硬件细节,专注于上层逻辑
▲
提高可移植性:一套代码可在不同 RISC-V 实现上运行
▲
支持渐进式开发:从简单的 TRM 程序到复杂的多核程序
▲
便于教学和调试:清晰的分层结构有助于理解计算机系统原理
点击下方图标,关注开芯院平台
▼
