从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件

RV编译器使用方法
第一步 安装RV GCC
参考文献:https://blog.csdn.net/qq_35553265/article/details/91324754
在学习riscv架构的时候必须会使用到相关指令来测试逻辑是否正常,而手写机器码是一个很痛苦的过程,而使用gcc进行编译生成相应的指令是一个方便的方法,而很多同志在刚开始学习是在windows环境,所以,本文介绍了riscv的gcc在windows(笔者使用的是windows10专业版)环境下的安装。
Linux版本的安装参考蜂鸟E203书籍上的描述。
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第1张图片

下载网盘地址:https://pan.baidu.com/s/1eUbBlVc
下载64位windows版本
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第2张图片

根据博客教程完成解压安装和环境变量的配置。

第二步 学习GCC编译的过程
参考文献:https://www.cnblogs.com/jfyl1573/p/6257004.html
gcc工作四个步骤:预处理,编译,汇编,连接。

1.预处理:

编译器将C源代码中的包含的头文件如stdio.h编译进来,用户可以使用gcc的选项”-E”进行查看。
用法:#gcc -E hello.c -o hello.i

2.编译:

在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。用户可以使用”-S”选项来进行      查看,该选项只进行编译而不进行汇编,生成汇编代码。
选项 -S
  用法: gcc –S hello.i –o hello.s
  作用:将预处理输出文件hello.i汇编成hello.s文件。

3.汇编:

这个阶段是把编译阶段生成的”.s”文件转成二进制目标代码.
选项 -c
用法: gcc –c hello.s –o hello.o
作用:将汇编输出文件test.s编译输出test.o文件。

4.链接:

这个阶段实际就是链接地址,比如去动态库找被调用的函数。

用法:gcc hello.o –o hello.exe
作用:将编译输出文件hello.o链接成最终可执行文件

学习完之后,我们打开cmd dos界面,进到RV GCC安装目录的bin下面,安装目录随意,不过最好参照我的来。
在这里插入图片描述

然后使用命令riscv-none-embed-gcc来替代之前学习到的gcc命令,即可完成编译工作。
在这里插入图片描述

使用RV的GCC命令,完成上述的前3步(预处理、编译、汇编),第四步亲测会报错,暂时不知道怎么解决,不过还好我们不需要用到第四步。完成前三步后,我们得到了.o文件,这个其实就已经是二进制机器码了,只不过我们看不到其中的内容,也无法在vivado当中使用。我们要做的就是将其转换为vivado可读的.mem文件。方法是使用GCC工具objcopy将ELF可执行文件转换成纯净的二进制文件。

第三步 转换格式
参考文献:https://www.cnblogs.com/jfyl1573/p/6257004.html
https://bbs.csdn.net/topics/120005205/

首先使用命令“riscv-none-embed-objcopy”将其转换为.verilog文件,相关用法可以查询GCN objcopy关键词。
在这里插入图片描述

用法如下,指明输入文件的格式和文件名,输出文件的格式和文件名
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第3张图片

之后我们就得到了16进制的.verilog文件。将.verilog文件手动该名为.mem,.mem文件就可以直接添加到vivado当中,然后在testbench中使用readmemh函数去读取其中的内容了,以便进一步加载到指令存储器当中使用。
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第4张图片

`timescale 10ns/1ns
module test;
reg[7:0] memory[0:7];//申请八个8位的存储单元
reg[4:0] n;
initial
begin
$readmemb(“yzj.mem”,memory); //读取yzj.mem中的数字到memory
for(n=0;n<=7;n=n+1) //把八个存储单元的数字都读取出来,若存的数不到八个单元输出x态,程序结果中会看到
$display("%h",memory[n]);
end
endmodule

备注:objcopy支持elf64-littleriscv elf32-littleriscv等格式,目前还没太参透,64 32 好像指的是多少位的处理器,比如64位处理器有64个通用寄存器,而32位的架构下好像只有32个, Little big应该就是指大小端,这个需要手动翻译一条指令,然后看看这个流程搞得对不对来验证。不过如果错了也就是只需要修改一下配置参数,大家可以自己探索一下。我看RV的只支持小端,只有64和32的差别,我编译了一下得到的16进制文件内容是一样的。
在这里插入图片描述在这里插入图片描述

后续:
修改了.s汇编代码的内容为:
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第5张图片

然后编译为.o文件,然后再用命令反汇编,得到结果正确,证明了以上流程可行。
从C(或汇编代码)到risc-v机器码:将risc-v的gcc编译结果转换为vivado可读取的.mem文件_第6张图片
感谢以上博主的帮助。

你可能感兴趣的:(深度学习加速器,risc-v,windows,10,gcc/gdb编译调试,verilog,c语言)