有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 新ちゃん 于 2020-8-20 22:25 编辑
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单片机中文网 |