面向 RISC-V 开放架构的应用移植与优化:Syntacore 开发工具

RISC-V 是一种现代、开放的指令集架构(ISA),适用于从嵌入式系统到高性能计算(HPC)的各类应用。RISC-V 采用模块化设计, 可以在精简的基础指令集之上进行扩展,从而轻松适配各种专用工作负载。与 x86 和 ARM 不同, RISC-V开放且无需支付授权费用, 这使其更易获取, 也让创新具有成本效业的产品得以实现。

RISC-V 软件生态系统汇聚了来自不同细分市场的众多领先企业,形成了广泛的国际社区。该生态系统持续演进,致力推动 RISC-V 软件开发的发展,涵盖操作系统,运行时环境,开发工具,引导加载程序 (bootloader) 以及终端应用程序。

Syntacore提供了一整套软件与工具,包括预构建且经过优化的工具链、IDE、操作系统、引导加载程序和运行时环境,帮助您快速开始 RISC-V 开发:

  • 专业软件开发套件(预构建的 GCC 工具链与针对微架构优化的 clang/LLVM 工具链、预先配置好的 Eclipse 与 Visual Studio Code IDE、QEMU 仿真环境、BSP、调试工具及相关库)。
  • 基础系统软件(经过 SCR 内核测试、兼容 RISC-V 的各类工具和系统软件, 包括预先配置好的 Linux、Zephyr、FreeRTOS 操作系统、引导加载程序、运行时环境等)
  • 功能完善的 FPGA SDK(基于主流厂商的 FPGA 开发板,支持多种 JTAG/cJTAG 适配器)

本文将概述 Syntacore 的开发套件、系统软件和 FPGA SDK,并深入探讨经过优化的 LLVM 工具链的优势——该工具链基于上游版本构建, 通过一系列优化带来可衡量的性能提升。

专业软件开发套件

Syntacore 提供了一款开箱即用的一体化开发工具包,包含在 SCR 内核上进行快速高效应用开发所需的一切。Syntacore 开发工具包(SC-DT) 是一款先进且定期更新的应用开发套件,基于预构建的 GCC 和 clang/LLVM 工具链打造。它集成了各软件组件的最新版本,确保开发者能够用上最新的功能和改进。该工具包将预先配置好的 Eclipse IDE、Visual Studio Code 扩展、QEMU 仿真环境、调试工具和相关库整合为一个软件包。SC-DT 支持 x86 平台的 Linux 和 Windows,也支持 RISC-V 版 Linux 操作系统,是一款适用面广泛的开发者工具。

SC-DT 包含以下内容:

  • 工具链
    • LLVM——基于上游版本预构建,并针对 SCR 专属微架构进行了优化
    • GCC——预构建的 RISC-V 工具链(针对裸机环境配置为 multilib,针对 Linux 应用配置为 glibc),并附带 RISC-V 版 GDB
  • IDE
    • Syntacore 的 Visual Studio Code 扩展
    • 预先配置好的 Eclipse IDE
  • 工具——预构建的 OpenOCD 和 QEMU
  • 系统软件
    • BSP/HAL——示例项目与硬件抽象层(HAL)
    • 微基准测试——集成了 Coremark、Dhrystone、FLOPS、Whetstone 等基准测试程序
    • 面向 Linux 镜像的软件*(文件系统、Linux 内核、miniboot、OpenSBI 和 U-Boot 引导加载程序)
  • 完整的文档资料(简明用户指南、安装指南和版本发布说明)
SC-DT 工具包组件概览

图 1. SC-DT 工具包组件概览

* Linux 操作系统、Zephyr、miniboot、OpenSBI 和 U-Boot 需单独下载

LLVM 工具链

LLVM 是一款功能强大的开源工具链,为编译器开发提供了全面的能力,支持根据特定应用需求进行定制。Syntacore 版 LLVM 专为 SCR 内核开发,内置多项优化以确保应用获得最佳性能。它包括:

  • 面向微架构的优化
  • 针对重要扩展的早期实验性支持,便于在硬件和性能模型上进行原型验证
  • 对特定指令和扩展的支持
  • 在上游项目中对 SCRx 系列内核的兼容与支持

LLVM 优化

LLVM 利用针对特定微架构的优化,通过生成与底层硬件特性精细匹配的代码来提升性能,例如:

  • LoopSplit 过程(pass),相当于 GCC 的 -fsplit-loops 优化选项,可让向量化更高效地处理循环。此外,诸如循环分发(loop distribution)等额外优化还能进一步改善效果
  • 推测去虚化(Speculative devirtualization),允许将间接调用替换为直接调用:

    转换前:

    struct A {
        virtual void vdo();
        void dosmth() {
            vdo(); // 虚函数调用
        }
    };
    

    转换后:

    void dosmth() {
      if (vtable[vdo] == A::vdo)
        A::vdo(); // 可内联
      else // 分支预测失败
        vtable[vdo]();
    }
    
  • 反向 if 转换(Reverse if-conversion),可将一组谓词赋值转换为条件块
  • 存储指令聚类,尝试将目标地址相邻的存储指令安排在一起调度
  • LoopIntWrapPredication ——执行循环版本化(loop versioning),并针对无符号归纳变量不会溢出的情形对其中一个版本进行优化
  • 改进的公共子表达式消除(CSE)

Syntacore LLVM 21 与社区版 LLVM 21 的性能对比(SCR4)*

Syntacore LLVM 21 与社区版 LLVM 21 的性能对比(SCR4)

Syntacore LLVM 21 与社区版 LLVM 21 的性能对比(SCR9,SPEC CPU2006)*

Syntacore LLVM 21 与社区版 LLVM 21 的性能对比(SCR9,SPEC CPU2006)

* 实际性能可能因应用程序而异

图表中展示的性能提升得益于与架构无关的 SC-DT clang 优化,包括:

  • 结合内核流水线结构进行的指令调度
  • 基于调度模型的指令合并与重结合(reassociation)
  • 选择用于执行循环展开(loop unrolling)的参数设置
  • 查找复杂模式,并利用可用 ISA 扩展中的指令对其进行优化,例如使用 clmul 指令来实现 CRC(循环冗余校验)
  • 代码对齐(函数、循环)

该工具包提供 CMake 工具链文件,这是为裸机和 Linux 应用配置构建环境的重要工具。这种双重支持简化了开发流程,使开发者无论面向哪种目标平台,都能轻松搭建和管理构建配置。

GCC 工具链

虽然 LLVM 是针对 SCR 处理器定制优化的,但在某些情况下,处理器架构仅使用标准的 RISC-V 扩展,此时可以使用常规的 GCC 工具链。

GCC 工具链是众多 Linux 系统的传统选择,也是业界标准:它直接取自上游项目,简单易用,无需额外配置即可使用。

作为 GCC 工具链的组成部分,GNU binutils、GNU libc 和 newlib 经过配置,可与 LLVM 编译器 clang 协同工作,从而提供更高的灵活性和兼容性,让开发者能够根据具体需求选用不同的编译器和库。

集成开发环境(IDE)

在 SC-DT 中,两种工具链以及调试器都与 IDE 无缝集成,显著提升了开发效率和速度。

Visual Studio Code

Syntacore 的 VS Code 扩展为面向 SCR 内核的应用开发提供了灵活的环境。它内置向导和配置文件,可简化项目配置,让开发流程更加顺畅。VS Code 通过与 GDB(GNU 调试器)、OpenOCD 和 QEMU 集成,支持轻量级调试,使开发者能够在将应用部署到实际硬件之前,先在受控环境中进行仿真测试。

Visual Studio Code IDE 中的项目向导

图 2. Visual Studio Code IDE 中的项目向导

预先配置好的 SCR 专属项目设置

图 3. 预先配置好的 SCR 专属项目设置

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "<debugger>/<toolchain>/<project name>",
            "variables": {
                "programPath": "${config:cmake.buildDirectory}/<toolchain>/<project name>.elf"
            },
            "type": "cppdbg",
            "request": "launch",
            "cwd": "${workspaceFolder}",
            "program": "${programPath}",
            "debugServerPath": "${config:syntacore.openocd.path}/bin/openocd",
            "debugServerArgs": "-s ${config:syntacore.openocd.path}/share/openocd/scripts -f /path/to/jtag_adapter.cfg -f target/syntacore_target.cfg -f syntacore/syntacore_ide_csr_cloak.cfg",
            "filterStderr": true,
            "miDebuggerPath": "${config:syntacore.gdb.path}/bin/riscv64-unknown-elf-gdb",
            "windows": {
                "debugServerPath": "${config:syntacore.openocd.path}/bin/openocd.exe",
                "miDebuggerPath": "${config:syntacore.gdb.path}/bin/riscv64-unknown-elf-gdb.exe"
            },
            "miDebuggerServerAddress": ":3333",
            "postRemoteConnectCommands": [
                {
                    "text": "load"
                }
            ],
            "useExtendedRemote": true,
            "stopAtEntry": true
        },
    ]
}

Visual Studio Code IDE 中的调试配置文件示例

Visual Studio Code IDE 中的调试环境

图 4. Visual Studio Code IDE 中的调试环境

Eclipse IDE

Eclipse 是一款广受欢迎的 IDE,除了具备前文所述 VS Code 的各项功能外,还提供了用户熟悉的图形界面,对从事嵌入式开发的工程师而言尤为友好易用。

Eclipse IDE 中的调试环境

图 5. Eclipse IDE 中的调试环境

Eclipse IDE 中基于图形界面的调试配置

图 5. Eclipse IDE 中基于图形界面的调试配置

仿真环境

该工具包包含一个 QEMU 环境,可快速仿真 Syntacore 的 CPU 内核及集群。开发者可以在模拟真实硬件行为的虚拟平台上对应用进行仿真和测试,从而显著加快开发进程。QEMU 能够运行使用上游 RISC-V GCC 和 LLVM 工具链,以及随工具包分发的预配置工具链构建的程序。QEMU 还内置了一个gdbserver,让您能够通过 GDB 调试程序。

QEMU 可以在两种模式下使用:用户级仿真和系统级仿真。

  • 用户级仿真:
    如下图所示,qemu-user 模式允许您像运行原生应用程序一样,在 x86 Linux 系统上直接运行为 RISC-V 构建的 Linux 应用程序(例如 nano 和 VIM)。
  • 系统级仿真:
    其中 x86 侧操作系统可以是 Windows 或 Linux,RISC-V 侧操作系统则可以是任意可用的 RISC-V 操作系统,例如 Linux、FreeBSD、NetBSD。系统级仿真器可模拟裸机 RISC-V 环境,让您能够调试任意裸机应用程序、RTOS 以及 Linux。
QEMU 中的仿真模式

图 7. QEMU 中的仿真模式

调试工具

该工具包为通过 OpenOCD 和 GDB 进行调试提供了强大支持,这两款工具在嵌入式系统开发中常常配合使用,应用广泛。OpenOCD 允许用户通过外部调试接口 JTAG/cJTAG 作为传输层,与 SCR 内核进行交互。

典型任务包括:

  • 运行带实时监控的调试会话
  • 设置断点、读写内存,以及单步执行代码
  • 将固件烧录到目标设备

OpenOCD 通常与调试适配器配合使用,并与 GDB 等工具对接,以提供源代码级调试支持。

GDB 可用于对软件进行源代码级调试:

  • 在特定代码行或指令地址上设置断点
  • 查看寄存器和内存
  • 逐行或逐指令单步执行代码

OpenOCD 与 GDB 之间的协作相当直接:OpenOCD 负责与硬件之间的底层交互(例如通过外部调试接口与 RISC-V 内核通信),而 GDB 则负责处理高层调试命令。

基础系统软件

系统软件随工具包提供,包含了开发者在 SCR 内核上以裸机或 Linux 方式启动和运行应用程序所需的一切。

该工具包提供:

  • 面向裸机应用、开箱即用的硬件抽象层(HAL)。它本质上是一个库,包含底层启动代码、一组用于操作 CPU 集群的驱动程序(例如控制缓存、中断控制器、UART 等硬件组件),以及用于构建裸机应用的通用链接规则,帮助开发者在 Syntacore 的 SCR 内核上快速实现自己的设计
  • 一套面向 Syntacore RISC-V 处理器的系统示例应用程序。示例应用同时支持裸机和 Linux 目标环境:为裸机编译时需要 Syntacore HAL,而面向 Linux 编译时则无需使用。这些示例应用既有简单的,也有较为复杂的,分别针对 SCR 内核的不同子系统和功能模块,用于演示其功能。开发者也可以将这些示例应用作为模板,构建自己的应用程序。
  • 两款最受欢迎的实时操作系统(RTOS)项目的最新版本,用于在 SCR 内核(单核/多核)上测试嵌入式解决方案的更复杂功能:FreeRTOS 和 Zephyr(需单独下载)。
  • Syntacore Linux 支持包,适用于 Windows 和 Linux 主机。该软件包包含在 Syntacore 平台上运行 Linux 所需的系统软件栈:
    • miniboot:作为第一阶段引导加载程序,仅执行最基本的硬件初始化。
    • OpenSBI:作为第一阶段引导加载程序,同时提供管理程序二进制接口(SBI)的实现。工具包中包含预构建的、适用于 SCR7 L2 集群的 OpenSBI 版本,可用于演示。如需定制,您可以从 GitHub 下载 OpenSBI 源代码。
    • U-Boot:作为第二阶段引导加载程序
    • Linux 内核镜像
    • Linux 根文件系统镜像

Syntacore FPGA SDK

Syntacore 提供了一款功能完善的软件开发套件,让您能够快速、便捷地启动、测试和开发基于 SCR 的项目。FPGA SDK 是一个开箱即用的软件包,包含一个 FPGA 工程以及相应的 IP 核和外设单元。它配备了内存及标准接口,方便您无缝集成其他外设,从而开展功能完善的应用测试。

总结

Syntacore 提供了一个专业、完整的 RISC-V 开发平台,包含预先配置好的 GCC 和 LLVM 工具链、灵活易用的 VS Code 与 Eclipse IDE,以及先进的调试器和仿真器,专为在 SCR 内核上构建高效应用而设计。其中的 LLVM 工具链基于上游 LLVM 构建,通过 Syntacore 的先进优化带来性能提升。再加上经过测试且定期更新的系统软件,以及开箱即用的 FPGA SDK,您将获得以最少的精力开始开发 RISC-V 应用所需的一切。