riscv-tests的使用

3.4 riscv-tests的使用

3.4.1 riscv-tests目录的作用。
riscv-tests目录放的是isa、debug、mt和benchmarks的测试文件、底层相关驱动、及其编译的文件,用于测试rocket-chip cpu的性能,可以适当地理解为系统验证,即通过编写C/汇编实现cpu性能的评估。riscv-tests目录的编译依赖于riscv-gnu-toolchain目录,因为C/汇编编译至bin/hex文件都需要用到工具链,同时反汇编的dump文件也需要用到工具链。一般比较常用的是:riscv$(XLEN)-unknown-elf-gcc、riscv$ (XLEN)-unknown-elf-objdump和riscv$ (XLEN)-unknown-elf-objcopy,$ (XLEN)是rocket-chip cpu的处理位数,有32和64两种。

3.4.2 riscv-tests目录的详细说明。

一级目录 二级目录 说明
benchmarks - benchmarks测试的源文件。
- common 通用的头文件、C函数、底层汇编文件和链接文件。
- Makefile make脚本。可以通过修改bmarks来减少编译文件。
- 其他 各测试程序的源代码。
build - riscv-tests目录编译后生成的elf & dump文件。
configure - configure脚本将Makefile.in文件转为Makfile。
configure.ac - 利用autoconf将configure.ac生成configure脚本。
debug - 利debug测试的源文件,通过Python脚本模拟openocd和gdb工作。
- program debug测试的头文件、汇编文件和C代码。
- targets 链接文件和openocd的cfg文件。
- 其他 各测试程序的源代码。
env - 定义了几种cpu使用的环境。
- encoding.h 编码头文件,定义了全部CSR寄存器和几种异常。
- LICENSE LICENSE。
- p virtual memory is disabled, only core 0 boots up.不使用虚拟内存,没有S模式,单核。
- pm dvirtual memory is disabled, all cores boot up.不使用虚拟内存,没有S模式,可以多核。
- pt virtual memory is disabled, timer interrupt fires every 100 cycles.不使用虚拟内存,没有S模式,同时使能了内部的timer。
- v virtual memory is enabled.使用虚拟内存,有S模式。
isa - RISC-V 32/64全部指令测试的源文件。
- macros 宏文件。
- Makefile make脚本。可以通过修改include $(src_dir)/xx/Makefrag来减少编译文件
- 其他 各测试程序的源代码。
LICENSE - LICENSE。
mt - 矩阵乘法测试的源文件。
- Makefile make脚本。可以通过修改bmarks_matmul来减少编译文件。
- 其他 各测试程序的源代码。
README.md - riscv-tests目录的相关说明。

3.4.3 riscv-tests目录使用例子。

(1) 新建C程序目录,在riscv-tests/benchmarks中新建test目录。

cd benchmarks && mkdir test

(2) 编写C语言程序,并保存为test.c。
test.c:

#define U32 *(volatile unsigned int *)

//--------------------------------------------------------------------------
// Main
void main()
{
  int i;
  for ( i = 0; i < 10; i++ )
    U32(0x20400000+4*i) = i;
}

(3) 由于我生成的rocket-chip memory_port是从0x2000_0000开始的,所有我需要修改链接文件,告诉gcc工具链,我希望代码从0x2000_0000开始。所以需要修改riscv-tests/benchmarks/common目录下的test.ld。

/* . = 0x80000000; */
. = 0x20000000;
.text.init : { *(.text.init) }

(4) 再次编译riscv-tests目录,然后在riscv-tests/build/benchmarks目录中能找到编译出来的test.riscv(elf文件) & test.riscv.dump(反汇编文件)。

(5) 最后对riscv-tests/benchmarks/common目录下的crt.S(汇编代码文件)做分析,每个benchmarks目录下的程序都会用到这个文件,#中文的就是注释。
我只对这个文件做初步分析,很多关键字各位可以自行百度或可以关注公众号:硅农亚历山大,阅读其发表的文章《编译过程简介》。

#关键字段
  .section ".text.init"
  .globl _start
#最开始的代码,将32个通用寄存器置0。
_start:			
  li  x1, 0
  li  x2, 0
  li  x3, 0
  li  x4, 0
  li  x5, 0
  li  x6, 0
  li  x7, 0
  li  x8, 0
  li  x9, 0
  li  x10,0
  li  x11,0
  li  x12,0
  li  x13,0
  li  x14,0
  li  x15,0
  li  x16,0
  li  x17,0
  li  x18,0
  li  x19,0
  li  x20,0
  li  x21,0
  li  x22,0
  li  x23,0
  li  x24,0
  li  x25,0
  li  x26,0
  li  x27,0
  li  x28,0
  li  x29,0
  li  x30,0
  li  x31,0

#使用浮点或ROCC,必须置位。
  # enable FPU and accelerator if present
  li t0, MSTATUS_FS | MSTATUS_XS
  csrs mstatus, t0

  # make sure XLEN agrees with compilation choice
  li t0, 1
  slli t0, t0, 31
#if __riscv_xlen == 64
  bgez t0, 1f
#else
  bltz t0, 1f
#endif
2:
  li a0, 1
  sw a0, tohost, t0
  j 2b
1:

#如果生成的rocket-chip支持浮点操作,则需要将浮点的32个通用寄存器置0。
#ifdef __riscv_flen
  # initialize FPU if we have one
  la t0, 1f
  csrw mtvec, t0

  fssr    x0
  fmv.s.x f0, x0
  fmv.s.x f1, x0
  fmv.s.x f2, x0
  fmv.s.x f3, x0
  fmv.s.x f4, x0
  fmv.s.x f5, x0
  fmv.s.x f6, x0
  fmv.s.x f7, x0
  fmv.s.x f8, x0
  fmv.s.x f9, x0
  fmv.s.x f10,x0
  fmv.s.x f11,x0
  fmv.s.x f12,x0
  fmv.s.x f13,x0
  fmv.s.x f14,x0
  fmv.s.x f15,x0
  fmv.s.x f16,x0
  fmv.s.x f17,x0
  fmv.s.x f18,x0
  fmv.s.x f19,x0
  fmv.s.x f20,x0
  fmv.s.x f21,x0
  fmv.s.x f22,x0
  fmv.s.x f23,x0
  fmv.s.x f24,x0
  fmv.s.x f25,x0
  fmv.s.x f26,x0
  fmv.s.x f27,x0
  fmv.s.x f28,x0
  fmv.s.x f29,x0
  fmv.s.x f30,x0
  fmv.s.x f31,x0
1:
#endif

#将trap_entry函数的地址付给mtvec CSR寄存器,发生中断或异常时,PC将会跳至mtvec的地址。
  # initialize trap vector
  la t0, trap_entry
  csrw mtvec, t0

#初始化全局点,设置堆栈的位置
  # initialize global pointer
.option push
.option norelax
  la gp, __global_pointer$
.option pop

  la  tp, _end + 63
  and tp, tp, -64

  # get core id
  csrr a0, mhartid
  # for now, assume only 1 core
  li a1, 1
1:bgeu a0, a1, 1b

  # give each core 128KB of stack + TLS
#define STKSHIFT 17
  sll a2, a0, STKSHIFT
  add tp, tp, a2
  add sp, a0, 1
  sll sp, sp, STKSHIFT
  add sp, sp, tp

#跳至_init的函数中。
  j _init

#对齐位置,接下来是trap_entry函数的汇编代码。
  .align 2
trap_entry:
  addi sp, sp, -272

#异常/中断发生时,保护现场,将32个通用寄存器的值存到某个地方。
  SREG x1, 1*REGBYTES(sp)
  SREG x2, 2*REGBYTES(sp)
  SREG x3, 3*REGBYTES(sp)
  SREG x4, 4*REGBYTES(sp)
  SREG x5, 5*REGBYTES(sp)
  SREG x6, 6*REGBYTES(sp)
  SREG x7, 7*REGBYTES(sp)
  SREG x8, 8*REGBYTES(sp)
  SREG x9, 9*REGBYTES(sp)
  SREG x10, 10*REGBYTES(sp)
  SREG x11, 11*REGBYTES(sp)
  SREG x12, 12*REGBYTES(sp)
  SREG x13, 13*REGBYTES(sp)
  SREG x14, 14*REGBYTES(sp)
  SREG x15, 15*REGBYTES(sp)
  SREG x16, 16*REGBYTES(sp)
  SREG x17, 17*REGBYTES(sp)
  SREG x18, 18*REGBYTES(sp)
  SREG x19, 19*REGBYTES(sp)
  SREG x20, 20*REGBYTES(sp)
  SREG x21, 21*REGBYTES(sp)
  SREG x22, 22*REGBYTES(sp)
  SREG x23, 23*REGBYTES(sp)
  SREG x24, 24*REGBYTES(sp)
  SREG x25, 25*REGBYTES(sp)
  SREG x26, 26*REGBYTES(sp)
  SREG x27, 27*REGBYTES(sp)
  SREG x28, 28*REGBYTES(sp)
  SREG x29, 29*REGBYTES(sp)
  SREG x30, 30*REGBYTES(sp)
  SREG x31, 31*REGBYTES(sp)

#存好一些特殊的CSR寄存器值,并跳至handle_trap函数中。
  csrr a0, mcause
  csrr a1, mepc
  SREG a1, 32*REGBYTES(sp)
  mv a2, sp
  jal handle_trap
  LREG a1, 32*REGBYTES(sp)
  csrw mepc, a1

#返回之前的工作模式
  # Remain in M-mode after eret
  li t0, MSTATUS_MPP
  csrs mstatus, t0

#恢复现场,将之前保存的32个通用寄存器的值返回。
  LREG x1, 1*REGBYTES(sp)
  LREG x2, 2*REGBYTES(sp)
  LREG x3, 3*REGBYTES(sp)
  LREG x4, 4*REGBYTES(sp)
  LREG x5, 5*REGBYTES(sp)
  LREG x6, 6*REGBYTES(sp)
  LREG x7, 7*REGBYTES(sp)
  LREG x8, 8*REGBYTES(sp)
  LREG x9, 9*REGBYTES(sp)
  LREG x10, 10*REGBYTES(sp)
  LREG x11, 11*REGBYTES(sp)
  LREG x12, 12*REGBYTES(sp)
  LREG x13, 13*REGBYTES(sp)
  LREG x14, 14*REGBYTES(sp)
  LREG x15, 15*REGBYTES(sp)
  LREG x16, 16*REGBYTES(sp)
  LREG x17, 17*REGBYTES(sp)
  LREG x18, 18*REGBYTES(sp)
  LREG x19, 19*REGBYTES(sp)
  LREG x20, 20*REGBYTES(sp)
  LREG x21, 21*REGBYTES(sp)
  LREG x22, 22*REGBYTES(sp)
  LREG x23, 23*REGBYTES(sp)
  LREG x24, 24*REGBYTES(sp)
  LREG x25, 25*REGBYTES(sp)
  LREG x26, 26*REGBYTES(sp)
  LREG x27, 27*REGBYTES(sp)
  LREG x28, 28*REGBYTES(sp)
  LREG x29, 29*REGBYTES(sp)
  LREG x30, 30*REGBYTES(sp)
  LREG x31, 31*REGBYTES(sp)

  addi sp, sp, 272
  mret

.section ".tdata.begin"
.globl _tdata_begin
_tdata_begin:

.section ".tdata.end"
.globl _tdata_end
_tdata_end:

.section ".tbss.end"
.globl _tbss_end
_tbss_end:

.section ".tohost","aw",@progbits
.align 6
.globl tohost
tohost: .dword 0
.align 6
.globl fromhost
fromhost: .dword 0

你可能感兴趣的:(RISC-V,&,rocket-chip)