如何建立自己的RISC-V编译环境–汇编?

1.RISC-V编译环境框架

这是我RISC-V编译环境的架构:

build  case  common  toolchain
一级目录 二级目录 说明
build - xx.hex、xx.bin、xx.dump & xx.elf生成的目录。
- Makefile 编译脚本。
- add(例子) 生成文件,根据test.c生成的xx.hex、xx.bin、xx.dump & xx.elf
project - 各个目录的源代码。
- add(例子) 放add项目的S文件。
common - 各个项目公用的文件。
- encoding.h /riscv-tests/env目录中的H文件。
- asm.h /riscv-tests/env/p/riscv_test.h文件,只是我改为asm.h。
- asm.ld /riscv-tests/env/p/link.ld文件,用于链接物理地址和汇编,我改名字为asm.ld了。
toolchain - 工具链。我在/riscv-tools/riscv-gnu-toolchain/的工具链上提取了对我有用的部分。

2.各目录内容介绍

2.1 toolchain:工具链目录我不打算介绍,如果有不明白的,可以看我的这个博客:
rocket-chip工具链的编译与使用(https://blog.csdn.net/a_weiming/article/details/84801051)

2.2 project:这个目录就是放你的项目代码的。每个项目建立一个目录。在这个例子中,我放的是add目录,add的源代码如下(全为汇编代码):
此外,RISC-V汇编不熟悉的可以参考以下链接:
https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md
https://mp.weixin.qq.com/s/-syKN0DibKGGPCllaeNqMg
https://mp.weixin.qq.com/s/jyI-SSm_5Gg-KQyjKsIj5Q
https://mp.weixin.qq.com/s/3RHss3vhfK004-TtM8fpeA
https://mp.weixin.qq.com/s/Ln4qBYvSsgRvdiK1IJqI6Q

下面贴图为.section的说明。

注意,下文中使用“###”形式的均是我添加的注释,原代码中没有。

#*****************************************************************************
# add.S
#-----------------------------------------------------------------------------
#
# Test add instructions.
##屏蔽了原来的include "riscv_test.h"
######include "riscv_test.h"
#使用我自己的asm.h
#include "asm.h"###使用RVTEST_RV32U段内容
RVTEST_RV32U
###使用RVTEST_CODE_BEGIN段内容
RVTEST_CODE_BEGIN
###按2^2字节(4字节)数据对齐.align 2###“.option push”伪操作暂时将当前的选项设置保存起来,###从而允许之后使用.option伪操作指定新的选项;###而“.option pop”伪操作将最近保存的选项设置恢复出来重新生效。###通过“.option push”和“.option pop”的组合,便可以在汇编程序中在不影响全###局选项设置的情况下,为其中嵌入的某一段代码特别地设置不同的选项。###意思就是:###在add.S这个汇编文件中,将前面其他.S/.h文件中的配置选项保存起来,###然后在add.S文件中设置一些新的选项,新的选项就是下面的.option norvc.option push###伪操作表示接下来的汇编程序不可以被汇编生成16位宽的压缩指令。.option norvc###定义标签asm_start
asm_start:###将0xAAAAAAAA赋给a1li   a1, 0xAAAAAAAA###将0x22222222赋给a1li   a0, 0x22222222###将a0和a1相加,并出入a2中add  a2, a1, a0###将0x7000_0000存入a4中lui  a4, 0x70000###将a4的值+4并存入a6中addi a6, a4, 4###将a2的结果存到总线为0x7000_0004的memory中sw   a2, 0(a6)###将0xFF存到a5中li   a5, 255###将a5的结果存到总线为0x7000_0000的memory中,用于停止VCS仿真sw   a5, 0(a4)###恢复原选项配置.option pop###使用RVTEST_CODE_END段内容
RVTEST_CODE_END###数据段.data:已初始化的C程序全局变量和静态局部变量。.data
###使用RVTEST_DATA_BEGIN段内容
RVTEST_DATA_BEGIN###使用RVTEST_DATA_END段内容
RVTEST_DATA_END

以下的定义在asm.h中有详细的说明。
RVTEST_RV32U
RVTEST_CODE_BEGIN
RVTEST_CODE_END
RVTEST_DATA_BEGIN
RVTEST_DATA_END

2.3 common:这个目录放的是通用的内容,例如asm.h和asm.lk。

2.3.1 encoding.h:这个文件不解释,就是RISC-V各重要CSR寄存器的定义。

2.3.2 asm.h:这个我是根据/riscv-tests/env/p/riscv_test.h文件进行修改的,下面简单说明一下里面各汇编的含义。
此外,我修改的是p目录下的文件,p目录下是单核的,而且是没有MMU的。具体env中各目录的差异大家可以看:
https://github.com/riscv/riscv-tests/tree/7ef425b4aea0a93568c788e68acebcc2f08da8d6

// See LICENSE for license details.#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
#define _ENV_PHYSICAL_SINGLE_CORE_H#include "./encoding.h"//-----------------------------------------------------------------------
// Begin Macro
//-----------------------------------------------------------------------###定义宏init
#define RVTEST_RV64U                                                    \.macro init;                                                          \.endm###定义宏init,同时运行RVTEST_FP_ENABLE段
#define RVTEST_RV64UF                                                   \.macro init;                                                          \RVTEST_FP_ENABLE;                                                     \.endm###定义宏init
#define RVTEST_RV32U                                                    \.macro init;                                                          \.endm###定义宏init,同时运行RVTEST_FP_ENABLE段
#define RVTEST_RV32UF                                                   \.macro init;                                                          \RVTEST_FP_ENABLE;                                                     \.endm###定义宏init
#define RVTEST_RV64M                                                    \.macro init;                                                          \RVTEST_ENABLE_MACHINE;                                                \.endm###定义宏init,同时运行RVTEST_ENABLE_SUPERVISOR段
#define RVTEST_RV64S                                                    \.macro init;                                                          \RVTEST_ENABLE_SUPERVISOR;                                             \.endm###定义宏init,同时运行RVTEST_ENABLE_MACHINE段
#define RVTEST_RV32M                                                    \.macro init;                                                          \RVTEST_ENABLE_MACHINE;                                                \.endm###定义宏init,同时运行RVTEST_ENABLE_SUPERVISOR段
#define RVTEST_RV32S                                                    \.macro init;                                                          \RVTEST_ENABLE_SUPERVISOR;                                             \.endm###运行CHECK_XLEN段
#if __riscv_xlen == 64
###将1装入a0;将a0的值进行逻辑左移31位;如果a0的值≥0,跳转至标志为1的地方;
###运行RVTEST_PASS段;标志1的位置。
###1f的意思是向前找第一个数字为1的标志,即往下面的行找
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
#else
###将1装入a0;将a0的值进行逻辑左移31位;如果a0的值<0,跳转至标志为1的地方;
###运行RVTEST_PASS段;标志1的位置。
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
#endif###定义INIT_PMP段的内容
#define INIT_PMP                                                        \###将标志1的PC赋值给t0la t0, 1f;                                                            \###将t0的值赋值给mtveccsrw mtvec, t0;                                                       \###将-1赋值给t0,实际上是赋0xFFFF_FFFF给t0li t0, -1;        /* Set up a PMP to permit all accesses */           \###将t0的值写入pmpaddr0 CSR寄存器中csrw pmpaddr0, t0;                                                    \###将PMP_NAPOT | PMP_R | PMP_W | PMP_X的值赋给t0,这些值在encoding.h中定义li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X;                             \###将t0的值写入pmpcfg0 CSR寄存器中csrw pmpcfg0, t0;                                                     \###按2^2字节(4字节)数据对齐.align 2;                                                             \
###标志1的具体位置
1:/*Configure MMU*/
/*SATP:Supervisor Address Translation and Protection (satp) Register*/
#define INIT_SATP                                                       \###将标志1的PC赋值给t0la t0, 1f;                                                            \###t0的值赋给mtveccsrw mtvec, t0;                                                       \###写CSR寄存器sptrb为0csrwi sptbr, 0;                                                       \###按2^2字节(4字节)数据对齐.align 2;                                                             \
###标志1的具体位置
1:###定义DELEGATE_NO_TRAPS段的内容,这是对应多模式情况下的
###将中断权限分配到其他模式中,不单单机器模式可以处理中断
#define DELEGATE_NO_TRAPS                                               \###将标志1的PC赋值给t0la t0, 1f;                                                            \###t0的值赋给mtveccsrw mtvec, t0;                                                       \###写CSR寄存器medeleg(异常)为0,如果没有这个CSR寄存器会产生异常csrwi medeleg, 0;                                                     \###写CSR寄存器mideleg(中断)为0,如果没有这个CSR寄存器会产生异常csrwi mideleg, 0;                                                     \###写CSR寄存器mie为0,清除中断使能csrwi mie, 0;                                                         \###按2^2字节(4字节)数据对齐.align 2;                                                             \
###标志1的具体位置
1:###定义RVTEST_ENABLE_SUPERVISOR段的内容
###SUPERVISOR模式的定义
#define RVTEST_ENABLE_SUPERVISOR                                        \li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1);                              \csrs mstatus, a0;                                                     \###将SIP_SSIP | SIP_STIP赋给a0li a0, SIP_SSIP | SIP_STIP;                                           \###将a0赋值给mideleg CSR寄存器,用于授权SUPERVISOR模式可以处理中断csrs mideleg, a0;                                                     \###定义RVTEST_ENABLE_MACHINE段的内容
### MACHINE模式的定义
#define RVTEST_ENABLE_MACHINE                                           \###将MSTATUS_MPP赋给a0,MSTATUS_MPP在encoding.h中定义li a0, MSTATUS_MPP;                                                   \###将a0的值赋给mstatuscsrs mstatus, a0;                                                     \###定义VTEST_FP_ENABLE段的内容
###浮点模式的定义
#define RVTEST_FP_ENABLE                                                \###将MSTATUS_FS & (MSTATUS_FS >> 1)赋给a0li a0, MSTATUS_FS & (MSTATUS_FS >> 1);                                \###将a0赋给mstatuscsrs mstatus, a0;                                                     \###将0写入到fcsr CSR寄存器中,如果核没有支持浮点功能,则不会存在fcsr,###写fcsr的行为会报异常csrwi fcsr, 0###定义RISCV_MULTICORE_DISABLE段的内容
###不使用多核的配置
#define RISCV_MULTICORE_DISABLE                                         \###读mhartid CSR寄存器的值,并赋给a0csrr a0, mhartid;                                                     \###判断a0的值,如果不等于0,则一直保持在标志1的位置,即多核情况下,###一直保持在标志1的位置,1b为向后找第一个数字为1的标志,也就是这条指令###若等于0,则为单核,可以进行下面的指令执行1: bnez a0, 1b###定义EXTRA_TVEC_USER、EXTRA_TVEC_MACHINE、
###EXTRA_INIT和EXTRA_INIT_TIMER,这些段虽然定义了,但没有内容,
###需要用到的自己补充汇编内容
#define EXTRA_TVEC_USER
#define EXTRA_TVEC_MACHINE
#define EXTRA_INIT
#define EXTRA_INIT_TIMER###定义NTERRUPT_HANDLER段内容,将跳到other_exception函数中
#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */###定义RVTEST_CODE_BEGIN段的内容
#define RVTEST_CODE_BEGIN                                               \###指令代码段.text.section .text.init;                                            \###按2^6(64字节)对齐.align  6;                                                      \###占个位置,后面有对stvec_handler定义的,就会覆盖.weak stvec_handler;                                            \###占个位置,后面有对mtvec_handler定义的,就会覆盖.weak mtvec_handler;                                            \### .global和.globl伪操作用于定义一个全局的符号,使得链接器能够全###局识别它,即一个程序文件中定义的符号能够被所有###其他程序文件可见。指定汇编程序入口为_start,即代码的最开始地方。.globl _start;                                                  \
_start:                                                                 \/* reset vector */                                              \###跳到reset_vector函数中j reset_vector;                                                 \###跳到asm_start函数中,这是我自己改的,不用那么多繁琐的步骤,直接跳/* j asm_start; */                                                \###按2^2(4字节)对齐.align 2;                                                       \
trap_vector:                                                            \/* test whether the test came from pass/fail */                 \###将mcasue的值赋给t5csrr t5, mcause;                                                \###将CAUSE_USER_ECALL值赋给t6li t6, CAUSE_USER_ECALL;                                        \###如果t5和t6相等,则跳到write_tohost函数中beq t5, t6, write_tohost;                                       \###将CAUSE_SUPERVISOR_ECALL值赋给t6li t6, CAUSE_SUPERVISOR_ECALL;                                  \###如果t5和t6相等,则跳到write_tohost函数中beq t5, t6, write_tohost;                                       \###将CAUSE_MACHINE_ECALL值赋给t6li t6, CAUSE_MACHINE_ECALL;                                     \###如果t5和t6相等,则跳到write_tohost函数中beq t5, t6, write_tohost;                                       \/* if an mtvec_handler is defined, jump to it */                \la t5, mtvec_handler;                                           \###如果没有定义mtvec_handler函数,则mtvec_handler为0,等于0则跳到标志1beqz t5, 1f;                                                    \jr t5;                                                          \/* was it an interrupt or an exception? */                      \###前面的异常/中断都不符合了,才跳到这,对mcause的值到t5中1:    csrr t5, mcause;                                                \###如果t5≥0,则跳到handle_exception中bgez t5, handle_exception;                                      \###如果连handle_exception都不是,那就跳到other_exception中INTERRUPT_HANDLER;                                              \
handle_exception:                                                       \/* we don't know how to handle whatever the exception was */    \###意思就是,这里需要你自己补充,如果想用的话other_exception:                                                      \/* some unhandlable exception occurred */                       \###意思就是,这里需要你自己补充,如果想用的话###利用TESTNUM和立即数1337进行或操作1:    ori TESTNUM, TESTNUM, 1337;                                     \### write_tohost函数write_tohost:                                                         \###将TESTNUM的值存到tohost的位置上sw TESTNUM, tohost, t5;                                         \###PC一直保持在当前位置,进入死循环j write_tohost;                                                 \
reset_vector:                                                           \###运行RISCV_MULTICORE_DISABLE的内容RISCV_MULTICORE_DISABLE;                                        \###运行INIT_SATP的内容,因为我生成的没有MMU,所以屏蔽了这句###如果不屏蔽,会产生异常,但也没有影响,因为异常处理的PC就是接下来的指令/*INIT_SATP;*/                                                  \###运行INIT_PMP的内容INIT_PMP;                                                       \###运行DELEGATE_NO_TRAPS的内容DELEGATE_NO_TRAPS;                                              \###因为运行DELEGATE_NO_TRAPS时产生了异常,所以下一句清除异常csrw mcause, 0;                                                 \###将0赋值给TESTNUM(gp)li TESTNUM, 0;                                                  \###将trap_vector的物理地址赋值给t0la t0, trap_vector;                                             \###将t0赋值给mtvec CSR寄存器csrw mtvec, t0;                                                 \###运行CHECK_XLEN的内容CHECK_XLEN;                                                     \/* if an stvec_handler is defined, delegate exceptions to it */ \###这里如果有定义stvec_handler就会进入下面的指令,没有就跳到标志1la t0, stvec_handler;                                           \beqz t0, 1f;                                                    \csrw stvec, t0;                                                 \###将一些特殊的中断或者异常,MMU相关,授权给其他模式处理li t0, (1 << CAUSE_LOAD_PAGE_FAULT) |                           \(1 << CAUSE_STORE_PAGE_FAULT) |                          \(1 << CAUSE_FETCH_PAGE_FAULT) |                          \(1 << CAUSE_MISALIGNED_FETCH) |                          \(1 << CAUSE_USER_ECALL) |                                \(1 << CAUSE_BREAKPOINT);                                 \csrw medeleg, t0;                                               \csrr t1, medeleg;                                               \bne t0, t1, other_exception;                                    \###将0写入mstatus CSR寄存器中
1:      csrwi mstatus, 0;                                               \###这句编译出来的是auipc   t0,0x0init;                                                           \###这个没有定义,所以是空的EXTRA_INIT;                                                     \###这个没有定义,所以是空的EXTRA_INIT_TIMER;                                               \###跳到标志1的位置赋值给t0la t0, 1f;                                                      \###将t0赋值给mepccsrw mepc, t0;                                                  \###将mhartid的值赋值给a0csrr a0, mhartid;                                               \###M模式returnmret;                                                           \
1://-----------------------------------------------------------------------
// End Macro
//-----------------------------------------------------------------------#define RVTEST_CODE_END                \
###UNIMP : C0001073. This is an alias for CSRRW x0, cycle, x0. Since cycle is a
###read-only CSR, then #(whether this CSR exists or not) an attempt to write into
###it will generate an illegal instruction #exception. This 32-bit form of UNIMP is
###emitted when targeting a system without the C #extension, or when the .option
###norvc directive is used.                                         unimp//-----------------------------------------------------------------------
// Pass/Fail Macro
//-----------------------------------------------------------------------#define RVTEST_PASS                                                     \###执行fence指令,可以清楚ICache内容;将1赋值给gp;最后执行ecallfence;                                                          \li TESTNUM, 1;                                                  \ecall#define TESTNUM gp
#define RVTEST_FAIL                                                     \###执行fence指令fence;                                                          \###如何TESTNUM等于0,则一直停在这,不为0则执行下面的程序
1:      beqz TESTNUM, 1b;                                               \###将TESTNUM的值逻辑左移1位,并重新赋值给TESTNUMsll TESTNUM, TESTNUM, 1;                                        \###将TESTNUM的值与1或,并重新赋值给TESTNUMor TESTNUM, TESTNUM, 1;                                         \ecall//-----------------------------------------------------------------------
// Data Section Macro
//-----------------------------------------------------------------------###定义了EXTRA_DATA,但是是空的
#define EXTRA_DATA###此段基本是空的,需要用到的,要自己添加内容
#define RVTEST_DATA_BEGIN                                               \EXTRA_DATA                                                      \###将之前的段设置保存,并将当前的段设置改名.tohost.pushsection .tohost,"aw",@progbits;                            \.align 6; .global tohost; tohost: .dword 0;                     \.align 6; .global fromhost; fromhost: .dword 0;                 \###恢复之前的段设置.popsection;                                                    \.align 4; .global begin_signature; begin_signature:#define RVTEST_DATA_END .align 4; .global end_signature; end_signature:#endif

2.3.3 asm.lk:这个文件就是/riscv-tests/env/p/link.ld文件,只是我改了名字。

SECTIONS
{/*. = 0x80000000;*/###这里我修改了,因为我想它从我的ROM直接执行,我的ROM地址是0x10000. = 0x00010000;.text.init : { *(.text.init) }. = ALIGN(0x1000);.tohost : { *(.tohost) }. = ALIGN(0x1000);.text : { *(.text) }. = ALIGN(0x1000);.data : { *(.data) }.bss : { *(.bss) }_end = .;
}

2.4 bulid:这个目录最主要的是Makefile脚本,用于调用工具链编译asm。我只贴部分代码,是生成elf的代码,生成bin、hex和dump的方法大家参考/riscv-tests/benchmarks/Makefile。
部分代码:

#--------------------------------------------------------------------
# author    :   x
# data  :   2019.4.2
# name  :   project compiler for rocket-chip
#--------------------------------------------------------------------proj_name ?= add#--------------------------------------------------------------------
# Build rules
#--------------------------------------------------------------------RISCV_PREFIX ?= ../toolchain/bin/riscv32-unknown-elf-
RISCV_GCC ?= $(RISCV_PREFIX)gcc
RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf
RISCV_LINK_OPTS ?= -static -nostdlib -nostartfiles -lm -lgcc -T ../common/asm.ld
SOURCE_FILE ?= ../common ../asm/$(proj_name)/*.S#--------------------------------------------------------------------
# Object
#--------------------------------------------------------------------default: make allelf:$(RISCV_GCC) $(RISCV_GCC_OPTS) -o $(proj_name)/$(proj_name).elf $(SOURCE_FILE) $(RISCV_LINK_OPTS)all: elf

3.反汇编文件

add/add.elf:     file format elf32-littleriscvDisassembly of section .text.init:00010000 <_start>:
_start():10000: a081                    j   10040 <reset_vector>10002:    0001                    nop00010004 <trap_vector>:
trap_vector():10004:    34202f73            csrr    t5,mcause10008: 4fa1                    li  t6,81000a:  03ff0663            beq t5,t6,10036 <write_tohost>1000e:  4fa5                    li  t6,910010:  03ff0363            beq t5,t6,10036 <write_tohost>10014:  4fad                    li  t6,1110016: 03ff0063            beq t5,t6,10036 <write_tohost>1001a:  ffff0f17            auipc   t5,0xffff01001e:    fe6f0f13            addi    t5,t5,-26 # 0 <_start-0x10000>10022:  000f0363            beqz    t5,10028 <trap_vector+0x24>10026:    8f02                    jr  t510028:    34202f73            csrr    t5,mcause1002c: 000f5363            bgez    t5,10032 <handle_exception>10030: a009                    j   10032 <handle_exception>00010032 <handle_exception>:
handle_exception():10032:   5391e193            ori gp,gp,133700010036 <write_tohost>:
write_tohost():10036:   00001f17            auipc   t5,0x11003a:    fc3f2523            sw  gp,-54(t5) # 11000 <tohost>1003e: bfe5                    j   10036 <write_tohost>00010040 <reset_vector>:
reset_vector():10040:   f1402573            csrr    a0,mhartid10044:    e101                    bnez    a0,10044 <reset_vector+0x4>10046:    00000297            auipc   t0,0x01004a:    01a28293            addi    t0,t0,26 # 10060 <reset_vector+0x20>1004e:   30529073            csrw    mtvec,t010052:  52fd                    li  t0,-110054: 3b029073            csrw    pmpaddr0,t010058:   42fd                    li  t0,311005a: 3a029073            csrw    pmpcfg0,t01005e:    0001                    nop10060:   00000297            auipc   t0,0x010064:    01828293            addi    t0,t0,24 # 10078 <reset_vector+0x38>10068:   30529073            csrw    mtvec,t01006c:  30205073            csrwi   medeleg,010070: 30305073            csrwi   mideleg,010074: 30405073            csrwi   mie,010078: 34205073            csrwi   mcause,01007c:  4181                    li  gp,01007e:  00000297            auipc   t0,0x010082:    f8628293            addi    t0,t0,-122 # 10004 <trap_vector>10086:    30529073            csrw    mtvec,t01008a:  4505                    li  a0,11008c:  057e                    slli    a0,a0,0x1f1008e:    00054763            bltz    a0,1009c <reset_vector+0x5c>10092:   0ff0000f            fence10096: 4185                    li  gp,110098:  00000073            ecall1009c: ffff0297            auipc   t0,0xffff0100a0:    f6428293            addi    t0,t0,-156 # 0 <_start-0x10000>100a4: 00028e63            beqz    t0,100c0 <reset_vector+0x80>100a8:   10529073            csrw    stvec,t0100ac:  0000b2b7            lui t0,0xb100b0:    10928293            addi    t0,t0,265 # b109 <_start-0x4ef7>100b4:    30229073            csrw    medeleg,t0100b8:    30202373            csrr    t1,medeleg100bc:    f6629be3            bne t0,t1,10032 <handle_exception>100c0:  30005073            csrwi   mstatus,0100c4: 00000297            auipc   t0,0x0100c8:    01428293            addi    t0,t0,20 # 100d8 <asm_start>100cc:    34129073            csrw    mepc,t0100d0:   f1402573            csrr    a0,mhartid100d4:    30200073            mret000100d8 <asm_start>:
asm_start():100d8:  aaaab5b7            lui a1,0xaaaab100dc:    aaa58593            addi    a1,a1,-1366 # aaaaaaaa <_end+0xaaa98aaa>100e0:   22222537            lui a0,0x22222100e4:    22250513            addi    a0,a0,546 # 22222222 <_end+0x22210222>100e8: 00a58633            add a2,a1,a0100ec:  70000737            lui a4,0x70000100f0:    00470813            addi    a6,a4,4 # 70000004 <_end+0x6ffee004>100f4:   00c82023            sw  a2,0(a6)100f8:  0ff00793            li  a5,255100fc:    00f72023            sw  a5,0(a4)...Disassembly of section .tohost:00011000 <tohost>:...00011040 <fromhost>:

4.仿真测试

在说明仿真前,先贴部分TB中的代码,此代码用于自动停止VCS仿真。
具体的操作是CPU利用总线往0x7000_0000的地址写0xFF的值,然后TB就会执行$finish。
TB的代码是:

  /**************************//*    download memory     *//**************************/initial begin#100 $readmemh("../compiler/build/add/add.hex",ldut.bootrom.rom);end/**************************//*    capture finish      *//**************************/always @* beginif((mmio_axi4_0_aw_bits_addr == 31'h70000000) && mmio_axi4_0_aw_ready && mmio_axi4_0_aw_valid && (mmio_axi4_0_w_bits_data == 32'hFF)) begin#10 $finish(2);endend

汇编中对应的代码是:

 lui  a4, 0x70000li   a5, 255sw   a5, 0(a4)

接下来是仿真的波形分析。

如何建立自己的RISC-V编译环境--汇编?相关推荐

  1. 建立WD mycloud 4.x 编译环境生成transmission-daemon

    下载 WD已经将mycloud的固件包开源,大家可以去 http://support.wdc.com/downloads.aspx?FW&lang=en 网站下载,选择"Dowanl ...

  2. 怒飞垂云视频教程 一、建立编译环境

    本文讲述如何建立APM飞控固件的编译环境 原文链接:http://www.nufeichuiyun.com/?p=237

  3. Android-黄油刀ButterKnife依赖注入源码,APT自动生成代码,利用javapoet语法搭建编译环境,建立MVP中空指针的保护机制

    基本环境搭建(auto&javapoet) 一.API采取背景,举例 主要为了解决客户端MVP架构中,V层和P层生命周期不同步时,生成空View保护性逻辑. 之前需要手写空View的代码,现在 ...

  4. ubuntu上建立mini2440 qt编译环境

    参考mini2440手册,从5.3章开始建立交叉编译环境.跟着流程走,在设置环境变量的时候,发现ubuntu的root文件夹不可进入,修改权限进入修改.bashrc文件发现重启后不起作用.为了不每次开 ...

  5. blueJ连接mysql_快速建立Servlet和JSP的运行、调试和编译环境_MySQL

    servlet 相信很多刚开始学习Servlet和JSP的朋友都有一个困扰,就是如何快速方便的建立一个Servlet和JSP的运行.调试和编译环境.本人现在正在国外攻读MIT(Master of In ...

  6. blueJ连接mysql_快速建立Servlet和JSP的运行、调试和编译环境

    快速建立Servlet和JSP的运行.调试和编译环境 更新时间:2006年10月13日 00:00:00   作者: 相信很多刚开始学习Servlet和JSP的朋友都有一个困扰,就是如何快速方便的建立 ...

  7. 建立基于Equinox的OSGi编译与调试环境

    在上一篇博客中我按照书中介绍搭建了第一种开发环境(控制台形式,用jar方式启动):现在我们继续跟着书上搭建第二种开发环境,在<深入理解OSGi---Equinox原理.应用于最佳实践>第1 ...

  8. sublime text 3 快捷键大全以及配置编译环境

    Sublime Text 3 快捷键精华版 Ctrl+Shift+P:打开命令面板 Ctrl+P:搜索项目中的文件 Ctrl+G:跳转到第几行 Ctrl+W:关闭当前打开文件 Ctrl+Shift+W ...

  9. Xp下的程序编译成linux,WinXP下打造自己的linux 0.11简易编译环境(原创)

    http://caiwei8888.blog.163.com/blog/static/3017424120101913353856/ 学习赵炯博士的<linux 0.11 内核完全注释>, ...

最新文章

  1. 从谷歌辞职后,作为独立开发者的第三年,我从年入 3 万做到了年入 40 万
  2. dz 数据表分析!!!
  3. centos打显卡驱动命令_ubuntu16.04安装显卡以及驱动经验
  4. 最高一万星!GitHub 标星最多的 40 篇 ICLR2020 计算机视觉论文合集,附打包下载
  5. 三角网导线平差实例_导线测量平差实例
  6. 【iVX 初级工程师培训教程 10篇文拿证】05 画布及飞机大战游戏制作
  7. java生成j动态页面_zk动态产生多个页面的例子代码
  8. webserver 交互方式说明
  9. 湖南2021普通高考专业成绩查询,2021年湖南高考成绩查询时间 高考成绩查询入口...
  10. 方法同时使用微服务调用文件上传方法以及调用另一微服务的方法时报错failed to parse multipart servlet Request
  11. 南京大学信号与系统851考研上岸经验分享
  12. php宿舍管理系统毕业论文,学生宿舍管理系统(源码+论文)
  13. vuecli3代码压缩混淆使用uglifyjs压缩JS
  14. 论文笔记—RGB-D SLAM in Dynamic Environments Using Static Point Weighting
  15. 如何防止条码流水号打印出现重码漏码错码的防呆检错系统?
  16. 【矩阵论】6. 正规方程与矩阵方程求解
  17. MPEG-4与H264区别,编码及应用
  18. 小程序微信授权登录服务器异常,微信小程序授权登录流程(强制绑定手机号码)...
  19. 兔子数列 - C语言
  20. 10.statement对象实例(executeUpdate方法以及executeQuery方法),JDBC工具类编写

热门文章

  1. CSS教程(一)认识CSS
  2. 1到10加法创新图片-走迷宫_纽约楼市寒冬,曼哈顿房价创新低,为何上季度交易却反弹?...
  3. Java实现图片切割或图片裁剪
  4. 节省 3/4 的设计时间:14个设计神器
  5. 如何用 Python 执行常见的 Excel 和 SQL 任务
  6. 全景漫游软件|全景漫游制作软件|三维全景软件|
  7. 第四周毛概课学习心得
  8. centos 安装Jitsi架设_1.2 VMware虚拟机安装《LINUX-centos7-操作系统入门到精通》
  9. Vue中使用Fullcalendar日历开发日程安排
  10. 温故知新:基于R语言的群体药代动力学数据探索