1、阅读相关文档和文件,研究了仿真命令的执行过程,以及具体的仿真代码。
2、观察了rv32um-p-mul
的波形,分析了testcase的执行情况。
与仿真有关指令均在以下目录中执行:
${PWD}/n200_rls_pkg/n200/vsim
其中${PWD}
代表存放项目的目录。
根据Nuclei_Processor_Integration_Guide.pdf
文档中的说明,在执行仿真之前,我们需要执行make install
指令与make compile
指令,最后才执行仿真指令make run_test TESTNAME=rv32um-p-mul
。
所以如果需要了解指令执行过程就需要阅读vsim/Makefile
与vsim/run/Makefile
中的内容。
/vsim/Makefile
SIM_DIR := ${PWD}
RUN_DIR := ${PWD}/run
CORE := n200
TESTNAME := rv${XLEN}ui-p-lb
TESTCASE := ${RUN_DIR}/../../riscv-tests/isa/generated/${TESTNAME}
...
defines: ${SIM_DIR}/../design/core/*_defines.v
python bin/v2h.py $< ${core_name}_$@.h
cp $< ${SIM_DIR}/../tb/${core_name}_$@.v
install: ${RUN_DIR} defines
mkdir -p ${SIM_DIR}/install/tb
cp ${SIM_DIR}/../tb/* ${SIM_DIR}/install/tb/ -rf
find ${SIM_DIR}/../design/ -name *.v >& ${RUN_DIR}/rtlonly_flist
find ${SIM_DIR}/../design/core/ -name *.v >& ${RUN_DIR}/core_flist
compile: ${RUN_DIR}
make compile CORE=${CORE} RUN_DIR=${RUN_DIR} -C ${RUN_DIR} TESTCASE=${TESTCASE} COVERAGE=${COVERAGE}
wave: ${RUN_DIR}
make wave CORE=${CORE} TESTCASE=${TESTCASE} RUN_DIR=${RUN_DIR} -C ${RUN_DIR}
run_test: compile
make run CORE=${CORE} WFI_FORCE_IRQ=${WFI_FORCE_IRQ} FORCE_DELAY=${FORCE_DELAY} FORCE_IRQ=${FORCE_IRQ} FORCE_ECC=${FORCE_ECC} DUMPWAVE=${DUMPWAVE} TESTCASE=${TESTCASE} SEED=${SEED} RUN_DIR=${RUN_DIR} -C ${RUN_DIR} COVERAGE=${COVERAGE}
...
/vsim/run/Makefile
RUN_DIR := ${PWD}
TESTCASE := ${RUN_DIR}/../../riscv-tests/isa/generated/${TESTNAME}
SIM_TOOL := vcs
SIM_OPTIONS := +v2k -sverilog -notice -q +lint=all,noSVA-NSVU,noPCTIO-L,noVCDE,noUI,noSVA-CE,noSVA-DIU,noPORTFRC,noSVA-ICP,noNS -debug_access+all -full64 -timescale=1ns/10ps
SIM_OPTIONS += +incdir+${VSRC_DIR}/core+${VSRC_DIR}/soc+${VTB_DIR}
SIM_OPTIONS += +define+DISABLE_SV_ASSERTION
SIM_OPTIONS += -l compile.log
SIM_EXEC := ${RUN_DIR}/simv +plusarg_save +ntb_random_seed=${SEED}
ifeq ($(WAVEFSDB),1)
WAV_TOOL := verdi
else
WAV_TOOL := dve
endif
WAV_OPTIONS := +v2k -sverilog
ifeq ($(WAVEFSDB),1)
WAV_PFIX := fsdb
else
WAV_PFIX := vpd
endif
TESTNAME := $(notdir $(patsubst %.dump,%,${TESTCASE}.dump))
TEST_RUNDIR := ${TESTNAME}
...
compile.flg: ${RTL_V_FILES} ${TB_V_FILES}
@-rm -rf compile.flg
${SIM_TOOL} ${SIM_OPTIONS} ${RTL_V_FILES} ${TB_V_FILES} ;
touch compile.flg
compile: compile.flg
wave:
gvim ${TESTCASE}.dump &
ifeq ($(WAVEFSDB), 1)
${WAV_TOOL} ${WAV_OPTIONS} +incdir+"${VSRC_DIR}/core"+"${VSRC_DIR}/soc"+"${VTB_DIR}" ${RTL_V_FILES} ${TB_V_FILES} -ssf ${TEST_RUNDIR}/tb_top.${WAV_PFIX} -top tb_top -nologo &
else
${WAV_TOOL} -vpd ${TEST_RUNDIR}/tb_top.${WAV_PFIX} &
endif
run: compile
rm -rf ${TEST_RUNDIR}
mkdir -p ${TEST_RUNDIR}
cd ${TEST_RUNDIR}; ${SIM_EXEC} ${SIMV_FLAGS} +WFI_FORCE_IRQ=${WFI_FORCE_IRQ} +FORCE_DELAY=${FORCE_DELAY} +FORCE_IRQ=${FORCE_IRQ} +FORCE_ECC=${FORCE_ECC} +FORCE_RESP_ERR=${FORCE_RESP_ERR} +DUMPWAVE=${DUMPWAVE} +WAVEFSDB=${WAVEFSDB} +TESTCASE=${TESTCASE} +SEED=${SEED} |& tee ${TESTNAME}.log; cd ${RUN_DIR};
...
make install
指令创建了${RUN_DIR}
地址,利用python代码
与defines.v
生成defines.h
文件,将testbench文件复制到/vsim/install/tb
目录下,并将n200的verilog源码链接到${RUN_DIR}
下。
make compile
指令执行的地址位于${RUN_DIR}
下。执行make compile
首先要生成compile.flg
文件,在生成compile.flg
文件过程中设置好仿真工具${SIM_TOOL}
、仿真参数${SIM_OPTIONS}
、n200核心rtl文件${RTL_V_FILES}
、以及testbench文件${TB_V_FILES}
,最后修改compile.flg
文件的时间属性。
make run_test TESTNAME=rv32um-p-mul
仿真指令执行的地址同样位于${RUN_DIR}
下。相当于执行了/vsim/run/Makefile
内的run
伪指令。此指令可以创建测试地址${TEST_RUNDIR}
并在此地址下利用${SIM_EXEC}
执行仿真。最后将屏幕上的打印信息保存到n200.log
内。
如果继续执行make wave TESTNAME=rv32um-p-mul
仿真指令则可以将run_test
生成的波形信息利用${WAV_TOOL}
显示出来。
从Nuclei_Processor_Integration_Guide.pdf
文档中可以得知,testcase的源码位于如下位置:
${PWD}/n200_rls_pkg/n200/riscv-tests/isa_origs/rv32um/
其中${PWD}
代表存放项目的目录。
在此路径下,mul.S
文件就是rv32um-p-mul
的源码了。
/rv32um/mul.S
# See LICENSE for license details.
#*****************************************************************************
# mul.S
#-----------------------------------------------------------------------------
#
# Test mul instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
#include "test_register.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
#li t3, 0x0;
#li t4, 0x2;
#ifndef N200_CFG_NO_MULDIV
test_start:
TEST_RR_OP(32, mul, 0x00001200, 0x00007e00, 0xb6db6db7 );
TEST_RR_OP(33, mul, 0x00001240, 0x00007fc0, 0xb6db6db7 );
TEST_RR_OP( 2, mul, 0x00000000, 0x00000000, 0x00000000 );
TEST_RR_OP( 3, mul, 0x00000001, 0x00000001, 0x00000001 );
TEST_RR_OP( 4, mul, 0x00000015, 0x00000003, 0x00000007 );
TEST_RR_OP( 5, mul, 0x00000000, 0x00000000, 0xffff8000 );
TEST_RR_OP( 6, mul, 0x00000000, 0x80000000, 0x00000000 );
TEST_RR_OP( 7, mul, 0x00000000, 0x80000000, 0xffff8000 );
TEST_RR_OP(30, mul, 0x0000ff7f, 0xaaaaaaab, 0x0002fe7d );
TEST_RR_OP(31, mul, 0x0000ff7f, 0x0002fe7d, 0xaaaaaaab );
TEST_RR_OP(34, mul, 0x00000000, 0xff000000, 0xff000000 );
TEST_RR_OP(35, mul, 0x00000001, 0xffffffff, 0xffffffff );
TEST_RR_OP(36, mul, 0xffffffff, 0xffffffff, 0x00000001 );
TEST_RR_OP(37, mul, 0xffffffff, 0x00000001, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 8, mul, 143, 13, 11 );
TEST_RR_SRC2_EQ_DEST( 9, mul, 154, 14, 11 );
TEST_RR_SRC12_EQ_DEST( 10, mul, 169, 13 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 11, 0, mul, 143, 13, 11 );
TEST_RR_DEST_BYPASS( 12, 1, mul, 154, 14, 11 );
TEST_RR_DEST_BYPASS( 13, 2, mul, 165, 15, 11 );
TEST_RR_SRC12_BYPASS( 14, 0, 0, mul, 143, 13, 11 );
TEST_RR_SRC12_BYPASS( 15, 0, 1, mul, 154, 14, 11 );
TEST_RR_SRC12_BYPASS( 16, 0, 2, mul, 165, 15, 11 );
TEST_RR_SRC12_BYPASS( 17, 1, 0, mul, 143, 13, 11 );
TEST_RR_SRC12_BYPASS( 18, 1, 1, mul, 154, 14, 11 );
TEST_RR_SRC12_BYPASS( 19, 2, 0, mul, 165, 15, 11 );
TEST_RR_SRC21_BYPASS( 20, 0, 0, mul, 143, 13, 11 );
TEST_RR_SRC21_BYPASS( 21, 0, 1, mul, 154, 14, 11 );
TEST_RR_SRC21_BYPASS( 22, 0, 2, mul, 165, 15, 11 );
TEST_RR_SRC21_BYPASS( 23, 1, 0, mul, 143, 13, 11 );
TEST_RR_SRC21_BYPASS( 24, 1, 1, mul, 154, 14, 11 );
TEST_RR_SRC21_BYPASS( 25, 2, 0, mul, 165, 15, 11 );
TEST_RR_ZEROSRC1( 26, mul, 0, 31 );
TEST_RR_ZEROSRC2( 27, mul, 0, 32 );
TEST_RR_ZEROSRC12( 28, mul, 0 );
TEST_RR_ZERODEST( 29, mul, 33, 34 );
# SWITCH_TO_UMODE(mstatus , mepc , 0xffffffff, 0xff);
#check_mode:
# addi t3, t3, 1;
# bne t4, t4, test_start;
#endif
j pass
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END
从文件中可以看出测试从大分类上一共分为了三个方面Arithmetic tests、Source/Destination tests、Bypassing tests。在此文件中用了许多宏定义的功能,比如TEST_RR_OP
,此类宏定义可以在#include "test_macros.h"
中查找其源码。
test_macros.h
#define TEST_CASE( testnum, testreg, correctval, code... ) \
test_ ## testnum: \
code; \
li a0, MASK_XLEN(correctval); \
li TESTNUM, testnum; \
bne testreg, a0, fail;
...
#define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
TEST_CASE( testnum, a1, result, \
li x1, MASK_XLEN(val1); \
li a2, MASK_XLEN(val2); \
inst a1, x1, a2; \
)
#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
TEST_CASE( testnum, x1, result, \
li x1, MASK_XLEN(val1); \
li a2, MASK_XLEN(val2); \
inst x1, x1, a2; \
)
#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
TEST_CASE( testnum, a2, result, \
li x1, MASK_XLEN(val1); \
li a2, MASK_XLEN(val2); \
inst a2, x1, a2; \
)
#define TEST_RR_SRC12_EQ_DEST( testnum, inst, result, val1 ) \
TEST_CASE( testnum, x1, result, \
li x1, MASK_XLEN(val1); \
inst x1, x1, x1; \
)
#define TEST_RR_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, val2 ) \
TEST_CASE( testnum, x6, result, \
li x4, 0; \
1: li x1, MASK_XLEN(val1); \
li a2, MASK_XLEN(val2); \
inst a1, x1, a2; \
TEST_INSERT_NOPS_ ## nop_cycles \
addi x6, a1, 0; \
addi x4, x4, 1; \
li x5, 2; \
bne x4, x5, 1b \
)
#define TEST_RR_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
TEST_CASE( testnum, a1, result, \
li x4, 0; \
1: li x1, MASK_XLEN(val1); \
TEST_INSERT_NOPS_ ## src1_nops \
li a2, MASK_XLEN(val2); \
TEST_INSERT_NOPS_ ## src2_nops \
inst a1, x1, a2; \
addi x4, x4, 1; \
li x5, 2; \
bne x4, x5, 1b \
)
#define TEST_RR_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
TEST_CASE( testnum, a1, result, \
li x4, 0; \
1: li a2, MASK_XLEN(val2); \
TEST_INSERT_NOPS_ ## src1_nops \
li x1, MASK_XLEN(val1); \
TEST_INSERT_NOPS_ ## src2_nops \
inst a1, x1, a2; \
addi x4, x4, 1; \
li x5, 2; \
bne x4, x5, 1b \
)
#define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
TEST_CASE( testnum, a2, result, \
li x1, MASK_XLEN(val); \
inst a2, x0, x1; \
)
#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
TEST_CASE( testnum, a2, result, \
li x1, MASK_XLEN(val); \
inst a2, x1, x0; \
)
#define TEST_RR_ZEROSRC12( testnum, inst, result ) \
TEST_CASE( testnum, x1, result, \
inst x1, x0, x0; \
)
#define TEST_RR_ZERODEST( testnum, inst, val1, val2 ) \
TEST_CASE( testnum, x0, 0, \
li x1, MASK_XLEN(val1); \
li a2, MASK_XLEN(val2); \
inst x0, x1, a2; \
)
...
#-----------------------------------------------------------------------
# Pass and fail code (assumes test num is in TESTNUM)
#-----------------------------------------------------------------------
#define TEST_PASSFAIL \
bne x0, TESTNUM, pass; \
fail: \
RVTEST_FAIL; \
pass: \
RVTEST_PASS \
在随后生成的.dump文件中,mul.S内宏定义的功能都会被替换为test_macros.h
内的代码。包括最后的TEST_PASSFAIL
也会被替换。所以可以看到在.dump文件内的内容如下:
.dump
RVTEST_RV32U
RVTEST_CODE_BEGIN
80000000: 7d0023f3 csrr t2,0x7d0
80000004: 2003f393 andi t2,t2,512
80000008: 00039a63 bnez t2,8000001c
8000000c: 342023f3 csrr t2,mcause
80000010: 7ff3f393 andi t2,t2,2047
80000014: 0013c393 xori t2,t2,1
80000018: 22038863 beqz t2,80000248
8000001c :
8000001c: 4081 li ra,0
8000001e: 4101 li sp,0
80000020: 4181 li gp,0
80000022: 4201 li tp,0
80000024: 4281 li t0,0
80000026: 4315 li t1,5
80000028: 4399 li t2,6
8000002a: 441d li s0,7
8000002c: 44a1 li s1,8
8000002e: 4525 li a0,9
80000030: 45a9 li a1,10
80000032: 462d li a2,11
80000034: 46b1 li a3,12
80000036: 4735 li a4,13
80000038: 47b9 li a5,14
8000003a: 483d li a6,15
8000003c: 48c1 li a7,16
8000003e: 4945 li s2,17
80000040: 49c9 li s3,18
80000042: 4a4d li s4,19
80000044: 4ad1 li s5,20
80000046: 4b55 li s6,21
80000048: 4bd9 li s7,22
8000004a: 4c5d li s8,23
8000004c: 4ce1 li s9,24
8000004e: 4d65 li s10,25
80000050: 4de9 li s11,26
80000052: 4e6d li t3,27
80000054: 4ef1 li t4,28
80000056: 4ff5 li t6,29
80000058: 0c40106f j 8000111c
...
#ifndef N200_CFG_NO_MULDIV
test_start:
TEST_RR_OP(32, mul, 0x00001200, 0x00007e00, 0xb6db6db7 );
800012ca: 000080b7 lui ra,0x8
800012ce: e0008093 addi ra,ra,-512 # 7e00 <__stack_size+0x7600>
800012d2: b6db7637 lui a2,0xb6db7
800012d6: db760613 addi a2,a2,-585 # b6db6db7 <_sp+0x36da6db7>
800012da: 02c085b3 mul a1,ra,a2
800012de: 00001537 lui a0,0x1
800012e2: 20050513 addi a0,a0,512 # 1200 <__stack_size+0xa00>
800012e6: 02000213 li tp,32
800012ea: 36a59d63 bne a1,a0,80001664
...
80001416 :
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 8, mul, 143, 13, 11 );
80001416: 40b5 li ra,13
80001418: 462d li a2,11
8000141a: 02c080b3 mul ra,ra,a2
8000141e: 08f00513 li a0,143
80001422: 4221 li tp,8
80001424: 24a09063 bne ra,a0,80001664
80001428 :
TEST_RR_SRC2_EQ_DEST( 9, mul, 154, 14, 11 );
80001428: 40b9 li ra,14
8000142a: 462d li a2,11
8000142c: 02c08633 mul a2,ra,a2
80001430: 09a00513 li a0,154
80001434: 4225 li tp,9
80001436: 22a61763 bne a2,a0,80001664
8000143a :
TEST_RR_SRC12_EQ_DEST( 10, mul, 169, 13 );
8000143a: 40b5 li ra,13
8000143c: 021080b3 mul ra,ra,ra
80001440: 0a900513 li a0,169
80001444: 4229 li tp,10
80001446: 20a09f63 bne ra,a0,80001664
8000144a :
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 11, 0, mul, 143, 13, 11 );
8000144a: 4201 li tp,0
8000144c: 40b5 li ra,13
8000144e: 462d li a2,11
80001450: 02c085b3 mul a1,ra,a2
80001454: 00058313 mv t1,a1
80001458: 0205 addi tp,tp,1
8000145a: 4289 li t0,2
8000145c: fe5218e3 bne tp,t0,8000144c
80001460: 08f00513 li a0,143
80001464: 422d li tp,11
80001466: 1ea31f63 bne t1,a0,80001664
8000146a :
TEST_RR_DEST_BYPASS( 12, 1, mul, 154, 14, 11 );
8000146a: 4201 li tp,0
8000146c: 40b9 li ra,14
8000146e: 462d li a2,11
80001470: 02c085b3 mul a1,ra,a2
80001474: 0001 nop
80001476: 00058313 mv t1,a1
8000147a: 0205 addi tp,tp,1
8000147c: 4289 li t0,2
8000147e: fe5217e3 bne tp,t0,8000146c
80001482: 09a00513 li a0,154
80001486: 4231 li tp,12
80001488: 1ca31e63 bne t1,a0,80001664
8000148c :
TEST_RR_DEST_BYPASS( 13, 2, mul, 165, 15, 11 );
8000148c: 4201 li tp,0
8000148e: 40bd li ra,15
80001490: 462d li a2,11
80001492: 02c085b3 mul a1,ra,a2
80001496: 0001 nop
80001498: 0001 nop
8000149a: 00058313 mv t1,a1
8000149e: 0205 addi tp,tp,1
800014a0: 4289 li t0,2
800014a2: fe5216e3 bne tp,t0,8000148e
800014a6: 0a500513 li a0,165
800014aa: 4235 li tp,13
800014ac: 1aa31c63 bne t1,a0,80001664
800014b0 :
TEST_RR_SRC12_BYPASS( 14, 0, 0, mul, 143, 13, 11 );
800014b0: 4201 li tp,0
800014b2: 40b5 li ra,13
800014b4: 462d li a2,11
800014b6: 02c085b3 mul a1,ra,a2
800014ba: 0205 addi tp,tp,1
800014bc: 4289 li t0,2
800014be: fe521ae3 bne tp,t0,800014b2
800014c2: 08f00513 li a0,143
800014c6: 4239 li tp,14
800014c8: 18a59e63 bne a1,a0,80001664
800014cc :
TEST_RR_SRC12_BYPASS( 15, 0, 1, mul, 154, 14, 11 );
800014cc: 4201 li tp,0
800014ce: 40b9 li ra,14
800014d0: 462d li a2,11
800014d2: 0001 nop
800014d4: 02c085b3 mul a1,ra,a2
800014d8: 0205 addi tp,tp,1
800014da: 4289 li t0,2
800014dc: fe5219e3 bne tp,t0,800014ce
800014e0: 09a00513 li a0,154
800014e4: 423d li tp,15
800014e6: 16a59f63 bne a1,a0,80001664
800014ea :
TEST_RR_SRC12_BYPASS( 16, 0, 2, mul, 165, 15, 11 );
800014ea: 4201 li tp,0
800014ec: 40bd li ra,15
800014ee: 462d li a2,11
800014f0: 0001 nop
800014f2: 0001 nop
800014f4: 02c085b3 mul a1,ra,a2
800014f8: 0205 addi tp,tp,1
800014fa: 4289 li t0,2
800014fc: fe5218e3 bne tp,t0,800014ec
80001500: 0a500513 li a0,165
80001504: 4241 li tp,16
80001506: 14a59f63 bne a1,a0,80001664
8000150a :
TEST_RR_SRC12_BYPASS( 17, 1, 0, mul, 143, 13, 11 );
8000150a: 4201 li tp,0
8000150c: 40b5 li ra,13
8000150e: 0001 nop
80001510: 462d li a2,11
80001512: 02c085b3 mul a1,ra,a2
80001516: 0205 addi tp,tp,1
80001518: 4289 li t0,2
8000151a: fe5219e3 bne tp,t0,8000150c
8000151e: 08f00513 li a0,143
80001522: 4245 li tp,17
80001524: 14a59063 bne a1,a0,80001664
80001528 :
TEST_RR_SRC12_BYPASS( 18, 1, 1, mul, 154, 14, 11 );
80001528: 4201 li tp,0
8000152a: 40b9 li ra,14
8000152c: 0001 nop
8000152e: 462d li a2,11
80001530: 0001 nop
80001532: 02c085b3 mul a1,ra,a2
80001536: 0205 addi tp,tp,1
80001538: 4289 li t0,2
8000153a: fe5218e3 bne tp,t0,8000152a
8000153e: 09a00513 li a0,154
80001542: 4249 li tp,18
80001544: 12a59063 bne a1,a0,80001664
80001548 :
TEST_RR_SRC12_BYPASS( 19, 2, 0, mul, 165, 15, 11 );
80001548: 4201 li tp,0
8000154a: 40bd li ra,15
8000154c: 0001 nop
8000154e: 0001 nop
80001550: 462d li a2,11
80001552: 02c085b3 mul a1,ra,a2
80001556: 0205 addi tp,tp,1
80001558: 4289 li t0,2
8000155a: fe5218e3 bne tp,t0,8000154a
8000155e: 0a500513 li a0,165
80001562: 424d li tp,19
80001564: 10a59063 bne a1,a0,80001664
80001568 :
TEST_RR_SRC21_BYPASS( 20, 0, 0, mul, 143, 13, 11 );
80001568: 4201 li tp,0
8000156a: 462d li a2,11
8000156c: 40b5 li ra,13
8000156e: 02c085b3 mul a1,ra,a2
80001572: 0205 addi tp,tp,1
80001574: 4289 li t0,2
80001576: fe521ae3 bne tp,t0,8000156a
8000157a: 08f00513 li a0,143
8000157e: 4251 li tp,20
80001580: 0ea59263 bne a1,a0,80001664
80001584 :
TEST_RR_SRC21_BYPASS( 21, 0, 1, mul, 154, 14, 11 );
80001584: 4201 li tp,0
80001586: 462d li a2,11
80001588: 40b9 li ra,14
8000158a: 0001 nop
8000158c: 02c085b3 mul a1,ra,a2
80001590: 0205 addi tp,tp,1
80001592: 4289 li t0,2
80001594: fe5219e3 bne tp,t0,80001586
80001598: 09a00513 li a0,154
8000159c: 4255 li tp,21
8000159e: 0ca59363 bne a1,a0,80001664
800015a2 :
TEST_RR_SRC21_BYPASS( 22, 0, 2, mul, 165, 15, 11 );
800015a2: 4201 li tp,0
800015a4: 462d li a2,11
800015a6: 40bd li ra,15
800015a8: 0001 nop
800015aa: 0001 nop
800015ac: 02c085b3 mul a1,ra,a2
800015b0: 0205 addi tp,tp,1
800015b2: 4289 li t0,2
800015b4: fe5218e3 bne tp,t0,800015a4
800015b8: 0a500513 li a0,165
800015bc: 4259 li tp,22
800015be: 0aa59363 bne a1,a0,80001664
800015c2 :
TEST_RR_SRC21_BYPASS( 23, 1, 0, mul, 143, 13, 11 );
800015c2: 4201 li tp,0
800015c4: 462d li a2,11
800015c6: 0001 nop
800015c8: 40b5 li ra,13
800015ca: 02c085b3 mul a1,ra,a2
800015ce: 0205 addi tp,tp,1
800015d0: 4289 li t0,2
800015d2: fe5219e3 bne tp,t0,800015c4
800015d6: 08f00513 li a0,143
800015da: 425d li tp,23
800015dc: 08a59463 bne a1,a0,80001664
800015e0 :
TEST_RR_SRC21_BYPASS( 24, 1, 1, mul, 154, 14, 11 );
800015e0: 4201 li tp,0
800015e2: 462d li a2,11
800015e4: 0001 nop
800015e6: 40b9 li ra,14
800015e8: 0001 nop
800015ea: 02c085b3 mul a1,ra,a2
800015ee: 0205 addi tp,tp,1
800015f0: 4289 li t0,2
800015f2: fe5218e3 bne tp,t0,800015e2
800015f6: 09a00513 li a0,154
800015fa: 4261 li tp,24
800015fc: 06a59463 bne a1,a0,80001664
80001600 :
TEST_RR_SRC21_BYPASS( 25, 2, 0, mul, 165, 15, 11 );
80001600: 4201 li tp,0
80001602: 462d li a2,11
80001604: 0001 nop
80001606: 0001 nop
80001608: 40bd li ra,15
8000160a: 02c085b3 mul a1,ra,a2
8000160e: 0205 addi tp,tp,1
80001610: 4289 li t0,2
80001612: fe5218e3 bne tp,t0,80001602
80001616: 0a500513 li a0,165
8000161a: 4265 li tp,25
8000161c: 04a59463 bne a1,a0,80001664
80001620 :
TEST_RR_ZEROSRC1( 26, mul, 0, 31 );
80001620: 40fd li ra,31
80001622: 02100633 mul a2,zero,ra
80001626: 4501 li a0,0
80001628: 4269 li tp,26
8000162a: 02a61d63 bne a2,a0,80001664
8000162e :
TEST_RR_ZEROSRC2( 27, mul, 0, 32 );
8000162e: 02000093 li ra,32
80001632: 02008633 mul a2,ra,zero
80001636: 4501 li a0,0
80001638: 426d li tp,27
8000163a: 02a61563 bne a2,a0,80001664
8000163e :
TEST_RR_ZEROSRC12( 28, mul, 0 );
8000163e: 020000b3 mul ra,zero,zero
80001642: 4501 li a0,0
80001644: 4271 li tp,28
80001646: 00a09f63 bne ra,a0,80001664
8000164a :
TEST_RR_ZERODEST( 29, mul, 33, 34 );
8000164a: 02100093 li ra,33
8000164e: 02200613 li a2,34
80001652: 02c08033 mul zero,ra,a2
80001656: 4501 li a0,0
80001658: 4275 li tp,29
8000165a: 00a01563 bne zero,a0,80001664
#check_mode:
# addi t3, t3, 1;
# bne t4, t4, test_start;
#endif
j pass
8000165e: a801 j 8000166e
TEST_PASSFAIL
80001660: 00401763 bne zero,tp,8000166e
80001664 :
80001664: 0ff0000f fence
80001668: 4201 li tp,0
8000166a: 00000073 ecall
8000166e :
8000166e: 0ff0000f fence
80001672: 0000f297 auipc t0,0xf
80001676: 98e28293 addi t0,t0,-1650 # 80010000 <_sp>
8000167a: 8116 mv sp,t0
8000167c: 4185 li gp,1
8000167e: 00000073 ecall
80001682: 0001 nop
80001684: 0001 nop
80001686: 0001 nop
80001688: 0001 nop
8000168a: 0001 nop
.dump/.verilog文件均为mul.S
文件所生成,.verilog文件可以被仿真verilog代码读取。
testbench中最顶层文件为tb_top.v
。
tb_top.v
负责例化n200_core,并将JTAG从n200_core中连接出来。
tb_monitor.v
负责监视testcase的运行情况,在testcase运行完毕后,如果x3为1则运行成功输出pass,否则输出fail。在终端输出的pass与fail均为tb_monitor.v
的输出结果,Makefile中的命令将终端的输出结果保存于.log文件。
tb_mem_init
负责初始化运行程序的存储,其中有一行代码为:
$readmemh({testcase, ".verilog"}, ilm_mem);
负责将.verilog二进制文件读入mem内部,从而可以执行汇编程序。
首先在观察波形之前,需要找到相关寄存器所在位置。由于随机SEED种子的原因,很多地方名字不易辨析,但是最终找到了相关的寄存器位置。如下图所示:
现在观察相关波形,首先观察pc的运行:
pc从0跳到1000,然后跳到1004,接着从8000_0000执行程序。
以下部分对应于li赋值代码:
从8000_12ca开始的test部分:
源码如下:
test_start:
TEST_RR_OP(32, mul, 0x00001200, 0x00007e00, 0xb6db6db7 );
800012ca: 000080b7 lui ra,0x8
800012ce: e0008093 addi ra,ra,-512 # 7e00 <__stack_size+0x7600>
800012d2: b6db7637 lui a2,0xb6db7
800012d6: db760613 addi a2,a2,-585 # b6db6db7 <_sp+0x36da6db7>
800012da: 02c085b3 mul a1,ra,a2
800012de: 00001537 lui a0,0x1
800012e2: 20050513 addi a0,a0,512 # 1200 <__stack_size+0xa00>
800012e6: 02000213 li tp,32
800012ea: 36a59d63 bne a1,a0,80001664
ra在执行完两个指令后变为了7e00,a2在执行完两个指令后变为了0xb6db7,接下来的乘法指令运行了17个周期,并最终在a1中得到了1200。接下来的两个指令将a0赋值为1200,最后做了比较判断。
从8000_1416开始的test部分:
源码如下:
TEST_RR_SRC1_EQ_DEST( 8, mul, 143, 13, 11 );
80001416: 40b5 li ra,13
80001418: 462d li a2,11
8000141a: 02c080b3 mul ra,ra,a2
8000141e: 08f00513 li a0,143
80001422: 4221 li tp,8
80001424: 24a09063 bne ra,a0,80001664
在经过一个指令后ra赋值为13,在经过一个指令后a2赋值为11。接下来的乘法指令执行了17个周期并最终将计算结果赋值为ra=8f。下一个指令将a0赋值为8f,最后比较判断。
从8000_15e0开始的test部分:
源码如下:
TEST_RR_SRC21_BYPASS( 24, 1, 1, mul, 154, 14, 11 );
800015e0: 4201 li tp,0
800015e2: 462d li a2,11
800015e4: 0001 nop
800015e6: 40b9 li ra,14
800015e8: 0001 nop
800015ea: 02c085b3 mul a1,ra,a2
800015ee: 0205 addi tp,tp,1
800015f0: 4289 li t0,2
800015f2: fe5218e3 bne tp,t0,800015e2
800015f6: 09a00513 li a0,154
800015fa: 4261 li tp,24
800015fc: 06a59463 bne a1,a0,80001664
在插入nop指令后,在第四个指令ra才变为14。同时,由于这个乘法指令需要执行两遍,所以可以看到两条8000_15ea指令。
最基础的RV32I指令集只使用了32位指令字中的编码空间的不到1/8。如果仅仅计算op_code为11/128,没有算上func_code。
同时,RV32I中的共同数据通路的指令的操作码位有尽可能多的位的值是一样的,简化了逻辑控制。
作用:1、大范围PC跳转
2、构造大立即数