RISCV——指令集工具链

众所周知,软件生态对CPU是至关重要的,而软件工具链的完备是CPU能够真正运行的第一步。本文将以RISCV工具链为例。在RISCV基金会的统筹下,RISCV的生态形成了RISCV概念的两个层次和RISCV指令集架构实现的三个层次:

  • RISC-V概念的两个层次
    RISC-V是开放、免费指令的集架构
    RISC-V指令集架构的具体实现,可以分为自行开发版本、开源无质保免费版本、开源加服务费版本、商用闭源收费版本。
  • RISC-V指令集的三个层次
    基准指令:40余个基准指令,已固化不变
    标准扩展指令:一套标准的可选扩展指令,可能会缓慢演化
    独特指令:用户专为特定片上系统设计的独特指令,无需考虑复用性;各家可对其实现进行专利保护。

下图为RISCV基金会官方的Github中software list:

RISCV——指令集工具链_第1张图片

1. 模拟器——simulators

CPU系统机验证的激励来源主要有内存激励,外部中断和CPU内部激励。内存激励产生的过程:借助RISCV工具链将C代码转化成二进制文件(bin),并保存在内存中,也就是说二进制文件是直接激励,C代码为间接激励。而指令集模拟器在系统验证环境中则充当参考模型的成分。

通常可以将模拟器分为两种,一种是功能级的指令集模拟器,即只在功能上保证能够正确运行目标CPU的指令集;另一种是时钟精确型的指令集模拟器,即不仅能正确执行CPU的指令集,而且能够比较精确的模拟目标CPU的微架构和时序

Spike

  • riscv-isa-sim
    包含risc-fesvr和spike。
    riscv-fesvr:用于实现上位机和CPU之间通信机制的库,用于编译指令模拟器spike的源代码
    spike:基于C/C++开发的指令集模拟器,指令模拟器相当于CPU系统验证环境中的参考模型,testbench将模拟器的结果和CPU DUT的结果作比较。

安装参考:

RISC-V GNU编译环境搭建与运行实践_如何用spike搭建裸机运行环境-CSDN博客

  • riscv-pk
    提供模拟器的RISCV可执行文件运行的程序运行环境,同时提供最简单的bootloader。

    该工具和riscv-isa-sim可以在spike模拟器上运行一个完整的程序。

安装32bit和64bit的pk:

RISCV SOC开发环境 3——指令集仿真器(spike+pk) - 知乎

  • gem5
    一款模块化的离散事件驱动的时钟精确型全系统模拟器,可以模拟多种指令集(Alpha、ARM、SPARC、MIPS、POWER、x86)和微架构(Alpha、SPARC、MIPS、x86);特点是高度可配置,继承多种ISA和多种CPU模型的体系结构
  • OVPsim
    一款由imperas开发的商业化的指令集模拟器
  • riscv-opcodes
    是一个模拟器的riscv操作码信息转换脚本
  • riscv-tests
    riscv指令集自测试用例,是一种能够自我检测指令集运行成功还是失败的测试程序。这些程序均由汇编语言编写

    具体参见:CPU系统级验证——测试激励——riscv-tests代码结构分析-CSDN博客

2. 编译工具

riscv-gnu-toolchain工具链和普通的gnu工具链基本相同,本质区别是riscv-gnu-toolchain生成的bin文件只能在riscv指令集的芯片上运行。

同样,riscv gcc工具链也包含普通gnu工具链中相同作用的工具。若命名为riscv64-unknown-linux-gnu-gcc,riscv64-unknown-linux-gnu-gdb,riscv64-unknown-linux-gnu-ar,分别对应于gcc工具链中的GCC,GDB,Binutils;表示该版本工具链是64位架构的linux版本工具链。(注意:该linux不是指当前版本工具链一定要运行在linux操作系统的电脑上,而是该工具链会使用glibc作为C运行库

类似的,riscv64-unknown-elf-为前缀的版本,表明该版本是非linux版本的工具。(注意:此non-linux不是指当前版本工具链一定不能运行在linux系统中,而是该工具链须使用newlibc作为C运行库

  • GCC

GCC(GNU C Compiler)是编译工具,C代码转化为二进制代码即由该工具完成。

GCC既支持本地编译(在一个平台上编译该平台运行的程序),也支持交叉编译(在一个平台上编译供另一个平台运行的程序)。

编译工具的选项:

  1. -march=
    指定RISCV平台所支持的模块化指令集组合。具体组合有rv32i[m/a/f/d/c],rv32g[c],rv64i[m/a/f/d/c],rv64g[c]。
  2. -mabi=
    指定RISCV平台所支持的ABI函数调用规则。具体组合有ilp32[f/d],lp64[f/d]。ilp32表示目标平台是32位架构,在该架构下,C语言的“int”和“long”变量长度为32bit,“long long”变量为64bit;lp64表示平台为64位架构,在该架构下,C语言的“int”为32bit,“long”为64bit。
  3. -mcmodel=
    指定寻址范围模式,是编译器在编译阶段能按照相应的策略编译生成代码。
    -mcmodel=medany 用于指示该程序的寻址范围可以在任意的一个4GB空间内,该模式下寻址相对比较灵活。
    -mcmodel=medlow 寻址范围固定只能-2GB~+2GB空间内(-2GB指64位地址空间最高2GB地址空间)。
  4. -nostdlib
    不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。
    这个选项常用于编译内核、bootloader等程序,它们不需要启动文件、标准库文件。C语言程序执行的第一条指令并不是main函数。生成一个C程序的可执行文件时编译器通常会在C文件的基础上链接被称为启动文件,如crt.s,syscall.c等,这些代码设置C程序的堆栈等,然后调用main函数。他们依赖于操作系统,在裸板上无法执行,所以可以自己写一个*.S汇编文件。它相当于启动文件,替代上述的crt、syscall等,设置好堆栈后调用main函数。
  5. -nostartfiles
     连接的时候不使用标准系统的启动文件。通常选项“-nostdlib”和“-nodefaultlibs”同时被使用,以禁用标准系统库。
  6. -T  link.ld
    使编译行为根据链接脚本link.ld执行。
  • C运行库

c语言标准主要分为描述C的语法和描述C标准库两部分。C标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏实现,例如printf函数。由于C语言标准仅仅定义了C标准库函数原型,并没有提供实现,因此C语言编译器通常需要一个C运行库的支持。

  1. glibc
    linux下面的C标准的实现库有很多种,例如uclibc、klibc、linux libc等待,glibc (GNU C library)是其中的一种。

    glibc本身是GNU旗下的C标准库,后逐渐成为了linux的标准库,通常被视为操作系统和用户程序的接口。例如glibc不仅实现标准C语言中的函数,还封装了操作系统提供的系统服务,及系统调用的封装。通常情况下,每个特定的系统调用对应了至少一个glibc封装的库函数,而一个glibc的API也有可能由多个系统调用
  2. newlib
    嵌入式系统中使用较多的实现库是Newlib,由redhat公司维护,最新的版本时newlib-nano。与glibc相比,newlib实现了大部分的功能函数,但体积小很多。newlib独特的体系结构将功能实现与具体的操作系统分层,使之能够很好的进行配置,以满足嵌入式系统的要求。根据嵌入式系统的特性,newlib具有可移植性强、轻量级、速度快、功能完备等特点。

    newlib

    在嵌入式操作系统中,OS和底层硬件具有多样性,为了将C/C++需要的运行库与具体的操作系统和底层硬件分层,newlib的所有库函数都建立在20个桩函数的基础上,这20个桩函数完成具体操作系统和底层硬件的如下功能:
    1)I/O和文件系统访问(open、close、read、write、lseek、stat、fstat、fcntl、link、unlink、rename)
    2)扩大内存堆的需求(sbrk)
    3)获得当前系统的日期和时间(gettimeofday、times)
    4)各种类型的任务管理函数(execve、fork、getpid、kill、wait、exit)
  • Binutils

二进制程序处理工具,里面包含多种工具

3. OS and OS kernels

操作系统,主要以Linux为主。

如果是面向台式机,服务器等,需要支持一个完整的Linux发行版。Linux Kernel部分由芯片公司负责,Linux发行版的其他部分可以和操作系统公司合作。如果是嵌入式系统,需要选择支持那种系统,是嵌入式Linux,还是Android,或者其他的实时系统等。嵌入式的场景比较多,支持哪种系统和最后的芯片定位有关系。

4. 调试工具

  • riscv-openocd
    是一个基于openOCD的riscv调试器软件,该openOCD就是下文GDB中表述的GDBServer。
  • GDB

GDB既是一种本地调试器,也是常用的远程调试工具,可以用于对程序进行调试。与本地编译和交叉编译同理,当平台自身无法运行完整的调试器时,就需要PC上的调试器对其进行远程调试;本地调试可以在平台自身上进行调试。

对于远程调试,一般采用GDB+GDBServer的方式,即GDBServer在目标硬件上运行,而GDB在PC上运行。

5. security——安全技术工具

      传统计算的安全性不够,因为几乎所有的程序都能获取到程序的代码和数据,编译器和链接器将源码模块合并成bin文件;各个功能模块(如Stack,Heap,Buffers)通过共享存储单元来通信;任何bit的源码都能得到任何bit的数据;任何一个错误指令能够瘫痪整个系统(如DOS)。

为了解决该问题,RISC-V基金会的Security Technical Group(安全技术组)中的成员 HEX Five公司提出了一个Multi-domain Trusted Execution Environment(多区域信任执行环境),该技术也是基于RISC-V标准扩展指令。在2018年,Hex Five先后宣布完成了基于集成SiFive RISC-V CPU以及Andes RISC-V CPU的晶片开发了类似ARM TrustZone的Trusted Execution Environment。

4. 其他工具

  • riscv-llvm
    一种基于LLVM编译器的框架
  • qemu
    另外一种支持RISCV的qemu指令模拟器,可以运行Linux系统
  • firesim
    在云FPGA上跑的一种FPGA加速的全系统仿真平台

你可能感兴趣的:(#,RISC-V,riscv)