芯片开发验证之RISC-V编译器:绕过构建的烦恼,直接用Arduino的

0、背景。

----https://gitee.com/mirrors/riscv-gnu-toolchain

----一般的数字芯片开发:Verilog编写可综合的电路,Verilog编写Testbench,对待测电路(DUT)进行测试,包括给待测电路输入信号(或激励)、观察待测电路的输出信号、检查输出信号是否符合预期。比如待测电路是Verilog编写的加法器adder.v,测试台程序是Verilog编写的adder_tb.v,其中把adder.v里编写的电路模块实例化、并增加测试用例,然后使用iVerilog将adder.tb.v和adder.v编译为可执行的文件进行测试。

----CPU芯片的开发:相对于一般的数字芯片的区别是,CPU是一个"可编程"的通用的处理器/计算机,而不是一个简单的数字芯片电路。后者通过有限的测试用例进行覆盖,前者要通过各种用户程序来覆盖,特别是,这里的程序是一个指令序列,即使同样的指令,在不同的指令序列中也会产生不同的结果,这和一般数字电路的{输入信号,输出结果,预期输出结果}不同之处就在于指令序列构成第二层的抽象,大概也就是CPU被称为"状态机"的原因。每一个指令驱动CPU的状态变化,1000个指令组成的序列就是1000次状态变化。CPU芯片的开发验证,需要支持用户程序的测试运行。

----需要对RISC-V CPU芯片上的用户程序的相关工具做一个梳理。本文针对RISC-V的编译器,也就是上图中的gcc。

1、RISC-V的编译器:无需编译构建直接用Arduino的。

----曾经,编译构建risc-v的交叉编译器,是一个很大的障碍。

----如今,从CPU芯片开发到SoC/SoB/嵌入式开发走了一遍之后,这个交叉编译器已经在很多工具中见到了,包括Arduino和Keil,都以交叉编译器为基础工具。如上图中Arduino的ESP-r32v就是一个Windows下的risc-v交叉编译器。

----从此,再也不用纠结于RISC-V编译器的构建了!可以直接在Windows上通过安装Arduino以及相关板级开发包,就可以使用RISC-V的交叉编译器、编译出可以在RISC-V上运行的二进制代码(指令序列)!

2、RISC-V编译器的使用备忘。
Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ cat hello3.c

int calc()

{

int a = 3;

int b = 4;

int c = 5;

int d = a + b *b - c;

return d;

}

int main()

{

int a = 9;

int b = calc();

b = b + a;

return b;

}

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ cat link1.ld

SECTIONS

{

. = 0x00000000;

.text : { *(.text) }

}

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ cat link2.ld

OUTPUT_ARCH( "riscv" )

ENTRY(_start)

SECTIONS

{

. = 0x80000000;

.text.init : { *(.text.init) }

. = ALIGN(0x1000);

.tohost : { *(.tohost) }

. = ALIGN(0x1000);

.text : { *(.text) }

. = ALIGN(0x1000);

.data : { *(.data) }

.bss : { *(.bss) }

_end = .;

}

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-gcc -S -o hello3.s hello3.c

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-as -o hello3.o hello3.s

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-ld -o hello3a hello3.o

C:\users\Chipcamp\AppData\Local\Arduino15\Packages\esp32\tools\esp-rv32\2507\bin\riscv32-esp-elf-ld.exe: warning: cannot find entry symbol _start; defaulting to 00010094

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-ld -o hello3b -T link1.ld hello3.o

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-ld -o hello3c -T link2.ld hello3.o

C:\users\Chipcamp\AppData\Local\Arduino15\Packages\esp32\tools\esp-rv32\2507\bin\riscv32-esp-elf-ld.exe: warning: cannot find entry symbol _start; defaulting to 80000000

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ ll

total 31

-rw-r--r-- 1 Chipcamp 197609 196 Nov 16 02:05 hello3.c

-rw-r--r-- 1 Chipcamp 197609 1164 Nov 16 10:49 hello3.o

-rw-r--r-- 1 Chipcamp 197609 1025 Nov 16 10:49 hello3.s

-rw-r--r-- 1 Chipcamp 197609 1200 Nov 16 10:50 hello3a

-rw-r--r-- 1 Chipcamp 197609 4936 Nov 16 10:50 hello3b

-rw-r--r-- 1 Chipcamp 197609 4980 Nov 16 10:51 hello3c

-rw-r--r-- 1 Chipcamp 197609 55 Nov 16 02:02 link1.ld

-rw-r--r-- 1 Chipcamp 197609 272 Nov 16 02:02 link2.ld

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objcopy -O binary hello3a hello3a.bin

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objcopy -O binary hello3b hello3b.bin

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objcopy -O binary hello3c hello3c.bin

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objdump -D hello3a >hello3a.dmp

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objdump -D hello3b >hello3b.dmp

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ riscv32-esp-elf-objdump -D hello3c >hello3c.dmp

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ ll

total 58

-rw-r--r-- 1 Chipcamp 197609 196 Nov 16 02:05 hello3.c

-rw-r--r-- 1 Chipcamp 197609 1164 Nov 16 10:49 hello3.o

-rw-r--r-- 1 Chipcamp 197609 1025 Nov 16 10:49 hello3.s

-rw-r--r-- 1 Chipcamp 197609 1200 Nov 16 10:50 hello3a

-rw-r--r-- 1 Chipcamp 197609 114 Nov 16 10:52 hello3a.bin

-rw-r--r-- 1 Chipcamp 197609 4737 Nov 16 10:54 hello3a.dmp

-rw-r--r-- 1 Chipcamp 197609 4936 Nov 16 10:50 hello3b

-rw-r--r-- 1 Chipcamp 197609 114 Nov 16 10:52 hello3b.bin

-rw-r--r-- 1 Chipcamp 197609 4539 Nov 16 10:54 hello3b.dmp

-rw-r--r-- 1 Chipcamp 197609 4980 Nov 16 10:51 hello3c

-rw-r--r-- 1 Chipcamp 197609 114 Nov 16 10:52 hello3c.bin

-rw-r--r-- 1 Chipcamp 197609 4721 Nov 16 10:54 hello3c.dmp

-rw-r--r-- 1 Chipcamp 197609 55 Nov 16 02:02 link1.ld

-rw-r--r-- 1 Chipcamp 197609 272 Nov 16 02:02 link2.ld

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ file hello*

hello3.c: C source, ASCII text, with CRLF line terminators

hello3.o: ELF 32-bit LSB relocatable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), not stripped

hello3.s: assembler source, ASCII text, with CRLF line terminators

hello3a: ELF 32-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), statically linked, not stripped

hello3a.bin: data

hello3a.dmp: ASCII text, with CRLF line terminators

hello3b: ELF 32-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), statically linked, not stripped

hello3b.bin: data

hello3b.dmp: ASCII text, with CRLF line terminators

hello3c: ELF 32-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), statically linked, not stripped

hello3c.bin: data

hello3c.dmp: ASCII text, with CRLF line terminators

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$

3、RISC-V编译器相关生成中间文件或结果文件及查看工具。
Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ cat hello3.s

.file "hello3.c"

.option nopic

.attribute arch, "rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0"

.attribute unaligned_access, 0

.attribute stack_align, 16

.text

.align 1

.globl calc

.type calc, @function

calc:

addi sp,sp,-32

sw ra,28(sp)

sw s0,24(sp)

addi s0,sp,32

li a5,3

sw a5,-20(s0)

li a5,4

sw a5,-24(s0)

li a5,5

sw a5,-28(s0)

lw a5,-24(s0)

mul a4,a5,a5

lw a5,-20(s0)

add a4,a4,a5

lw a5,-28(s0)

sub a5,a4,a5

sw a5,-32(s0)

lw a5,-32(s0)

mv a0,a5

lw ra,28(sp)

lw s0,24(sp)

addi sp,sp,32

jr ra

.size calc, .-calc

.align 1

.globl main

.type main, @function

main:

addi sp,sp,-32

sw ra,28(sp)

sw s0,24(sp)

addi s0,sp,32

li a5,9

sw a5,-20(s0)

call calc

sw a0,-24(s0)

lw a4,-24(s0)

lw a5,-20(s0)

add a5,a4,a5

sw a5,-24(s0)

lw a5,-24(s0)

mv a0,a5

lw ra,28(sp)

lw s0,24(sp)

addi sp,sp,32

jr ra

.size main, .-main

.ident "GCC: (crosstool-NG esp-14.2.0_20250730) 14.2.0"

.section .note.GNU-stack,"",@progbits

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ head -52 hello3a.dmp

hello3a: file format elf32-littleriscv

Disassembly of section .text:

00010094 <calc>:

10094: 1101 addi sp,sp,-32

10096: ce06 sw ra,28(sp)

10098: cc22 sw s0,24(sp)

1009a: 1000 addi s0,sp,32

1009c: 478d li a5,3

1009e: fef42623 sw a5,-20(s0)

100a2: 4791 li a5,4

100a4: fef42423 sw a5,-24(s0)

100a8: 4795 li a5,5

100aa: fef42223 sw a5,-28(s0)

100ae: fe842783 lw a5,-24(s0)

100b2: 02f78733 mul a4,a5,a5

100b6: fec42783 lw a5,-20(s0)

100ba: 973e add a4,a4,a5

100bc: fe442783 lw a5,-28(s0)

100c0: 40f707b3 sub a5,a4,a5

100c4: fef42023 sw a5,-32(s0)

100c8: fe042783 lw a5,-32(s0)

100cc: 853e mv a0,a5

100ce: 40f2 lw ra,28(sp)

100d0: 4462 lw s0,24(sp)

100d2: 6105 addi sp,sp,32

100d4: 8082 ret

000100d6 <main>:

100d6: 1101 addi sp,sp,-32

100d8: ce06 sw ra,28(sp)

100da: cc22 sw s0,24(sp)

100dc: 1000 addi s0,sp,32

100de: 47a5 li a5,9

100e0: fef42623 sw a5,-20(s0)

100e4: 3f45 jal 10094 <calc>

100e6: fea42423 sw a0,-24(s0)

100ea: fe842703 lw a4,-24(s0)

100ee: fec42783 lw a5,-20(s0)

100f2: 97ba add a5,a5,a4

100f4: fef42423 sw a5,-24(s0)

100f8: fe842783 lw a5,-24(s0)

100fc: 853e mv a0,a5

100fe: 40f2 lw ra,28(sp)

10100: 4462 lw s0,24(sp)

10102: 6105 addi sp,sp,32

10104: 8082 ret

Disassembly of section .comment:

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ xxd.exe hello3a.bin

00000000: 0111 06ce 22cc 0010 8d47 2326 f4fe 9147 ...."....G#&...G

00000010: 2324 f4fe 9547 2322 f4fe 8327 84fe 3387 #$...G#"...'..3.

00000020: f702 8327 c4fe 3e97 8327 44fe b307 f740 ...'..>..'D....@

00000030: 2320 f4fe 8327 04fe 3e85 f240 6244 0561 # ...'..>..@bD.a

00000040: 8280 0111 06ce 22cc 0010 a547 2326 f4fe ......"....G#&..

00000050: 453f 2324 a4fe 0327 84fe 8327 c4fe ba97 E?#$...'...'....

00000060: 2324 f4fe 8327 84fe 3e85 f240 6244 0561 #$...'..>..@bD.a

00000070: 8280 ..

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ od -An -tx1 -w -v hello3a.bin

01 11 06 ce 22 cc 00 10 8d 47 23 26 f4 fe 91 47 23 24 f4 fe 95 47 23 22 f4 fe 83 27 84 fe 33 87

f7 02 83 27 c4 fe 3e 97 83 27 44 fe b3 07 f7 40 23 20 f4 fe 83 27 04 fe 3e 85 f2 40 62 44 05 61

82 80 01 11 06 ce 22 cc 00 10 a5 47 23 26 f4 fe 45 3f 23 24 a4 fe 03 27 84 fe 83 27 c4 fe ba 97

23 24 f4 fe 83 27 84 fe 3e 85 f2 40 62 44 05 61 82 80

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ od.exe -An -tx1 -w1 -v hello3a.bin > hello3a.hex

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$ ll hello3a.hex

-rw-r--r-- 1 Chipcamp 197609 456 Nov 16 11:12 hello3a.hex

Chipcamp@X2022 MINGW64 /d/chipcamp/hello3
$

4、总结备忘。

----RISC-V编译器的获取:Arduino支持多种CPU/MCU,其中RISC-V类型的MCU开发板就有相应的RISC-V编译器,可以直接使用来进行RISC-V源程序的编译和研究!不必在RISC-V编译器的编译构建上消耗时间。

----RISC-V编译器的使用:.c文件(C代码)编译为.s文件(汇编代码)。.s文件编译为.o文件。.o文件和.ld文件链接为可执行的ELF文件。

----RISC-V的CPU开发验证:可执行的ELF文件可以转换为纯指令序列的.bin文件。纯指令序列的.bin文件可以通过hexedit或者xxd进行查看,也可以通过od转换为十六进制文本文件格式的.hex文件。这个.hex文件可以在Chisel语言中加载到内存中(重新变为和bin文件等效的二进制的指令序列)并被CPU执行。这个CPU是使用Chisel语言编写的CPU的RTL代码。

----使用riscv-unknown-elf-gcc编译。//生成.s文件。也可以生成目标文件或执行文件。

----使用riscv-unknown-elf-as汇编。//生成.o文件

----使用riscv-unknown-elf-ld链接。//生成ELF格式可执行文件。

----使用riscv-unknown-objcopy拷贝。//生成.bin纯指令序列文件。对ELF文件有效。

----使用riscv-unknown-objdump导出。//生成.dmp文本文件。对ELF文件有效。

----使用hexedit或者xxd查看二进制文件。//包括ELF格式的.o或.exe以及纯指令序列.bin

----使用od将纯指令序列.bin转换为文本文件。//对纯指令序列的.bin文件有意义

----汇编代码.s文件中的CALL是汇编语言助记符/语法糖。bin/hex中对应的实际指令是JAL。

<<<<<<<<END>>>>>>>>

摘要:本文介绍了RISC-V交叉编译器的使用流程。通过Arduino可直接获取RISC-V编译器工具链,无需自行构建。演示了从C代码编译为汇编(.s)、目标文件(.o)、ELF可执行文件的过程,以及使用不同链接脚本生成二进制文件的方法。详细展示了使用objdump、xxd、od等工具分析生成文件的操作步骤,包括查看汇编指令、十六进制转储等。最后总结了RISC-V编译器工具链各组件功能,说明其在CPU开发验证中的关键作用------将程序转换为可被Chisel语言实现的CPU执行的二进制指令序列。

相关推荐
全球通史3 天前
[特殊字符] RISC-V实战:从0到100+FPS!进迭时空(Spacemit)开发板YOLOv8部署终极指南
嵌入式硬件·yolo·risc-v
码界奇点4 天前
Linux进程间通信三System V 共享内存完全指南原理系统调用与 C 封装实现
linux·c语言·网络·c++·ux·risc-v
飞凌嵌入式5 天前
【玩转多核异构】T153核心板RISC-V核的实时性应用解析
linux·嵌入式硬件·嵌入式·risc-v
卡奥斯开源社区官方5 天前
NVIDIA CUDA全面支持RISC-V深度解析:技术原理、开发实操与生态红利
risc-v
爱喝矿泉水的猛男5 天前
单周期Risc-V指令拆分与datapath绘制
运维·服务器·risc-v
国科安芯7 天前
FreeRTOS 在 AS32系列RISC-V 架构MCU电机驱动中的应用实践与优化
单片机·嵌入式硬件·安全·架构·压力测试·risc-v·安全性测试
矜辰所致9 天前
沁恒 RISC-V 蓝牙芯片 Flash 分区管理及操作
risc-v·flash·flash读写·ch585·蓝牙 ble
矜辰所致9 天前
沁恒微 RISC-V 蓝牙芯片低功耗测试
低功耗·risc-v·ble 蓝牙·蓝牙低功耗·沁恒微蓝牙
易·木9 天前
阅读 RISC-V 手册
risc-v