Init
This commit is contained in:
138
sim/Makefile
Normal file
138
sim/Makefile
Normal file
@@ -0,0 +1,138 @@
|
||||
# src_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
rtl_src_dir := $(root_dir)/src/
|
||||
rtl_core_files ?= core.files
|
||||
rtl_top_files ?= ahb_top.files
|
||||
rtl_tb_files ?= ahb_tb.files
|
||||
rtl_inc_dir ?= $(root_dir)/src/includes
|
||||
rtl_inc_tb_dir ?= $(root_dir)/src/tb
|
||||
top_module ?= scr1_top_tb_ahb
|
||||
|
||||
rtl_core_list := $(addprefix $(rtl_src_dir),$(shell cat $(rtl_src_dir)$(rtl_core_files)))
|
||||
rtl_top_list := $(addprefix $(rtl_src_dir),$(shell cat $(rtl_src_dir)$(rtl_top_files)))
|
||||
rtl_tb_list := $(addprefix $(rtl_src_dir),$(shell cat $(rtl_src_dir)$(rtl_tb_files)))
|
||||
sv_list := $(rtl_core_list) $(rtl_top_list) $(rtl_tb_list)
|
||||
|
||||
ifeq ($(MAKECMDGOALS), $(filter $(MAKECMDGOALS),build_verilator build_verilator_wf))
|
||||
ifeq ($(BUS),AHB)
|
||||
export scr1_wrapper := $(root_dir)/sim/verilator_wrap/scr1_ahb_wrapper.c
|
||||
endif
|
||||
ifeq ($(BUS),AXI)
|
||||
export scr1_wrapper := $(root_dir)/sim/verilator_wrap/scr1_axi_wrapper.c
|
||||
endif
|
||||
export verilator_ver ?= $(shell expr `verilator --version | cut -f2 -d' '`)
|
||||
|
||||
export verilator_ver_5x ?= $(shell expr `verilator --version | cut -f2 -d' '` \>= 5)
|
||||
|
||||
ifeq "$(verilator_ver_5x)" "1"
|
||||
VERILATOR_5X_OPTS ?= --no-timing # conservative way
|
||||
endif
|
||||
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: build_modelsim build_vcs build_ncsim build_verilator build_verilator_wf
|
||||
|
||||
default: build_modelsim
|
||||
|
||||
build_modelsim: $(sv_list)
|
||||
cd $(bld_dir); \
|
||||
vlib work; \
|
||||
vmap work work; \
|
||||
vlog -work work -O1 -mfcu -sv \
|
||||
+incdir+$(rtl_inc_dir) \
|
||||
+incdir+$(rtl_inc_tb_dir) \
|
||||
+nowarnSVCHK \
|
||||
+define+SCR1_TRGT_SIMULATION \
|
||||
+define+$(SIM_TRACE_DEF) \
|
||||
+define+$(SIM_CFG_DEF) \
|
||||
$(SIM_BUILD_OPTS) \
|
||||
$(sv_list)
|
||||
|
||||
build_vcs: $(sv_list)
|
||||
cd $(bld_dir); \
|
||||
vcs \
|
||||
-full64 \
|
||||
-lca \
|
||||
-sverilog \
|
||||
-notice \
|
||||
+lint=all,noVCDE,noNS,noVNGS,noSVA-DIU,noSVA-CE,noSVA-NSVU \
|
||||
-timescale=1ns/1ps \
|
||||
+incdir+$(rtl_inc_dir) \
|
||||
+incdir+$(rtl_inc_tb_dir) \
|
||||
+define+SCR1_TRGT_SIMULATION \
|
||||
+define+$(SIM_TRACE_DEF) \
|
||||
+define+$(SIM_CFG_DEF) \
|
||||
-nc \
|
||||
-debug_all \
|
||||
$(SIM_BUILD_OPTS) \
|
||||
$(sv_list)
|
||||
|
||||
build_ncsim: $(sv_list)
|
||||
cd $(bld_dir); \
|
||||
irun \
|
||||
-elaborate \
|
||||
-64bit \
|
||||
-disable_sem2009 \
|
||||
-verbose \
|
||||
-timescale 1ns/1ps \
|
||||
-incdir $(rtl_inc_dir) \
|
||||
-incdir $(rtl_inc_tb_dir) \
|
||||
-debug \
|
||||
+define+SCR1_TRGT_SIMULATION \
|
||||
+define+$(SIM_TRACE_DEF) \
|
||||
+define+$(SIM_CFG_DEF) \
|
||||
$(SIM_BUILD_OPTS) \
|
||||
$(sv_list) \
|
||||
-top $(top_module)
|
||||
|
||||
build_verilator: $(sv_list)
|
||||
cd $(bld_dir); \
|
||||
verilator \
|
||||
-cc \
|
||||
-sv \
|
||||
+1800-2017ext+sv \
|
||||
-Wno-fatal \
|
||||
$(VERILATOR_5X_OPTS) \
|
||||
--top-module $(top_module) \
|
||||
-DSCR1_TRGT_SIMULATION \
|
||||
-D$(SIM_TRACE_DEF) \
|
||||
-D$(SIM_CFG_DEF) \
|
||||
--clk clk \
|
||||
--exe $(scr1_wrapper) \
|
||||
--Mdir $(bld_dir)/verilator \
|
||||
-I$(rtl_inc_dir) \
|
||||
-I$(rtl_inc_tb_dir) \
|
||||
$(SIM_BUILD_OPTS) \
|
||||
$(sv_list); \
|
||||
cd verilator; \
|
||||
$(MAKE) -f V$(top_module).mk;
|
||||
|
||||
build_verilator_wf: $(sv_list)
|
||||
cd $(bld_dir); \
|
||||
verilator \
|
||||
-cc \
|
||||
-sv \
|
||||
+1800-2017ext+sv \
|
||||
-Wno-fatal \
|
||||
$(VERILATOR_5X_OPTS) \
|
||||
--top-module $(top_module) \
|
||||
-DSCR1_TRGT_SIMULATION \
|
||||
-D$(SIM_TRACE_DEF) \
|
||||
-D$(SIM_CFG_DEF) \
|
||||
-CFLAGS -DVCD_TRACE -CFLAGS -DTRACE_LVLV=20 \
|
||||
-CFLAGS -DVCD_FNAME=simx.vcd \
|
||||
--clk clk \
|
||||
--exe $(scr1_wrapper) \
|
||||
--trace \
|
||||
--trace-params \
|
||||
--trace-structs \
|
||||
--trace-underscore \
|
||||
--Mdir $(bld_dir)/verilator \
|
||||
-I$(rtl_inc_dir) \
|
||||
-I$(rtl_inc_tb_dir) \
|
||||
$(SIM_BUILD_OPTS) \
|
||||
$(sv_list); \
|
||||
cd verilator; \
|
||||
$(MAKE) -f V$(top_module).mk;
|
||||
|
||||
|
||||
27
sim/tests/benchmarks/coremark/Makefile
Normal file
27
sim/tests/benchmarks/coremark/Makefile
Normal file
@@ -0,0 +1,27 @@
|
||||
src_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
depend_dir := $(src_dir)/../../../../dependencies/coremark
|
||||
|
||||
ADD_FLAGS := -flto
|
||||
ADD_LDFLAGS := -flto
|
||||
|
||||
ifeq ("$(ITERATIONS)","")
|
||||
ITERATIONS=1
|
||||
endif
|
||||
|
||||
ADD_CFLAGS += -DITERATIONS=$(ITERATIONS)
|
||||
ADD_VPATH := $(depend_dir)
|
||||
ADD_incs := -I$(src_dir)/src -I$(depend_dir)
|
||||
|
||||
c_src := core_portme.c sc_print.c
|
||||
coremark_src := ./src/core_list_join.c ./src/core_matrix.c ./src/core_main.c ./src/core_util.c ./src/core_state.c
|
||||
c_src += core_list_join.c core_matrix.c core_main.c core_util.c core_state.c
|
||||
|
||||
include $(inc_dir)/common.mk
|
||||
|
||||
default: log_requested_tgt $(bld_dir)/coremark.elf $(bld_dir)/coremark.hex $(bld_dir)/coremark.dump
|
||||
|
||||
log_requested_tgt:
|
||||
echo coremark.hex>> $(bld_dir)/test_info
|
||||
|
||||
clean:
|
||||
$(RM) $(c_objs) $(asm_objs) $(bld_dir)/coremark.hex $(bld_dir)/coremark.dump
|
||||
141
sim/tests/benchmarks/coremark/core_portme.c
Normal file
141
sim/tests/benchmarks/coremark/core_portme.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
File : core_portme.c
|
||||
*/
|
||||
/*
|
||||
Author : Shay Gal-On, EEMBC
|
||||
Legal : TODO!
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "coremark.h"
|
||||
#include "core_portme.h"
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
#if VALIDATION_RUN
|
||||
volatile ee_s32 seed1_volatile=0x3415;
|
||||
volatile ee_s32 seed2_volatile=0x3415;
|
||||
volatile ee_s32 seed3_volatile=0x66;
|
||||
#endif
|
||||
#if PERFORMANCE_RUN
|
||||
volatile ee_s32 seed1_volatile=0x0;
|
||||
volatile ee_s32 seed2_volatile=0x0;
|
||||
volatile ee_s32 seed3_volatile=0x66;
|
||||
#endif
|
||||
#if PROFILE_RUN
|
||||
volatile ee_s32 seed1_volatile=0x8;
|
||||
volatile ee_s32 seed2_volatile=0x8;
|
||||
volatile ee_s32 seed3_volatile=0x8;
|
||||
#endif
|
||||
volatile ee_s32 seed4_volatile=ITERATIONS;
|
||||
volatile ee_s32 seed5_volatile=0;
|
||||
|
||||
/* Porting : Timing functions
|
||||
How to capture time and convert to seconds must be ported to whatever is supported by the platform.
|
||||
e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc.
|
||||
Sample implementation for standard time.h and windows.h definitions included.
|
||||
*/
|
||||
#if 1
|
||||
CORETIMETYPE barebones_clock() {
|
||||
unsigned long n;
|
||||
__asm__ __volatile__ (
|
||||
"rdtime %0"
|
||||
: "=r" (n));
|
||||
return n;
|
||||
}
|
||||
#define CLOCKS_PER_SEC 10000000
|
||||
|
||||
/* Define : TIMER_RES_DIVIDER
|
||||
Divider to trade off timer resolution and total time that can be measured.
|
||||
|
||||
Use lower values to increase resolution, but make sure that overflow does not occur.
|
||||
If there are issues with the return value overflowing, increase this value.
|
||||
*/
|
||||
/* #define NSECS_PER_SEC CLOCKS_PER_SEC */
|
||||
/* #define CORETIMETYPE clock_t */
|
||||
#define GETMYTIME(_t) (*_t=barebones_clock())
|
||||
#define MYTIMEDIFF(fin,ini) ((fin)-(ini))
|
||||
#define TIMER_RES_DIVIDER 1
|
||||
#define SAMPLE_TIME_IMPLEMENTATION 1
|
||||
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
/** Define Host specific (POSIX), or target specific global time variables. */
|
||||
static CORETIMETYPE start_time_val, stop_time_val;
|
||||
|
||||
/* Function : start_time
|
||||
This function will be called right before starting the timed portion of the benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the example code)
|
||||
or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0.
|
||||
*/
|
||||
void start_time(void) {
|
||||
GETMYTIME(&start_time_val );
|
||||
}
|
||||
/* Function : stop_time
|
||||
This function will be called right after ending the timed portion of the benchmark.
|
||||
|
||||
Implementation may be capturing a system timer (as implemented in the example code)
|
||||
or other system parameters - e.g. reading the current value of cpu cycles counter.
|
||||
*/
|
||||
void stop_time(void) {
|
||||
GETMYTIME(&stop_time_val );
|
||||
}
|
||||
/* Function : get_time
|
||||
Return an abstract "ticks" number that signifies time on the system.
|
||||
|
||||
Actual value returned may be cpu cycles, milliseconds or any other value,
|
||||
as long as it can be converted to seconds by <time_in_secs>.
|
||||
This methodology is taken to accomodate any hardware or simulated platform.
|
||||
The sample implementation returns millisecs by default,
|
||||
and the resolution is controlled by <TIMER_RES_DIVIDER>
|
||||
*/
|
||||
CORE_TICKS get_time(void) {
|
||||
CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
|
||||
return elapsed;
|
||||
}
|
||||
/* Function : time_in_secs
|
||||
Convert the value returned by get_time to seconds.
|
||||
|
||||
The <secs_ret> type is used to accomodate systems with no support for floating point.
|
||||
Default implementation implemented by the EE_TICKS_PER_SEC macro above.
|
||||
*/
|
||||
secs_ret time_in_secs(CORE_TICKS ticks) {
|
||||
secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
|
||||
return retval;
|
||||
}
|
||||
|
||||
ee_u32 default_num_contexts=1;
|
||||
|
||||
/* Function : portable_init
|
||||
Target specific initialization code
|
||||
Test for some common mistakes.
|
||||
*/
|
||||
void portable_init(core_portable *p, int *argc, char *argv[])
|
||||
{
|
||||
ee_printf("CoreMark 1.0\n");
|
||||
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
|
||||
ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer! (%u != %u)\n", sizeof(ee_ptr_int), sizeof(ee_u8 *));
|
||||
}
|
||||
if (sizeof(ee_u32) != 4) {
|
||||
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type! (%u)\n", sizeof(ee_u32));
|
||||
}
|
||||
p->portable_id=1;
|
||||
}
|
||||
/* Function : portable_fini
|
||||
Target specific final code
|
||||
*/
|
||||
void portable_fini(core_portable *p)
|
||||
{
|
||||
p->portable_id=0;
|
||||
|
||||
report_results(0, 0, 0, 0, 0);
|
||||
|
||||
/* results[0].iterations * 10000000/(total_time) */
|
||||
|
||||
/* extern void tohost_exit(long code); */
|
||||
|
||||
/* tohost_exit(0); */
|
||||
}
|
||||
210
sim/tests/benchmarks/coremark/core_portme.h
Normal file
210
sim/tests/benchmarks/coremark/core_portme.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/* File : core_portme.h */
|
||||
|
||||
/*
|
||||
Author : Shay Gal-On, EEMBC
|
||||
Legal : TODO!
|
||||
*/
|
||||
/* Topic : Description
|
||||
This file contains configuration constants required to execute on different platforms
|
||||
*/
|
||||
#ifndef CORE_PORTME_H
|
||||
#define CORE_PORTME_H
|
||||
/************************/
|
||||
/* Data types and settings */
|
||||
/************************/
|
||||
/* Configuration : HAS_FLOAT
|
||||
Define to 1 if the platform supports floating point.
|
||||
*/
|
||||
#ifndef HAS_FLOAT
|
||||
#define HAS_FLOAT 0
|
||||
#endif
|
||||
/* Configuration : HAS_TIME_H
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef HAS_TIME_H
|
||||
#define HAS_TIME_H 0
|
||||
#endif
|
||||
/* Configuration : USE_CLOCK
|
||||
Define to 1 if platform has the time.h header file,
|
||||
and implementation of functions thereof.
|
||||
*/
|
||||
#ifndef USE_CLOCK
|
||||
#define USE_CLOCK 0
|
||||
#endif
|
||||
/* Configuration : HAS_STDIO
|
||||
Define to 1 if the platform has stdio.h.
|
||||
*/
|
||||
#ifndef HAS_STDIO
|
||||
#define HAS_STDIO 1
|
||||
#endif
|
||||
/* Configuration : HAS_PRINTF
|
||||
Define to 1 if the platform has stdio.h and implements the printf function.
|
||||
*/
|
||||
#ifndef HAS_PRINTF
|
||||
#define HAS_PRINTF 0
|
||||
#endif
|
||||
|
||||
#include "sc_print.h"
|
||||
#define ee_printf sc_printf
|
||||
|
||||
/* static inline int ee_printf(const char *fmt, ...) {} */
|
||||
|
||||
/* Configuration : CORE_TICKS
|
||||
Define type of return from the timing functions.
|
||||
*/
|
||||
/* #include <time.h> */
|
||||
/* typedef clock_t CORE_TICKS; */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#define CORETIMETYPE uint32_t
|
||||
typedef uint32_t CORE_TICKS;
|
||||
|
||||
/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
|
||||
Initialize these strings per platform
|
||||
*/
|
||||
#ifndef COMPILER_VERSION
|
||||
#ifdef __GNUC__
|
||||
#define COMPILER_VERSION "GCC"__VERSION__
|
||||
#else
|
||||
#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef COMPILER_FLAGS
|
||||
#define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
|
||||
#endif
|
||||
#ifndef MEM_LOCATION
|
||||
/* #define MEM_LOCATION "STACK" */
|
||||
#define MEM_LOCATION "STATIC"
|
||||
#endif
|
||||
|
||||
/* Data Types :
|
||||
To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in <core_portme.h>.
|
||||
|
||||
*Imprtant* :
|
||||
ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!!
|
||||
*/
|
||||
typedef int16_t ee_s16;
|
||||
typedef uint16_t ee_u16;
|
||||
typedef int32_t ee_s32;
|
||||
typedef float ee_f32;
|
||||
typedef uint8_t ee_u8;
|
||||
typedef uint32_t ee_u32;
|
||||
typedef uintptr_t ee_ptr_int;
|
||||
typedef size_t ee_size_t;
|
||||
/* align_mem :
|
||||
This macro is used to align an offset to point to a 32b value. It is used in the Matrix algorithm to initialize the input memory blocks.
|
||||
*/
|
||||
#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3))
|
||||
|
||||
/* Configuration : SEED_METHOD
|
||||
Defines method to get seed values that cannot be computed at compile time.
|
||||
|
||||
Valid values :
|
||||
SEED_ARG - from command line.
|
||||
SEED_FUNC - from a system function.
|
||||
SEED_VOLATILE - from volatile variables.
|
||||
*/
|
||||
#ifndef SEED_METHOD
|
||||
#define SEED_METHOD SEED_VOLATILE
|
||||
#endif
|
||||
|
||||
/* Configuration : MEM_METHOD
|
||||
Defines method to get a block of memry.
|
||||
|
||||
Valid values :
|
||||
MEM_MALLOC - for platforms that implement malloc and have malloc.h.
|
||||
MEM_STATIC - to use a static memory array.
|
||||
MEM_STACK - to allocate the data block on the stack (NYI).
|
||||
*/
|
||||
#ifndef MEM_METHOD
|
||||
/* #define MEM_METHOD MEM_STACK */
|
||||
#define MEM_METHOD MEM_STATIC
|
||||
#endif
|
||||
|
||||
/* Configuration : MULTITHREAD
|
||||
Define for parallel execution
|
||||
|
||||
Valid values :
|
||||
1 - only one context (default).
|
||||
N>1 - will execute N copies in parallel.
|
||||
|
||||
Note :
|
||||
If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined.
|
||||
|
||||
Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK> to enable them.
|
||||
|
||||
It is valid to have a different implementation of <core_start_parallel> and <core_end_parallel> in <core_portme.c>,
|
||||
to fit a particular architecture.
|
||||
*/
|
||||
#ifndef MULTITHREAD
|
||||
#define MULTITHREAD 1
|
||||
#define USE_PTHREAD 0
|
||||
#define USE_FORK 0
|
||||
#define USE_SOCKET 0
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NOARGC
|
||||
Needed if platform does not support getting arguments to main.
|
||||
|
||||
Valid values :
|
||||
0 - argc/argv to main is supported
|
||||
1 - argc/argv to main is not supported
|
||||
|
||||
Note :
|
||||
This flag only matters if MULTITHREAD has been defined to a value greater then 1.
|
||||
*/
|
||||
#ifndef MAIN_HAS_NOARGC
|
||||
#define MAIN_HAS_NOARGC 1
|
||||
#endif
|
||||
|
||||
/* Configuration : MAIN_HAS_NORETURN
|
||||
Needed if platform does not support returning a value from main.
|
||||
|
||||
Valid values :
|
||||
0 - main returns an int, and return value will be 0.
|
||||
1 - platform does not support returning a value from main
|
||||
*/
|
||||
#ifndef MAIN_HAS_NORETURN
|
||||
#define MAIN_HAS_NORETURN 0
|
||||
#endif
|
||||
|
||||
/* Variable : default_num_contexts
|
||||
Not used for this simple port, must cintain the value 1.
|
||||
*/
|
||||
extern ee_u32 default_num_contexts;
|
||||
|
||||
typedef struct CORE_PORTABLE_S {
|
||||
ee_u8 portable_id;
|
||||
} core_portable;
|
||||
|
||||
/* target specific init/fini */
|
||||
void portable_init(core_portable *p, int *argc, char *argv[]);
|
||||
void portable_fini(core_portable *p);
|
||||
|
||||
#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN)
|
||||
#if (TOTAL_DATA_SIZE==1200)
|
||||
#define PROFILE_RUN 1
|
||||
#elif (TOTAL_DATA_SIZE==2000)
|
||||
#define PERFORMANCE_RUN 1
|
||||
#else
|
||||
#define VALIDATION_RUN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef ee_s16 MATDAT;
|
||||
typedef ee_s32 MATRES;
|
||||
|
||||
|
||||
ee_u16 crcu8(ee_u8 data, ee_u16 crc ) __attribute__ ((hot));
|
||||
ee_u16 crcu16(ee_u16 newval, ee_u16 crc) __attribute__ ((hot));
|
||||
ee_u16 crcu32(ee_u32 newval, ee_u16 crc) __attribute__ ((hot));
|
||||
ee_u16 crc16(ee_s16 newval, ee_u16 crc) __attribute__ ((hot));
|
||||
ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) __attribute__ ((hot));
|
||||
void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) __attribute__ ((hot));
|
||||
void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) __attribute__ ((hot));
|
||||
void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) __attribute__ ((hot));
|
||||
void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) __attribute__ ((hot));
|
||||
void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val) __attribute__ ((hot));
|
||||
|
||||
#endif /* CORE_PORTME_H */
|
||||
17
sim/tests/benchmarks/dhrystone21/Makefile
Normal file
17
sim/tests/benchmarks/dhrystone21/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
src_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
ADD_FLAGS := -flto
|
||||
ADD_LDFLAGS := -flto
|
||||
ADD_CFLAGS := -DSELF_TIMED=1 -DTIME=1
|
||||
|
||||
c_src := sc_print.c dhry_1.c dhry_2.c
|
||||
|
||||
include $(inc_dir)/common.mk
|
||||
|
||||
default: log_requested_tgt $(bld_dir)/dhrystone21.elf $(bld_dir)/dhrystone21.hex $(bld_dir)/dhrystone21.dump
|
||||
|
||||
log_requested_tgt:
|
||||
@echo dhrystone21.hex>> $(bld_dir)/test_info
|
||||
|
||||
clean:
|
||||
$(RM) $(c_objs) $(asm_objs) $(bld_dir)/dhrystone21.elf $(bld_dir)/dhrystone21.hex $(bld_dir)/dhrystone21.dump
|
||||
446
sim/tests/benchmarks/dhrystone21/dhry.h
Normal file
446
sim/tests/benchmarks/dhrystone21/dhry.h
Normal file
@@ -0,0 +1,446 @@
|
||||
/*****************************************************************************
|
||||
* The BYTE UNIX Benchmarks - Release 3
|
||||
* Module: dhry.h SID: 3.4 5/15/91 19:30:21
|
||||
*
|
||||
*****************************************************************************
|
||||
* Bug reports, patches, comments, suggestions should be sent to:
|
||||
*
|
||||
* Ben Smith, Rick Grehan or Tom Yager
|
||||
* ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
|
||||
*
|
||||
*****************************************************************************
|
||||
* Modification Log:
|
||||
* addapted from:
|
||||
*
|
||||
*
|
||||
* "DHRYSTONE" Benchmark Program
|
||||
* -----------------------------
|
||||
*
|
||||
* Version: C, Version 2.1
|
||||
*
|
||||
* File: dhry.h (part 1 of 3)
|
||||
*
|
||||
* Date: May 25, 1988
|
||||
*
|
||||
* Author: Reinhold P. Weicker
|
||||
* Siemens AG, AUT E 51
|
||||
* Postfach 3220
|
||||
* 8520 Erlangen
|
||||
* Germany (West)
|
||||
* Phone: [+49]-9131-7-20330
|
||||
* (8-17 Central European Time)
|
||||
* Usenet: ..!mcvax!unido!estevax!weicker
|
||||
*
|
||||
* Original Version (in Ada) published in
|
||||
* "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
|
||||
* pp. 1013 - 1030, together with the statistics
|
||||
* on which the distribution of statements etc. is based.
|
||||
*
|
||||
* In this C version, the following C library functions are used:
|
||||
* - strcpy, strcmp (inside the measurement loop)
|
||||
* - printf, scanf (outside the measurement loop)
|
||||
* In addition, Berkeley UNIX system calls "times ()" or "time ()"
|
||||
* are used for execution time measurement. For measurements
|
||||
* on other systems, these calls have to be changed.
|
||||
*
|
||||
* Collection of Results:
|
||||
* Reinhold Weicker (address see above) and
|
||||
*
|
||||
* Rick Richardson
|
||||
* PC Research. Inc.
|
||||
* 94 Apple Orchard Drive
|
||||
* Tinton Falls, NJ 07724
|
||||
* Phone: (201) 834-1378 (9-17 EST)
|
||||
* Usenet: ...!seismo!uunet!pcrat!rick
|
||||
*
|
||||
* Please send results to Rick Richardson and/or Reinhold Weicker.
|
||||
* Complete information should be given on hardware and software used.
|
||||
* Hardware information includes: Machine type, CPU, type and size
|
||||
* of caches; for microprocessors: clock frequency, memory speed
|
||||
* (number of wait states).
|
||||
* Software information includes: Compiler (and runtime library)
|
||||
* manufacturer and version, compilation switches, OS version.
|
||||
* The Operating System version may give an indication about the
|
||||
* compiler; Dhrystone itself performs no OS calls in the measurement loop.
|
||||
*
|
||||
* The complete output generated by the program should be mailed
|
||||
* such that at least some checks for correctness can be made.
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* History: This version C/2.1 has been made for two reasons:
|
||||
*
|
||||
* 1) There is an obvious need for a common C version of
|
||||
* Dhrystone, since C is at present the most popular system
|
||||
* programming language for the class of processors
|
||||
* (microcomputers, minicomputers) where Dhrystone is used most.
|
||||
* There should be, as far as possible, only one C version of
|
||||
* Dhrystone such that results can be compared without
|
||||
* restrictions. In the past, the C versions distributed
|
||||
* by Rick Richardson (Version 1.1) and by Reinhold Weicker
|
||||
* had small (though not significant) differences.
|
||||
*
|
||||
* 2) As far as it is possible without changes to the Dhrystone
|
||||
* statistics, optimizing compilers should be prevented from
|
||||
* removing significant statements.
|
||||
*
|
||||
* This C version has been developed in cooperation with
|
||||
* Rick Richardson (Tinton Falls, NJ), it incorporates many
|
||||
* ideas from the "Version 1.1" distributed previously by
|
||||
* him over the UNIX network Usenet.
|
||||
* I also thank Chaim Benedelac (National Semiconductor),
|
||||
* David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
|
||||
* Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
|
||||
* for their help with comments on earlier versions of the
|
||||
* benchmark.
|
||||
*
|
||||
* Changes: In the initialization part, this version follows mostly
|
||||
* Rick Richardson's version distributed via Usenet, not the
|
||||
* version distributed earlier via floppy disk by Reinhold Weicker.
|
||||
* As a concession to older compilers, names have been made
|
||||
* unique within the first 8 characters.
|
||||
* Inside the measurement loop, this version follows the
|
||||
* version previously distributed by Reinhold Weicker.
|
||||
*
|
||||
* At several places in the benchmark, code has been added,
|
||||
* but within the measurement loop only in branches that
|
||||
* are not executed. The intention is that optimizing compilers
|
||||
* should be prevented from moving code out of the measurement
|
||||
* loop, or from removing code altogether. Since the statements
|
||||
* that are executed within the measurement loop have NOT been
|
||||
* changed, the numbers defining the "Dhrystone distribution"
|
||||
* (distribution of statements, operand types and locality)
|
||||
* still hold. Except for sophisticated optimizing compilers,
|
||||
* execution times for this version should be the same as
|
||||
* for previous versions.
|
||||
*
|
||||
* Since it has proven difficult to subtract the time for the
|
||||
* measurement loop overhead in a correct way, the loop check
|
||||
* has been made a part of the benchmark. This does have
|
||||
* an impact - though a very minor one - on the distribution
|
||||
* statistics which have been updated for this version.
|
||||
*
|
||||
* All changes within the measurement loop are described
|
||||
* and discussed in the companion paper "Rationale for
|
||||
* Dhrystone version 2".
|
||||
*
|
||||
* Because of the self-imposed limitation that the order and
|
||||
* distribution of the executed statements should not be
|
||||
* changed, there are still cases where optimizing compilers
|
||||
* may not generate code for some statements. To a certain
|
||||
* degree, this is unavoidable for small synthetic benchmarks.
|
||||
* Users of the benchmark are advised to check code listings
|
||||
* whether code is generated for all statements of Dhrystone.
|
||||
*
|
||||
* Version 2.1 is identical to version 2.0 distributed via
|
||||
* the UNIX network Usenet in March 1988 except that it corrects
|
||||
* some minor deficiencies that were found by users of version 2.0.
|
||||
* The only change within the measurement loop is that a
|
||||
* non-executed "else" part was added to the "if" statement in
|
||||
* Func_3, and a non-executed "else" part removed from Proc_3.
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Defines: The following "Defines" are possible:
|
||||
* -DREG=register (default: Not defined)
|
||||
* As an approximation to what an average C programmer
|
||||
* might do, the "register" storage class is applied
|
||||
* (if enabled by -DREG=register)
|
||||
* - for local variables, if they are used (dynamically)
|
||||
* five or more times
|
||||
* - for parameters if they are used (dynamically)
|
||||
* six or more times
|
||||
* Note that an optimal "register" strategy is
|
||||
* compiler-dependent, and that "register" declarations
|
||||
* do not necessarily lead to faster execution.
|
||||
* -DNOSTRUCTASSIGN (default: Not defined)
|
||||
* Define if the C compiler does not support
|
||||
* assignment of structures.
|
||||
* -DNOENUMS (default: Not defined)
|
||||
* Define if the C compiler does not support
|
||||
* enumeration types.
|
||||
* -DTIMES (default)
|
||||
* -DTIME
|
||||
* The "times" function of UNIX (returning process times)
|
||||
* or the "time" function (returning wallclock time)
|
||||
* is used for measurement.
|
||||
* For single user machines, "time ()" is adequate. For
|
||||
* multi-user machines where you cannot get single-user
|
||||
* access, use the "times ()" function. If you have
|
||||
* neither, use a stopwatch in the dead of night.
|
||||
* "printf"s are provided marking the points "Start Timer"
|
||||
* and "Stop Timer". DO NOT use the UNIX "time(1)"
|
||||
* command, as this will measure the total time to
|
||||
* run this program, which will (erroneously) include
|
||||
* the time to allocate storage (malloc) and to perform
|
||||
* the initialization.
|
||||
* -DHZ=nnn
|
||||
* In Berkeley UNIX, the function "times" returns process
|
||||
* time in 1/HZ seconds, with HZ = 60 for most systems.
|
||||
* CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
|
||||
* A VALUE.
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Compilation model and measurement (IMPORTANT):
|
||||
*
|
||||
* This C version of Dhrystone consists of three files:
|
||||
* - dhry.h (this file, containing global definitions and comments)
|
||||
* - dhry_1.c (containing the code corresponding to Ada package Pack_1)
|
||||
* - dhry_2.c (containing the code corresponding to Ada package Pack_2)
|
||||
*
|
||||
* The following "ground rules" apply for measurements:
|
||||
* - Separate compilation
|
||||
* - No procedure merging
|
||||
* - Otherwise, compiler optimizations are allowed but should be indicated
|
||||
* - Default results are those without register declarations
|
||||
* See the companion paper "Rationale for Dhrystone Version 2" for a more
|
||||
* detailed discussion of these ground rules.
|
||||
*
|
||||
* For 16-Bit processors (e.g. 80186, 80286), times for all compilation
|
||||
* models ("small", "medium", "large" etc.) should be given if possible,
|
||||
* together with a definition of these models for the compiler system used.
|
||||
*
|
||||
**************************************************************************
|
||||
*
|
||||
* Dhrystone (C version) statistics:
|
||||
*
|
||||
* [Comment from the first distribution, updated for version 2.
|
||||
* Note that because of language differences, the numbers are slightly
|
||||
* different from the Ada version.]
|
||||
*
|
||||
* The following program contains statements of a high level programming
|
||||
* language (here: C) in a distribution considered representative:
|
||||
*
|
||||
* assignments 52 (51.0 %)
|
||||
* control statements 33 (32.4 %)
|
||||
* procedure, function calls 17 (16.7 %)
|
||||
*
|
||||
* 103 statements are dynamically executed. The program is balanced with
|
||||
* respect to the three aspects:
|
||||
*
|
||||
* - statement type
|
||||
* - operand type
|
||||
* - operand locality
|
||||
* operand global, local, parameter, or constant.
|
||||
*
|
||||
* The combination of these three aspects is balanced only approximately.
|
||||
*
|
||||
* 1. Statement Type:
|
||||
* ----------------- number
|
||||
*
|
||||
* V1 = V2 9
|
||||
* (incl. V1 = F(..)
|
||||
* V = Constant 12
|
||||
* Assignment, 7
|
||||
* with array element
|
||||
* Assignment, 6
|
||||
* with record component
|
||||
* --
|
||||
* 34 34
|
||||
*
|
||||
* X = Y +|-|"&&"|"|" Z 5
|
||||
* X = Y +|-|"==" Constant 6
|
||||
* X = X +|- 1 3
|
||||
* X = Y *|/ Z 2
|
||||
* X = Expression, 1
|
||||
* two operators
|
||||
* X = Expression, 1
|
||||
* three operators
|
||||
* --
|
||||
* 18 18
|
||||
*
|
||||
* if .... 14
|
||||
* with "else" 7
|
||||
* without "else" 7
|
||||
* executed 3
|
||||
* not executed 4
|
||||
* for ... 7 | counted every time
|
||||
* while ... 4 | the loop condition
|
||||
* do ... while 1 | is evaluated
|
||||
* switch ... 1
|
||||
* break 1
|
||||
* declaration with 1
|
||||
* initialization
|
||||
* --
|
||||
* 34 34
|
||||
*
|
||||
* P (...) procedure call 11
|
||||
* user procedure 10
|
||||
* library procedure 1
|
||||
* X = F (...)
|
||||
* function call 6
|
||||
* user function 5
|
||||
* library function 1
|
||||
* --
|
||||
* 17 17
|
||||
* ---
|
||||
* 103
|
||||
*
|
||||
* The average number of parameters in procedure or function calls
|
||||
* is 1.82 (not counting the function values as implicit parameters).
|
||||
*
|
||||
*
|
||||
* 2. Operators
|
||||
* ------------
|
||||
* number approximate
|
||||
* percentage
|
||||
*
|
||||
* Arithmetic 32 50.8
|
||||
*
|
||||
* + 21 33.3
|
||||
* - 7 11.1
|
||||
* * 3 4.8
|
||||
* / (int div) 1 1.6
|
||||
*
|
||||
* Comparison 27 42.8
|
||||
*
|
||||
* == 9 14.3
|
||||
* /= 4 6.3
|
||||
* > 1 1.6
|
||||
* < 3 4.8
|
||||
* >= 1 1.6
|
||||
* <= 9 14.3
|
||||
*
|
||||
* Logic 4 6.3
|
||||
*
|
||||
* && (AND-THEN) 1 1.6
|
||||
* | (OR) 1 1.6
|
||||
* ! (NOT) 2 3.2
|
||||
*
|
||||
* -- -----
|
||||
* 63 100.1
|
||||
*
|
||||
*
|
||||
* 3. Operand Type (counted once per operand reference):
|
||||
* ---------------
|
||||
* number approximate
|
||||
* percentage
|
||||
*
|
||||
* Integer 175 72.3 %
|
||||
* Character 45 18.6 %
|
||||
* Pointer 12 5.0 %
|
||||
* String30 6 2.5 %
|
||||
* Array 2 0.8 %
|
||||
* Record 2 0.8 %
|
||||
* --- -------
|
||||
* 242 100.0 %
|
||||
*
|
||||
* When there is an access path leading to the final operand (e.g. a record
|
||||
* component), only the final data type on the access path is counted.
|
||||
*
|
||||
*
|
||||
* 4. Operand Locality:
|
||||
* -------------------
|
||||
* number approximate
|
||||
* percentage
|
||||
*
|
||||
* local variable 114 47.1 %
|
||||
* global variable 22 9.1 %
|
||||
* parameter 45 18.6 %
|
||||
* value 23 9.5 %
|
||||
* reference 22 9.1 %
|
||||
* function result 6 2.5 %
|
||||
* constant 55 22.7 %
|
||||
* --- -------
|
||||
* 242 100.0 %
|
||||
*
|
||||
*
|
||||
* The program does not compute anything meaningful, but it is syntactically
|
||||
* and semantically correct. All variables have a value assigned to them
|
||||
* before they are used as a source operand.
|
||||
*
|
||||
* There has been no explicit effort to account for the effects of a
|
||||
* cache, or to balance the use of long or short displacements for code or
|
||||
* data.
|
||||
*
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Compiler and system dependent definitions: */
|
||||
|
||||
#ifndef TIME
|
||||
#define TIMES
|
||||
#endif
|
||||
/* Use times(2) time function unless */
|
||||
/* explicitly defined otherwise */
|
||||
|
||||
#ifdef TIMES
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
/* for "times" */
|
||||
#endif
|
||||
|
||||
#define Mic_secs_Per_Second 1000000
|
||||
/* Berkeley UNIX C returns process times in seconds/HZ */
|
||||
|
||||
#ifdef NOSTRUCTASSIGN
|
||||
#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
|
||||
#else
|
||||
#define structassign(d, s) d = s
|
||||
#endif
|
||||
|
||||
#ifdef NOENUM
|
||||
#define Ident_1 0
|
||||
#define Ident_2 1
|
||||
#define Ident_3 2
|
||||
#define Ident_4 3
|
||||
#define Ident_5 4
|
||||
typedef int Enumeration;
|
||||
#else
|
||||
typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
|
||||
Enumeration;
|
||||
#endif
|
||||
/* for boolean and enumeration types in Ada, Pascal */
|
||||
|
||||
/* General definitions: */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
/* for strcpy, strcmp */
|
||||
|
||||
#define Null 0
|
||||
/* Value of a Null pointer */
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
typedef int One_Thirty;
|
||||
typedef int One_Fifty;
|
||||
typedef char Capital_Letter;
|
||||
typedef int Boolean;
|
||||
typedef char Str_30 [31];
|
||||
typedef int Arr_1_Dim [50];
|
||||
typedef int Arr_2_Dim [50] [50];
|
||||
|
||||
typedef struct record
|
||||
{
|
||||
struct record *Ptr_Comp;
|
||||
Enumeration Discr;
|
||||
union {
|
||||
struct {
|
||||
Enumeration Enum_Comp;
|
||||
int Int_Comp;
|
||||
char Str_Comp [31];
|
||||
} var_1;
|
||||
struct {
|
||||
Enumeration E_Comp_2;
|
||||
char Str_2_Comp [31];
|
||||
} var_2;
|
||||
struct {
|
||||
char Ch_1_Comp;
|
||||
char Ch_2_Comp;
|
||||
} var_3;
|
||||
} variant;
|
||||
} Rec_Type, *Rec_Pointer;
|
||||
|
||||
#include "sc_print.h"
|
||||
#include "csr.h"
|
||||
|
||||
# define printf sc_printf
|
||||
|
||||
#define HZ 1000000
|
||||
static long time(long *x)
|
||||
{
|
||||
return rdcycle();
|
||||
}
|
||||
461
sim/tests/benchmarks/dhrystone21/dhry_1.c
Normal file
461
sim/tests/benchmarks/dhrystone21/dhry_1.c
Normal file
@@ -0,0 +1,461 @@
|
||||
/*****************************************************************************
|
||||
* The BYTE UNIX Benchmarks - Release 3
|
||||
* Module: dhry_1.c SID: 3.4 5/15/91 19:30:21
|
||||
*
|
||||
*****************************************************************************
|
||||
* Bug reports, patches, comments, suggestions should be sent to:
|
||||
*
|
||||
* Ben Smith, Rick Grehan or Tom Yager
|
||||
* ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
|
||||
*
|
||||
*****************************************************************************
|
||||
*
|
||||
* *** WARNING **** With BYTE's modifications applied, results obtained with
|
||||
* ******* this version of the Dhrystone program may not be applicable
|
||||
* to other versions.
|
||||
*
|
||||
* Modification Log:
|
||||
* 10/22/97 - code cleanup to remove ANSI C compiler warnings
|
||||
* Andy Kahn <kahn@zk3.dec.com>
|
||||
*
|
||||
* Adapted from:
|
||||
*
|
||||
* "DHRYSTONE" Benchmark Program
|
||||
* -----------------------------
|
||||
*
|
||||
* Version: C, Version 2.1
|
||||
*
|
||||
* File: dhry_1.c (part 2 of 3)
|
||||
*
|
||||
* Date: May 25, 1988
|
||||
*
|
||||
* Author: Reinhold P. Weicker
|
||||
*
|
||||
***************************************************************************/
|
||||
char SCCSid[] = "@(#) @(#)dhry_1.c:3.4 -- 5/15/91 19:30:21";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dhry.h"
|
||||
//#include "timeit.c"
|
||||
|
||||
unsigned long Run_Index;
|
||||
/*
|
||||
void report()
|
||||
{
|
||||
fprintf(stderr,"COUNT|%ld|1|lps\n", Run_Index);
|
||||
exit(0);
|
||||
}
|
||||
*/
|
||||
/* Global Variables: */
|
||||
|
||||
Rec_Pointer Ptr_Glob,
|
||||
Next_Ptr_Glob;
|
||||
int Int_Glob;
|
||||
Boolean Bool_Glob;
|
||||
char Ch_1_Glob,
|
||||
Ch_2_Glob;
|
||||
int Arr_1_Glob [50];
|
||||
int Arr_2_Glob [50] [50];
|
||||
|
||||
Enumeration Func_1 ();
|
||||
/* forward declaration necessary since Enumeration may not simply be int */
|
||||
|
||||
#ifndef REG
|
||||
Boolean Reg = false;
|
||||
#define REG
|
||||
/* REG becomes defined as empty */
|
||||
/* i.e. no register variables */
|
||||
#else
|
||||
Boolean Reg = true;
|
||||
#endif
|
||||
|
||||
/* variables for time measurement: */
|
||||
|
||||
#ifdef TIMES
|
||||
struct tms time_info;
|
||||
/* extern int times (); */
|
||||
/* see library function "times" */
|
||||
#define Too_Small_Time 120
|
||||
/* Measurements should last at least about 2 seconds */
|
||||
#endif
|
||||
#ifdef TIME
|
||||
extern long time();
|
||||
/* see library function "time" */
|
||||
#define Too_Small_Time 2
|
||||
/* Measurements should last at least 2 seconds */
|
||||
#endif
|
||||
|
||||
long Begin_Time,
|
||||
End_Time,
|
||||
User_Time;
|
||||
#if 0
|
||||
float Microseconds,
|
||||
Dhrystones_Per_Second;
|
||||
#else
|
||||
long Microseconds,
|
||||
Dhrystones_Per_Second;
|
||||
#endif
|
||||
|
||||
/* end of variables for time measurement */
|
||||
|
||||
void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
|
||||
void Proc_2 (One_Fifty *Int_Par_Ref);
|
||||
void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
|
||||
void Proc_4 (void);
|
||||
void Proc_5 (void);
|
||||
|
||||
|
||||
extern Boolean Func_2(Str_30, Str_30);
|
||||
extern void Proc_6(Enumeration, Enumeration *);
|
||||
extern void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
|
||||
extern void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);
|
||||
|
||||
int main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
/* main program, corresponds to procedures */
|
||||
/* Main and Proc_0 in the Ada version */
|
||||
{
|
||||
#ifdef SELF_TIMED
|
||||
int Number_Of_Runs;
|
||||
#else /* SELF_TIMED */
|
||||
int duration;
|
||||
#endif /* SELF_TIMED */
|
||||
One_Fifty Int_1_Loc;
|
||||
REG One_Fifty Int_2_Loc;
|
||||
One_Fifty Int_3_Loc;
|
||||
REG char Ch_Index;
|
||||
Enumeration Enum_Loc;
|
||||
Str_30 Str_1_Loc;
|
||||
Str_30 Str_2_Loc;
|
||||
|
||||
/* Initializations */
|
||||
#if 0
|
||||
Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
|
||||
Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
|
||||
#else
|
||||
static Rec_Type glob1, glob2;
|
||||
Next_Ptr_Glob = &glob1;
|
||||
Ptr_Glob = &glob2;
|
||||
#endif
|
||||
|
||||
Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
|
||||
Ptr_Glob->Discr = Ident_1;
|
||||
Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
|
||||
Ptr_Glob->variant.var_1.Int_Comp = 40;
|
||||
strcpy (Ptr_Glob->variant.var_1.Str_Comp,
|
||||
"DHRYSTONE PROGRAM, SOME STRING");
|
||||
strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
|
||||
|
||||
Arr_2_Glob [8][7] = 10;
|
||||
/* Was missing in published program. Without this statement, */
|
||||
/* Arr_2_Glob [8][7] would have an undefined value. */
|
||||
/* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
|
||||
/* overflow may occur for this array element. */
|
||||
|
||||
#ifdef SELF_TIMED
|
||||
Number_Of_Runs = 500;//500000;
|
||||
if (argc >= 2) {
|
||||
Number_Of_Runs = atoi(argv[1]);
|
||||
}
|
||||
printf ("\n");
|
||||
printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
|
||||
printf ("\n");
|
||||
if (Reg)
|
||||
{
|
||||
printf ("Program compiled with 'register' attribute\n");
|
||||
printf ("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Program compiled without 'register' attribute\n");
|
||||
printf ("\n");
|
||||
}
|
||||
#ifdef PRATTLE
|
||||
printf ("Please give the number of runs through the benchmark: ");
|
||||
{
|
||||
int n;
|
||||
scanf ("%d", &n);
|
||||
Number_Of_Runs = n;
|
||||
}
|
||||
printf ("\n");
|
||||
#endif /* PRATTLE */
|
||||
|
||||
printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
|
||||
|
||||
Run_Index = 0;
|
||||
#else /* SELF_TIMED */
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s duration\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
duration = atoi(argv[1]);
|
||||
Run_Index = 0;
|
||||
wake_me(duration, report);
|
||||
#endif /* SELF_TIMED */
|
||||
|
||||
/***************/
|
||||
/* Start timer */
|
||||
/***************/
|
||||
|
||||
#ifdef SELF_TIMED
|
||||
#ifdef TIMES
|
||||
times (&time_info);
|
||||
Begin_Time = (long) time_info.tms_utime;
|
||||
#endif
|
||||
#ifdef TIME
|
||||
Begin_Time = time ( (long *) 0);
|
||||
#endif
|
||||
#endif /* SELF_TIMED */
|
||||
|
||||
#ifdef SELF_TIMED
|
||||
for (Run_Index = 1; Run_Index <= Number_Of_Runs ; ++Run_Index)
|
||||
#else /* SELF_TIMED */
|
||||
for (Run_Index = 1; ; ++Run_Index)
|
||||
#endif /* SELF_TIMED */
|
||||
{
|
||||
|
||||
Proc_5();
|
||||
Proc_4();
|
||||
/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
|
||||
Int_1_Loc = 2;
|
||||
Int_2_Loc = 3;
|
||||
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
|
||||
Enum_Loc = Ident_2;
|
||||
Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
|
||||
/* Bool_Glob == 1 */
|
||||
while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
|
||||
{
|
||||
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
|
||||
/* Int_3_Loc == 7 */
|
||||
Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
|
||||
/* Int_3_Loc == 7 */
|
||||
Int_1_Loc += 1;
|
||||
} /* while */
|
||||
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
|
||||
Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
|
||||
/* Int_Glob == 5 */
|
||||
Proc_1 (Ptr_Glob);
|
||||
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
|
||||
/* loop body executed twice */
|
||||
{
|
||||
if (Enum_Loc == Func_1 (Ch_Index, 'C'))
|
||||
/* then, not executed */
|
||||
{
|
||||
Proc_6 (Ident_1, &Enum_Loc);
|
||||
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
|
||||
Int_2_Loc = Run_Index;
|
||||
Int_Glob = Run_Index;
|
||||
}
|
||||
}
|
||||
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
|
||||
Int_2_Loc = Int_2_Loc * Int_1_Loc;
|
||||
Int_1_Loc = Int_2_Loc / Int_3_Loc;
|
||||
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
|
||||
/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
|
||||
Proc_2 (&Int_1_Loc);
|
||||
/* Int_1_Loc == 5 */
|
||||
|
||||
} /* loop "for Run_Index" */
|
||||
|
||||
/**************/
|
||||
/* Stop timer */
|
||||
/**************/
|
||||
#ifdef SELF_TIMED
|
||||
#ifdef TIMES
|
||||
times (&time_info);
|
||||
End_Time = (long) time_info.tms_utime;
|
||||
#endif
|
||||
#ifdef TIME
|
||||
End_Time = time ( (long *) 0);
|
||||
#endif
|
||||
#endif /* SELF_TIMED */
|
||||
|
||||
/* BYTE version never executes this stuff */
|
||||
#ifdef SELF_TIMED
|
||||
printf ("Execution ends\n");
|
||||
printf ("\n");
|
||||
printf ("Final values of the variables used in the benchmark:\n");
|
||||
printf ("\n");
|
||||
printf ("Int_Glob: %d\n", Int_Glob);
|
||||
printf (" should be: %d\n", 5);
|
||||
printf ("Bool_Glob: %d\n", Bool_Glob);
|
||||
printf (" should be: %d\n", 1);
|
||||
printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
|
||||
printf (" should be: %c\n", 'A');
|
||||
printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
|
||||
printf (" should be: %c\n", 'B');
|
||||
printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
|
||||
printf (" should be: %d\n", 7);
|
||||
printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
|
||||
printf (" should be: Number_Of_Runs + 10\n");
|
||||
printf ("Ptr_Glob->\n");
|
||||
printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
|
||||
printf (" should be: (implementation-dependent)\n");
|
||||
printf (" Discr: %d\n", Ptr_Glob->Discr);
|
||||
printf (" should be: %d\n", 0);
|
||||
printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
|
||||
printf (" should be: %d\n", 2);
|
||||
printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
|
||||
printf (" should be: %d\n", 17);
|
||||
printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
|
||||
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
printf ("Next_Ptr_Glob->\n");
|
||||
printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
|
||||
printf (" should be: (implementation-dependent), same as above\n");
|
||||
printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
|
||||
printf (" should be: %d\n", 0);
|
||||
printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
|
||||
printf (" should be: %d\n", 1);
|
||||
printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
|
||||
printf (" should be: %d\n", 18);
|
||||
printf (" Str_Comp: %s\n",
|
||||
Next_Ptr_Glob->variant.var_1.Str_Comp);
|
||||
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
|
||||
printf ("Int_1_Loc: %d\n", Int_1_Loc);
|
||||
printf (" should be: %d\n", 5);
|
||||
printf ("Int_2_Loc: %d\n", Int_2_Loc);
|
||||
printf (" should be: %d\n", 13);
|
||||
printf ("Int_3_Loc: %d\n", Int_3_Loc);
|
||||
printf (" should be: %d\n", 7);
|
||||
printf ("Enum_Loc: %d\n", Enum_Loc);
|
||||
printf (" should be: %d\n", 1);
|
||||
printf ("Str_1_Loc: %s\n", Str_1_Loc);
|
||||
printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
|
||||
printf ("Str_2_Loc: %s\n", Str_2_Loc);
|
||||
printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
|
||||
printf ("\n");
|
||||
|
||||
User_Time = End_Time - Begin_Time;
|
||||
|
||||
if (User_Time < Too_Small_Time)
|
||||
{
|
||||
printf ("Measured time too small to obtain meaningful results\n");
|
||||
printf ("Please increase number of runs\n");
|
||||
printf ("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
#ifdef TIME
|
||||
Microseconds = (float) User_Time * Mic_secs_Per_Second
|
||||
/ (float) Number_Of_Runs;
|
||||
Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
|
||||
#else
|
||||
Microseconds = (float) User_Time * Mic_secs_Per_Second
|
||||
/ ((float) HZ * ((float) Number_Of_Runs));
|
||||
Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
|
||||
/ (float) User_Time;
|
||||
#endif
|
||||
#else
|
||||
Microseconds = ((User_Time / Number_Of_Runs) * Mic_secs_Per_Second) / HZ;
|
||||
Dhrystones_Per_Second = (HZ * Number_Of_Runs) / User_Time;
|
||||
|
||||
sc_printf("Number_Of_Runs= %ld, HZ= %ld\n", Number_Of_Runs, HZ);
|
||||
sc_printf("Time: begin= %ld, end= %ld, diff= %ld\n", Begin_Time, End_Time, User_Time);
|
||||
sc_printf("Microseconds for one run through Dhrystone: %ld\n", Microseconds);
|
||||
sc_printf("Dhrystones per Second: %ld\n", Dhrystones_Per_Second);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif /* SELF_TIMED */
|
||||
}
|
||||
|
||||
|
||||
void Proc_1 (REG Rec_Pointer Ptr_Val_Par)
|
||||
/* executed once */
|
||||
{
|
||||
REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
|
||||
/* == Ptr_Glob_Next */
|
||||
/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
|
||||
/* corresponds to "rename" in Ada, "with" in Pascal */
|
||||
|
||||
structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
|
||||
Ptr_Val_Par->variant.var_1.Int_Comp = 5;
|
||||
Next_Record->variant.var_1.Int_Comp
|
||||
= Ptr_Val_Par->variant.var_1.Int_Comp;
|
||||
Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
|
||||
Proc_3 (&Next_Record->Ptr_Comp);
|
||||
/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
|
||||
== Ptr_Glob->Ptr_Comp */
|
||||
if (Next_Record->Discr == Ident_1)
|
||||
/* then, executed */
|
||||
{
|
||||
Next_Record->variant.var_1.Int_Comp = 6;
|
||||
Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
|
||||
&Next_Record->variant.var_1.Enum_Comp);
|
||||
Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
|
||||
Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
|
||||
&Next_Record->variant.var_1.Int_Comp);
|
||||
}
|
||||
else /* not executed */
|
||||
structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
|
||||
} /* Proc_1 */
|
||||
|
||||
|
||||
void Proc_2 (One_Fifty *Int_Par_Ref)
|
||||
/* executed once */
|
||||
/* *Int_Par_Ref == 1, becomes 4 */
|
||||
{
|
||||
One_Fifty Int_Loc;
|
||||
Enumeration Enum_Loc;
|
||||
|
||||
Enum_Loc = 0;
|
||||
|
||||
Int_Loc = *Int_Par_Ref + 10;
|
||||
do /* executed once */
|
||||
if (Ch_1_Glob == 'A')
|
||||
/* then, executed */
|
||||
{
|
||||
Int_Loc -= 1;
|
||||
*Int_Par_Ref = Int_Loc - Int_Glob;
|
||||
Enum_Loc = Ident_1;
|
||||
} /* if */
|
||||
while (Enum_Loc != Ident_1); /* true */
|
||||
} /* Proc_2 */
|
||||
|
||||
|
||||
void Proc_3 (Rec_Pointer *Ptr_Ref_Par)
|
||||
/* executed once */
|
||||
/* Ptr_Ref_Par becomes Ptr_Glob */
|
||||
{
|
||||
if (Ptr_Glob != Null)
|
||||
/* then, executed */
|
||||
*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
|
||||
Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
|
||||
} /* Proc_3 */
|
||||
|
||||
|
||||
void Proc_4 (void) /* without parameters */
|
||||
/* executed once */
|
||||
{
|
||||
Boolean Bool_Loc;
|
||||
|
||||
Bool_Loc = Ch_1_Glob == 'A';
|
||||
Bool_Glob = Bool_Loc | Bool_Glob;
|
||||
Ch_2_Glob = 'B';
|
||||
} /* Proc_4 */
|
||||
|
||||
void Proc_5 (void) /* without parameters */
|
||||
/*******/
|
||||
/* executed once */
|
||||
{
|
||||
Ch_1_Glob = 'A';
|
||||
Bool_Glob = false;
|
||||
} /* Proc_5 */
|
||||
|
||||
|
||||
/* Procedure for the assignment of structures, */
|
||||
/* if the C compiler doesn't support this feature */
|
||||
#ifdef NOSTRUCTASSIGN
|
||||
memcpy (d, s, l)
|
||||
register char *d;
|
||||
register char *s;
|
||||
register int l;
|
||||
{
|
||||
while (l--) *d++ = *s++;
|
||||
}
|
||||
#endif
|
||||
209
sim/tests/benchmarks/dhrystone21/dhry_2.c
Normal file
209
sim/tests/benchmarks/dhrystone21/dhry_2.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*****************************************************************************
|
||||
* The BYTE UNIX Benchmarks - Release 3
|
||||
* Module: dhry_2.c SID: 3.4 5/15/91 19:30:22
|
||||
*
|
||||
*****************************************************************************
|
||||
* Bug reports, patches, comments, suggestions should be sent to:
|
||||
*
|
||||
* Ben Smith, Rick Grehan or Tom Yager
|
||||
* ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com
|
||||
*
|
||||
*****************************************************************************
|
||||
* Modification Log:
|
||||
* 10/22/97 - code cleanup to remove ANSI C compiler warnings
|
||||
* Andy Kahn <kahn@zk3.dec.com>
|
||||
*
|
||||
* Adapted from:
|
||||
*
|
||||
* "DHRYSTONE" Benchmark Program
|
||||
* -----------------------------
|
||||
*
|
||||
* **** WARNING **** See warning in n.dhry_1.c
|
||||
*
|
||||
* Version: C, Version 2.1
|
||||
*
|
||||
* File: dhry_2.c (part 3 of 3)
|
||||
*
|
||||
* Date: May 25, 1988
|
||||
*
|
||||
* Author: Reinhold P. Weicker
|
||||
*
|
||||
****************************************************************************/
|
||||
/* SCCSid is defined in dhry_1.c */
|
||||
|
||||
#include <string.h>
|
||||
#include "dhry.h"
|
||||
|
||||
#ifndef REG
|
||||
#define REG
|
||||
/* REG becomes defined as empty */
|
||||
/* i.e. no register variables */
|
||||
#endif
|
||||
|
||||
extern int Int_Glob;
|
||||
extern char Ch_1_Glob;
|
||||
|
||||
void Proc_6(Enumeration, Enumeration *);
|
||||
void Proc_7(One_Fifty, One_Fifty, One_Fifty *);
|
||||
void Proc_8(Arr_1_Dim, Arr_2_Dim, int, int);
|
||||
Enumeration Func_1(Capital_Letter, Capital_Letter);
|
||||
Boolean Func_2(Str_30, Str_30);
|
||||
Boolean Func_3(Enumeration);
|
||||
|
||||
void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
|
||||
/* executed once */
|
||||
/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
|
||||
{
|
||||
*Enum_Ref_Par = Enum_Val_Par;
|
||||
if (! Func_3 (Enum_Val_Par))
|
||||
/* then, not executed */
|
||||
*Enum_Ref_Par = Ident_4;
|
||||
switch (Enum_Val_Par)
|
||||
{
|
||||
case Ident_1:
|
||||
*Enum_Ref_Par = Ident_1;
|
||||
break;
|
||||
case Ident_2:
|
||||
if (Int_Glob > 100)
|
||||
/* then */
|
||||
*Enum_Ref_Par = Ident_1;
|
||||
else *Enum_Ref_Par = Ident_4;
|
||||
break;
|
||||
case Ident_3: /* executed */
|
||||
*Enum_Ref_Par = Ident_2;
|
||||
break;
|
||||
case Ident_4: break;
|
||||
case Ident_5:
|
||||
*Enum_Ref_Par = Ident_3;
|
||||
break;
|
||||
} /* switch */
|
||||
} /* Proc_6 */
|
||||
|
||||
void Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
|
||||
One_Fifty Int_1_Par_Val;
|
||||
One_Fifty Int_2_Par_Val;
|
||||
One_Fifty *Int_Par_Ref;
|
||||
/**********************************************/
|
||||
/* executed three times */
|
||||
/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
|
||||
/* Int_Par_Ref becomes 7 */
|
||||
/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
|
||||
/* Int_Par_Ref becomes 17 */
|
||||
/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
|
||||
/* Int_Par_Ref becomes 18 */
|
||||
{
|
||||
One_Fifty Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 2;
|
||||
*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
|
||||
} /* Proc_7 */
|
||||
|
||||
|
||||
void Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
|
||||
/*********************************************************************/
|
||||
/* executed once */
|
||||
/* Int_Par_Val_1 == 3 */
|
||||
/* Int_Par_Val_2 == 7 */
|
||||
Arr_1_Dim Arr_1_Par_Ref;
|
||||
Arr_2_Dim Arr_2_Par_Ref;
|
||||
int Int_1_Par_Val;
|
||||
int Int_2_Par_Val;
|
||||
{
|
||||
REG One_Fifty Int_Index;
|
||||
REG One_Fifty Int_Loc;
|
||||
|
||||
Int_Loc = Int_1_Par_Val + 5;
|
||||
Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
|
||||
Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
|
||||
Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
|
||||
for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
|
||||
Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
|
||||
Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
|
||||
Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
|
||||
Int_Glob = 5;
|
||||
} /* Proc_8 */
|
||||
|
||||
|
||||
Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
|
||||
/*************************************************/
|
||||
/* executed three times */
|
||||
/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
|
||||
/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
|
||||
/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
|
||||
{
|
||||
Capital_Letter Ch_1_Loc;
|
||||
Capital_Letter Ch_2_Loc;
|
||||
|
||||
Ch_1_Loc = Ch_1_Par_Val;
|
||||
Ch_2_Loc = Ch_1_Loc;
|
||||
if (Ch_2_Loc != Ch_2_Par_Val)
|
||||
/* then, executed */
|
||||
return (Ident_1);
|
||||
else /* not executed */
|
||||
{
|
||||
Ch_1_Glob = Ch_1_Loc;
|
||||
return (Ident_2);
|
||||
}
|
||||
} /* Func_1 */
|
||||
|
||||
|
||||
|
||||
Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
|
||||
/*************************************************/
|
||||
/* executed once */
|
||||
/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
|
||||
/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
|
||||
|
||||
Str_30 Str_1_Par_Ref;
|
||||
Str_30 Str_2_Par_Ref;
|
||||
{
|
||||
REG One_Thirty Int_Loc;
|
||||
Capital_Letter Ch_Loc;
|
||||
|
||||
Ch_Loc = 'A';
|
||||
Int_Loc = 2;
|
||||
while (Int_Loc <= 2) /* loop body executed once */
|
||||
if (Func_1 (Str_1_Par_Ref[Int_Loc],
|
||||
Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
|
||||
/* then, executed */
|
||||
{
|
||||
Ch_Loc = 'A';
|
||||
Int_Loc += 1;
|
||||
} /* if, while */
|
||||
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
|
||||
/* then, not executed */
|
||||
Int_Loc = 7;
|
||||
if (Ch_Loc == 'R')
|
||||
/* then, not executed */
|
||||
return (true);
|
||||
else /* executed */
|
||||
{
|
||||
if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
|
||||
/* then, not executed */
|
||||
{
|
||||
Int_Loc += 7;
|
||||
Int_Glob = Int_Loc;
|
||||
return (true);
|
||||
}
|
||||
else /* executed */
|
||||
return (false);
|
||||
} /* if Ch_Loc */
|
||||
} /* Func_2 */
|
||||
|
||||
|
||||
Boolean Func_3 (Enum_Par_Val)
|
||||
/***************************/
|
||||
/* executed once */
|
||||
/* Enum_Par_Val == Ident_3 */
|
||||
Enumeration Enum_Par_Val;
|
||||
{
|
||||
Enumeration Enum_Loc;
|
||||
|
||||
Enum_Loc = Enum_Par_Val;
|
||||
if (Enum_Loc == Ident_3)
|
||||
/* then, executed */
|
||||
return (true);
|
||||
else /* not executed */
|
||||
return (false);
|
||||
} /* Func_3 */
|
||||
|
||||
24
sim/tests/common/LICENSE
Normal file
24
sim/tests/common/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2015, The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the Regents nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
47
sim/tests/common/common.mk
Normal file
47
sim/tests/common/common.mk
Normal file
@@ -0,0 +1,47 @@
|
||||
ADD_ASM_MACRO ?= -D__ASSEMBLY__=1
|
||||
|
||||
FLAGS = -O3 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las $(ADD_FLAGS)
|
||||
FLAGS_STR = "$(FLAGS)"
|
||||
|
||||
CFLAGS_COMMON = -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=$(TCM)
|
||||
CFLAGS_ARCH = -Wa,-march=rv32$(ARCH)_zicsr_zifencei -march=rv32$(ARCH)_zicsr_zifencei -mabi=$(ABI)
|
||||
|
||||
CFLAGS := $(FLAGS) $(EXT_CFLAGS) \
|
||||
$(CFLAGS_COMMON) \
|
||||
$(CFLAGS_ARCH) \
|
||||
-DFLAGS_STR=\"$(FLAGS_STR)\" \
|
||||
$(ADD_CFLAGS)
|
||||
|
||||
LDFLAGS ?= -nostartfiles -nostdlib -lc -lgcc -march=rv32$(ARCH)_zicsr_zifencei -mabi=$(ABI) --specs=nano.specs $(ADD_LDFLAGS)
|
||||
|
||||
ifeq (,$(findstring 0,$(TCM)))
|
||||
ld_script ?= $(inc_dir)/link_tcm.ld
|
||||
asm_src ?= crt_tcm.S
|
||||
else
|
||||
ld_script ?= $(inc_dir)/link.ld
|
||||
asm_src ?= crt.S
|
||||
endif
|
||||
|
||||
#this is optional assembly files from project
|
||||
asm_src += $(asm_src_in_project)
|
||||
|
||||
VPATH += $(src_dir) $(inc_dir) $(ADD_VPATH)
|
||||
incs += -I$(src_dir) -I$(inc_dir) $(ADD_incs)
|
||||
|
||||
c_objs := $(addprefix $(bld_dir)/,$(patsubst %.c, %.o, $(c_src)))
|
||||
asm_objs := $(addprefix $(bld_dir)/,$(patsubst %.S, %.o, $(asm_src)))
|
||||
|
||||
$(bld_dir)/%.o: %.S
|
||||
$(RISCV_GCC) $(CFLAGS) $(ADD_ASM_MACRO) -c $(incs) $< -o $@
|
||||
|
||||
$(bld_dir)/%.o: %.c
|
||||
$(RISCV_GCC) $(CFLAGS) -c $(incs) $< -o $@
|
||||
|
||||
$(bld_dir)/%.elf: $(ld_script) $(c_objs) $(asm_objs)
|
||||
$(RISCV_GCC) -o $@ -T $^ $(LDFLAGS)
|
||||
|
||||
$(bld_dir)/%.hex: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJCOPY) $^ $@
|
||||
|
||||
$(bld_dir)/%.dump: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJDUMP) -D -w -x -S $^ > $@
|
||||
146
sim/tests/common/crt.S
Normal file
146
sim/tests/common/crt.S
Normal file
@@ -0,0 +1,146 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <crt.S>
|
||||
///
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
# define LREG lw
|
||||
# define SREG sw
|
||||
# define REGBYTES 4
|
||||
|
||||
.globl _start
|
||||
.globl main
|
||||
.globl trap_entry
|
||||
.globl handle_trap
|
||||
.globl sc_exit
|
||||
.weak trap_entry, handle_trap
|
||||
|
||||
.text
|
||||
.org (64*3)
|
||||
.balign 64
|
||||
machine_trap_entry:
|
||||
j trap_entry
|
||||
|
||||
.balign 64
|
||||
|
||||
_start:
|
||||
#ifndef __RVE_EXT
|
||||
zero_int_regs 1, 31
|
||||
#else
|
||||
zero_int_regs 1, 15
|
||||
#endif
|
||||
# Global pointer init
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
# clear bss
|
||||
la a1, __BSS_START__
|
||||
la a2, __BSS_END__
|
||||
j 4f
|
||||
3: sw zero, 0(a1)
|
||||
add a1, a1, 4
|
||||
4: bne a1, a2, 3b
|
||||
la sp, __C_STACK_TOP__
|
||||
|
||||
// Timer init
|
||||
li t0, mtime_ctrl
|
||||
li t1, (1 << SCR1_MTIME_CTRL_EN) // enable, use internal clock
|
||||
sw t1, (t0)
|
||||
li t0, mtime_div
|
||||
li t1, (100-1) // divide by 100
|
||||
sw t1, (t0)
|
||||
li t0, mtimecmp
|
||||
li t1, -1
|
||||
sw t1, (t0) // max value for mtimecmp
|
||||
sw t1, 4(t0)
|
||||
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
call main
|
||||
tail sc_exit
|
||||
|
||||
trap_entry:
|
||||
addi sp, sp, -272
|
||||
|
||||
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)
|
||||
#ifndef __RVE_EXT
|
||||
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)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
|
||||
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)
|
||||
#ifndef __RVE_EXT
|
||||
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)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
addi sp, sp, 272
|
||||
mret
|
||||
|
||||
handle_trap:
|
||||
j SIM_EXIT
|
||||
|
||||
// end of crt.S
|
||||
155
sim/tests/common/crt_tcm.S
Normal file
155
sim/tests/common/crt_tcm.S
Normal file
@@ -0,0 +1,155 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <crt_tcm.S>
|
||||
///
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "reloc.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
# define LREG lw
|
||||
# define SREG sw
|
||||
# define REGBYTES 4
|
||||
|
||||
.globl _start
|
||||
.globl main
|
||||
.globl trap_entry
|
||||
.globl handle_trap
|
||||
.globl sc_exit
|
||||
.weak trap_entry, handle_trap
|
||||
|
||||
.section .text.init
|
||||
.org (64*3)
|
||||
.align 6;
|
||||
machine_trap_entry:
|
||||
j trap_entry
|
||||
|
||||
.align 6
|
||||
_start:
|
||||
#ifndef __RVE_EXT
|
||||
zero_int_regs 1, 31
|
||||
#else
|
||||
zero_int_regs 1, 15
|
||||
#endif
|
||||
# Global pointer init
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
RELOC_PROC;
|
||||
|
||||
// init tdata
|
||||
mv a1, tp
|
||||
la a2, _tdata_end
|
||||
j 6f
|
||||
5: lw a3, 0(a0)
|
||||
sw a3, 0(a1)
|
||||
add a0, a0, 4
|
||||
add a1, a1, 4
|
||||
6: bne a0, a2, 5b
|
||||
// clear tbss
|
||||
j 8f
|
||||
7: sw zero, 0(a1)
|
||||
add a1, a1, 4
|
||||
8: bne a1, a4, 7b
|
||||
|
||||
// Timer init
|
||||
li t0, mtime_ctrl
|
||||
li t1, (1 << SCR1_MTIME_CTRL_EN) // enable, use internal clock
|
||||
sw t1, (t0)
|
||||
li t0, mtime_div
|
||||
li t1, (100-1) // divide by 100
|
||||
sw t1, (t0)
|
||||
li t0, mtimecmp
|
||||
li t1, -1
|
||||
sw t1, (t0) // max value for mtimecmp
|
||||
sw t1, 4(t0)
|
||||
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
call main
|
||||
tail sc_exit
|
||||
|
||||
trap_entry:
|
||||
addi sp, sp, -272
|
||||
|
||||
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)
|
||||
#ifndef __RVE_EXT
|
||||
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)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
|
||||
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)
|
||||
#ifndef __RVE_EXT
|
||||
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)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
addi sp, sp, 272
|
||||
mret
|
||||
|
||||
handle_trap:
|
||||
j SIM_EXIT
|
||||
|
||||
// end of crt.S
|
||||
113
sim/tests/common/csr.h
Normal file
113
sim/tests/common/csr.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <csr.h>
|
||||
/// Architecture specific CSR's defs and inlines
|
||||
|
||||
#ifndef SCR_CSR_H
|
||||
#define SCR_CSR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __xstringify(s) __stringify(s)
|
||||
#define __stringify(s) #s
|
||||
|
||||
#ifdef read_csr
|
||||
#undef read_csr
|
||||
#endif
|
||||
|
||||
#ifdef write_csr
|
||||
#undef write_csr
|
||||
#endif
|
||||
|
||||
#ifdef swap_csr
|
||||
#undef swap_csr
|
||||
#endif
|
||||
|
||||
#ifdef set_csr
|
||||
#undef set_csr
|
||||
#endif
|
||||
|
||||
#ifdef clear_csr
|
||||
#undef clear_csr
|
||||
#endif
|
||||
|
||||
#ifdef rdtime
|
||||
#undef rdtime
|
||||
#endif
|
||||
|
||||
#ifdef rdcycle
|
||||
#undef rdcycle
|
||||
#endif
|
||||
|
||||
#ifdef rdinstret
|
||||
#undef rdinstret
|
||||
#endif
|
||||
|
||||
#define read_csr(reg) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " __xstringify(reg) : "=r"(__tmp)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define write_csr(reg, val) \
|
||||
do { \
|
||||
if (__builtin_constant_p(val) && (val) == 0) \
|
||||
asm volatile ("csrw " __xstringify(reg) ", zero" ::); \
|
||||
else if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " __xstringify(reg) ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " __xstringify(reg) ", %0" :: "r"(val)); \
|
||||
} while (0)
|
||||
|
||||
#define swap_csr(reg, val) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(val) && (val) == 0) \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", zero" : "=r"(__tmp) :); \
|
||||
else if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(val)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define set_csr(reg, bit) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (bit) < 32) \
|
||||
asm volatile ("csrrs %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define clear_csr(reg, bit) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (bit) < 32) \
|
||||
asm volatile ("csrrc %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define rdtime() read_csr(time)
|
||||
#define rdcycle() read_csr(cycle)
|
||||
#define rdinstret() read_csr(instret)
|
||||
|
||||
static inline unsigned long __attribute__((const)) hartid()
|
||||
{
|
||||
unsigned long res;
|
||||
asm ("csrr %0, mhartid" : "=r"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline unsigned long __attribute__((const)) impid()
|
||||
{
|
||||
unsigned long res;
|
||||
asm ("csrr %0, mimpid" : "=r"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // SCR_CSR_H
|
||||
99
sim/tests/common/link.ld
Normal file
99
sim/tests/common/link.ld
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
* @file <link.ld>
|
||||
* @brief bare metal tests' linker script
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 64K
|
||||
}
|
||||
|
||||
STACK_SIZE = 1024;
|
||||
|
||||
CL_SIZE = 32;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* code segment */
|
||||
.text.init 0 : {
|
||||
FILL(0);
|
||||
. = 0x100 - 12;
|
||||
SIM_EXIT = .;
|
||||
LONG(0x13);
|
||||
SIM_STOP = .;
|
||||
LONG(0x6F);
|
||||
LONG(-1);
|
||||
. = 0x100;
|
||||
PROVIDE(__TEXT_START__ = .);
|
||||
*(.text.init)
|
||||
} >RAM
|
||||
|
||||
.text : {
|
||||
*crt.o(.text .text.*)
|
||||
*(.text .text.*)
|
||||
*(sc_test_section)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__TEXT_END__ = .);
|
||||
} >RAM
|
||||
|
||||
/* data segment */
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
.sdata : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
/* thread-local data segment */
|
||||
.tdata : {
|
||||
PROVIDE(_tls_data = .);
|
||||
PROVIDE(_tdata_begin = .);
|
||||
*(.tdata .tdata.*)
|
||||
PROVIDE(_tdata_end = .);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
.tbss : {
|
||||
PROVIDE(__BSS_START__ = .);
|
||||
*(.tbss .tbss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(_tbss_end = .);
|
||||
} >RAM
|
||||
|
||||
/* bss segment */
|
||||
.sbss : {
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
} >RAM
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__BSS_END__ = .);
|
||||
} >RAM
|
||||
|
||||
_end = .;
|
||||
PROVIDE(__end = .);
|
||||
|
||||
/* End of uninitalized data segement */
|
||||
|
||||
.stack ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE : {
|
||||
FILL(0);
|
||||
PROVIDE(__STACK_START__ = .);
|
||||
. += STACK_SIZE;
|
||||
PROVIDE(__C_STACK_TOP__ = .);
|
||||
PROVIDE(__STACK_END__ = .);
|
||||
} >RAM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
||||
115
sim/tests/common/link_tcm.ld
Normal file
115
sim/tests/common/link_tcm.ld
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
* @file <link.ld>
|
||||
* @brief bare metal tests' linker script
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 64K
|
||||
TCM (rwx) : ORIGIN = 0x00480000, LENGTH = 64K
|
||||
}
|
||||
|
||||
STACK_SIZE = 1024;
|
||||
|
||||
CL_SIZE = 32;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* code segment */
|
||||
.text.init ORIGIN(RAM) : {
|
||||
FILL(0);
|
||||
. = 0x100 - 12;
|
||||
SIM_EXIT = .;
|
||||
LONG(0x13);
|
||||
SIM_STOP = .;
|
||||
LONG(0x6F);
|
||||
LONG(-1);
|
||||
. = 0x100;
|
||||
*crt_tcm.o(.text .text.*)
|
||||
*(.text.init)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
__reloc_start = .;
|
||||
|
||||
.text : {
|
||||
PROVIDE(__TEXT_START__ = .);
|
||||
*(.text .text.*)
|
||||
*(sc_test_section)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__TEXT_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.rodata ALIGN(CL_SIZE) : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
LONG(0x13);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
|
||||
/* data segment */
|
||||
.data ALIGN(CL_SIZE) : {
|
||||
PROVIDE(__DATA_START__ = .);
|
||||
*(.data .data.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
|
||||
.sdata ALIGN(CL_SIZE) : {
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__DATA_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
/* thread-local data segment */
|
||||
.tdata ALIGN(CL_SIZE) : {
|
||||
PROVIDE(_tls_data = .);
|
||||
PROVIDE(_tdata_begin = .);
|
||||
*(.tdata .tdata.*)
|
||||
PROVIDE(_tdata_end = .);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.tbss ALIGN(CL_SIZE) : {
|
||||
PROVIDE(_tbss_begin = .);
|
||||
*(.tbss .tbss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(_tbss_end = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
/* bss segment */
|
||||
.sbss ALIGN(CL_SIZE) : {
|
||||
PROVIDE(__BSS_START__ = .);
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.bss ALIGN(CL_SIZE) : {
|
||||
*(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__BSS_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
_end = .;
|
||||
PROVIDE(__end = .);
|
||||
|
||||
/* End of uninitalized data segement */
|
||||
|
||||
.stack ORIGIN(TCM) + LENGTH(TCM) - STACK_SIZE : {
|
||||
PROVIDE(__STACK_START__ = .);
|
||||
. += STACK_SIZE;
|
||||
PROVIDE(__C_STACK_TOP__ = .);
|
||||
PROVIDE(__STACK_END__ = .);
|
||||
} >TCM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
||||
37
sim/tests/common/reloc.h
Normal file
37
sim/tests/common/reloc.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef RELOC_H
|
||||
#define RELOC_H
|
||||
|
||||
#if (TCM == 1)
|
||||
#define RELOC_PROC \
|
||||
la a0, __reloc_start; \
|
||||
la a1, __TEXT_START__; \
|
||||
la a2, __DATA_END__; \
|
||||
beq a0, a1, 21f; \
|
||||
j 2f; \
|
||||
1: lw a3, 0(a0); \
|
||||
sw a3, 0(a1); \
|
||||
add a0, a0, 4; \
|
||||
add a1, a1, 4; \
|
||||
2: bne a1, a2, 1b; \
|
||||
/* clear bss */ \
|
||||
la a2, __BSS_START__; \
|
||||
21: la a1, __BSS_END__; \
|
||||
j 4f; \
|
||||
3: sw zero, 0(a2); \
|
||||
add a2, a2, 4; \
|
||||
4: bne a1, a2, 3b; \
|
||||
/* init stack */ \
|
||||
la sp, __C_STACK_TOP__; \
|
||||
/* init hart0 TLS */ \
|
||||
la a0, _tdata_begin; \
|
||||
la a2, _tbss_end; \
|
||||
sub a1, a2, a0; \
|
||||
la a4, __STACK_START__; \
|
||||
sub tp, a4, a1;
|
||||
#else // #if TCM
|
||||
|
||||
#define RELOC_PROC
|
||||
|
||||
#endif // #else #if TCM
|
||||
|
||||
#endif //
|
||||
1473
sim/tests/common/riscv_csr_encoding.h
Normal file
1473
sim/tests/common/riscv_csr_encoding.h
Normal file
File diff suppressed because it is too large
Load Diff
819
sim/tests/common/riscv_macros.h
Normal file
819
sim/tests/common/riscv_macros.h
Normal file
@@ -0,0 +1,819 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef __RISCV_MACROS_H
|
||||
#define __RISCV_MACROS_H
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Begin Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_RV64U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
|
||||
#else
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
|
||||
#endif
|
||||
|
||||
#define INIT_PMP \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
li t0, -1; /* Set up a PMP to permit all accesses */ \
|
||||
csrw pmpaddr0, t0; \
|
||||
li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X; \
|
||||
csrw pmpcfg0, t0; \
|
||||
.balign 4; \
|
||||
1:
|
||||
|
||||
#define INIT_SPTBR \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
csrwi sptbr, 0; \
|
||||
.balign 4; \
|
||||
1:
|
||||
|
||||
#define DELEGATE_NO_TRAPS
|
||||
|
||||
#define RVTEST_ENABLE_SUPERVISOR \
|
||||
li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
li a0, SIP_SSIP | SIP_STIP; \
|
||||
csrs mideleg, a0; \
|
||||
|
||||
#define RVTEST_ENABLE_MACHINE \
|
||||
li a0, MSTATUS_MPP; \
|
||||
csrs mstatus, a0; \
|
||||
|
||||
#define RVTEST_FP_ENABLE \
|
||||
li a0, MSTATUS_FS & (MSTATUS_FS >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
csrwi fcsr, 0
|
||||
|
||||
#define RISCV_MULTICORE_DISABLE \
|
||||
csrr a0, mhartid; \
|
||||
1: bnez a0, 1b
|
||||
|
||||
#define EXTRA_TVEC_USER
|
||||
#define EXTRA_TVEC_SUPERVISOR
|
||||
#define EXTRA_TVEC_HYPERVISOR
|
||||
#define EXTRA_TVEC_MACHINE
|
||||
#define EXTRA_INIT
|
||||
#define EXTRA_INIT_TIMER
|
||||
|
||||
#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */
|
||||
|
||||
#define RVTEST_CODE_BEGIN \
|
||||
.section .text.init; \
|
||||
.org 0xC0, 0x00; \
|
||||
.balign 64; \
|
||||
.weak stvec_handler; \
|
||||
.weak mtvec_handler; \
|
||||
trap_vector: \
|
||||
/* test whether the test came from pass/fail */ \
|
||||
csrr a4, mcause; \
|
||||
li a5, CAUSE_USER_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
li a5, CAUSE_SUPERVISOR_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
li a5, CAUSE_MACHINE_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
/* if an mtvec_handler is defined, jump to it */ \
|
||||
la a4, mtvec_handler; \
|
||||
beqz a4, 1f; \
|
||||
jr a4; \
|
||||
/* was it an interrupt or an exception? */ \
|
||||
1: csrr a4, mcause; \
|
||||
bgez a4, handle_exception; \
|
||||
INTERRUPT_HANDLER; \
|
||||
handle_exception: \
|
||||
/* we don't know how to handle whatever the exception was */ \
|
||||
other_exception: \
|
||||
/* some unhandlable exception occurred */ \
|
||||
li a0, 0x1; \
|
||||
_report: \
|
||||
j sc_exit; \
|
||||
.balign 64; \
|
||||
.globl _start; \
|
||||
_start: \
|
||||
RISCV_MULTICORE_DISABLE; \
|
||||
/*INIT_SPTBR;*/ \
|
||||
/*INIT_PMP;*/ \
|
||||
DELEGATE_NO_TRAPS; \
|
||||
li TESTNUM, 0; \
|
||||
la t0, trap_vector; \
|
||||
csrw mtvec, t0; \
|
||||
CHECK_XLEN; \
|
||||
/* if an stvec_handler is defined, delegate exceptions to it */ \
|
||||
la t0, stvec_handler; \
|
||||
beqz t0, 1f; \
|
||||
csrw stvec, t0; \
|
||||
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; \
|
||||
1: csrwi mstatus, 0; \
|
||||
init; \
|
||||
EXTRA_INIT; \
|
||||
EXTRA_INIT_TIMER; \
|
||||
la t0, _run_test; \
|
||||
csrw mepc, t0; \
|
||||
csrr a0, mhartid; \
|
||||
mret; \
|
||||
.section .text; \
|
||||
_run_test:
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// End Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_CODE_END ecall: ecall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Pass/Fail Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_PASS \
|
||||
fence; \
|
||||
mv a1, TESTNUM; \
|
||||
li a0, 0x0; \
|
||||
ecall
|
||||
|
||||
#define TESTNUM x28
|
||||
#define RVTEST_FAIL \
|
||||
fence; \
|
||||
mv a1, TESTNUM; \
|
||||
li a0, 0x1; \
|
||||
ecall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Data Section Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define EXTRA_DATA
|
||||
|
||||
#define RVTEST_DATA_BEGIN \
|
||||
EXTRA_DATA \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.balign 64; .global tohost; tohost: .dword 0; \
|
||||
.balign 64; .global fromhost; fromhost: .dword 0; \
|
||||
.popsection; \
|
||||
.balign 16; \
|
||||
.global begin_regstate; begin_regstate: .dword 0; .dword 0; .dword 0; \
|
||||
.balign 16; \
|
||||
.global begin_signature; begin_signature:
|
||||
|
||||
#define RVTEST_DATA_END .balign 16; .global end_signature; end_signature:
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Helper macros
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
|
||||
|
||||
#define TEST_CASE( testnum, testreg, correctval, code... ) \
|
||||
test_ ## testnum: \
|
||||
code; \
|
||||
li x29, MASK_XLEN(correctval); \
|
||||
li TESTNUM, testnum; \
|
||||
bne testreg, x29, fail;
|
||||
|
||||
# We use a macro hack to simpify code generation for various numbers
|
||||
# of bubble cycles.
|
||||
|
||||
#define TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_1 nop; TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_2 nop; TEST_INSERT_NOPS_1
|
||||
#define TEST_INSERT_NOPS_3 nop; TEST_INSERT_NOPS_2
|
||||
#define TEST_INSERT_NOPS_4 nop; TEST_INSERT_NOPS_3
|
||||
#define TEST_INSERT_NOPS_5 nop; TEST_INSERT_NOPS_4
|
||||
#define TEST_INSERT_NOPS_6 nop; TEST_INSERT_NOPS_5
|
||||
#define TEST_INSERT_NOPS_7 nop; TEST_INSERT_NOPS_6
|
||||
#define TEST_INSERT_NOPS_8 nop; TEST_INSERT_NOPS_7
|
||||
#define TEST_INSERT_NOPS_9 nop; TEST_INSERT_NOPS_8
|
||||
#define TEST_INSERT_NOPS_10 nop; TEST_INSERT_NOPS_9
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UI MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for instructions with immediate operand
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
|
||||
|
||||
#define TEST_IMM_OP( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_OP_RVC( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, val1; \
|
||||
inst x1, imm; \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x1, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZEROSRC1( testnum, inst, result, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
inst x1, x0, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZERODEST( testnum, inst, val1, imm ) \
|
||||
TEST_CASE( testnum, x0, 0, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x0, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for vector config instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_VSETCFGIVL( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12); \
|
||||
vsetcfg x1,nxpr,nfpr; \
|
||||
li x1, vl; \
|
||||
vsetvl x1,x1; \
|
||||
)
|
||||
|
||||
#define TEST_VVCFG( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12) | (nfpr << 6) | nxpr; \
|
||||
vsetcfg x1; \
|
||||
li x1, vl; \
|
||||
vsetvl x1,x1; \
|
||||
)
|
||||
|
||||
#define TEST_VSETVL( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12); \
|
||||
vsetcfg x1,nxpr,nfpr; \
|
||||
li x1, vl; \
|
||||
vsetvl x1, x1; \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_R_OP( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, val1; \
|
||||
inst x3, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_SRC1_EQ_DEST( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, val1; \
|
||||
inst x1, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_DEST_BYPASS( testnum, nop_cycles, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
inst x3, x1; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register-register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x3, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x1, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x2, x1, x2; \
|
||||
)
|
||||
|
||||
#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 x2, MASK_XLEN(val2); \
|
||||
inst x3, x1, x2; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 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, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x3, x1, x2; \
|
||||
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, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x3, x1, x2; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, x0, x1; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, 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 x2, MASK_XLEN(val2); \
|
||||
inst x0, x1, x2; \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test memory instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_LD_OP( testnum, inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
la x1, base; \
|
||||
inst x3, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
la x1, base; \
|
||||
li x2, result; \
|
||||
store_inst x2, offset(x1); \
|
||||
load_inst x3, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_LD_DEST_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
inst x3, offset(x1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
li x29, result; \
|
||||
bne x6, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b; \
|
||||
|
||||
#define TEST_LD_SRC1_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x3, offset(x1); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC12_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x3, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC21_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x3, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test branch instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_BR1_OP_TAKEN( testnum, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
inst x1, 2f; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
1: bne x0, TESTNUM, 3f; \
|
||||
2: inst x1, 1b; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
3:
|
||||
|
||||
#define TEST_BR1_OP_NOTTAKEN( testnum, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
inst x1, 1f; \
|
||||
bne x0, TESTNUM, 2f; \
|
||||
1: bne x0, TESTNUM, fail; \
|
||||
2: inst x1, 1b; \
|
||||
3:
|
||||
|
||||
#define TEST_BR1_SRC1_BYPASS( testnum, nop_cycles, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x1, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_OP_TAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 2f; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
1: bne x0, TESTNUM, 3f; \
|
||||
2: inst x1, x2, 1b; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_OP_NOTTAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 1f; \
|
||||
bne x0, TESTNUM, 2f; \
|
||||
1: bne x0, TESTNUM, fail; \
|
||||
2: inst x1, x2, 1b; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test jump instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_JR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x6; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_JALR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x19, x6, 0; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UF MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests floating-point instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define qNaNf 0f:7fc00000
|
||||
#define sNaNf 0f:7f800001
|
||||
#define qNaN 0d:7ff8000000000000
|
||||
#define sNaN 0d:7ff0000000000001
|
||||
|
||||
#define TEST_FP_OP_S_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
flw f0, 0(a0); \
|
||||
flw f1, 4(a0); \
|
||||
flw f2, 8(a0); \
|
||||
lw a3, 12(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
j 2f; \
|
||||
.balign 4; \
|
||||
.data; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.float val3; \
|
||||
.result; \
|
||||
.text; \
|
||||
2:
|
||||
|
||||
#define TEST_FP_OP_D_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld f0, 0(a0); \
|
||||
fld f1, 8(a0); \
|
||||
fld f2, 16(a0); \
|
||||
ld a3, 24(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
j 2f; \
|
||||
.data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.result; \
|
||||
.text; \
|
||||
2:
|
||||
|
||||
#define TEST_FCVT_S_D( testnum, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
|
||||
fcvt.s.d f3, f0; fcvt.d.s f3, f3; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FCVT_D_S( testnum, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, 0, float result, val1, 0.0, 0.0, \
|
||||
fcvt.d.s f3, f0; fcvt.s.d f3, f3; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_S( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_D( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_INT_OP_S( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_INT_OP_D( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_CMP_OP_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FP_CMP_OP_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FCLASS_S(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.s.x fa0, a0; \
|
||||
fclass.s a0, fa0)
|
||||
|
||||
#define TEST_FCLASS_D(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.d.x fa0, a0; \
|
||||
fclass.d a0, fa0)
|
||||
|
||||
#define TEST_INT_FP_OP_S( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
lw a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.s a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
j 1f; \
|
||||
.balign 4; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float result; \
|
||||
1:
|
||||
|
||||
#define TEST_INT_FP_OP_D( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
ld a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.d a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
j 1f; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double result; \
|
||||
1:
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Pass and fail code (assumes test num is in TESTNUM)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_PASSFAIL \
|
||||
bne x0, TESTNUM, pass; \
|
||||
fail: \
|
||||
RVTEST_FAIL; \
|
||||
pass: \
|
||||
RVTEST_PASS \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test data section
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_DATA
|
||||
|
||||
#endif
|
||||
|
||||
282
sim/tests/common/sc_print.c
Normal file
282
sim/tests/common/sc_print.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_print.c>
|
||||
///
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "sc_print.h"
|
||||
|
||||
#define SC_SIM_OUTPORT (0xf0000000)
|
||||
#define CHAR_BIT (8)
|
||||
|
||||
static void
|
||||
sc_puts(long str, long strlen) {
|
||||
volatile char *out_ptr = (volatile char*)SC_SIM_OUTPORT;
|
||||
const char *in_ptr = (const char*)str;
|
||||
for (long len = strlen; len > 0; --len)
|
||||
*out_ptr = *in_ptr++;
|
||||
}
|
||||
|
||||
#undef putchar
|
||||
int
|
||||
putchar(int ch) {
|
||||
static __thread char buf[64] __attribute__((aligned(64)));
|
||||
static __thread int buflen = 0;
|
||||
|
||||
buf[buflen++] = ch;
|
||||
|
||||
if ( ch == '\n' || buflen == sizeof(buf) ) {
|
||||
sc_puts((long)buf, buflen);
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
printf_putch(int ch, void** data)
|
||||
{
|
||||
putchar(ch);
|
||||
}
|
||||
|
||||
static void
|
||||
print(const char *str)
|
||||
{
|
||||
sc_puts((long)str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
static long long
|
||||
getint(va_list *ap, int lflag)
|
||||
{
|
||||
if ( lflag >= 2 )
|
||||
return va_arg(*ap, long long);
|
||||
else if ( lflag )
|
||||
return va_arg(*ap, long);
|
||||
else
|
||||
return va_arg(*ap, int);
|
||||
}
|
||||
|
||||
|
||||
static unsigned long long
|
||||
getuint(va_list *ap, int lflag)
|
||||
{
|
||||
if ( lflag >= 2 )
|
||||
return va_arg(*ap, unsigned long long);
|
||||
else if ( lflag )
|
||||
return va_arg(*ap, unsigned long);
|
||||
else
|
||||
return va_arg(*ap, unsigned int);
|
||||
}
|
||||
|
||||
static inline void
|
||||
printnum(void(*putch)(int, void**),
|
||||
void **putdat,
|
||||
unsigned long long num,
|
||||
unsigned base,
|
||||
int width,
|
||||
int padc,
|
||||
int hex_A)
|
||||
{
|
||||
unsigned digs[sizeof(num) * CHAR_BIT];
|
||||
int pos = 0;
|
||||
|
||||
for ( ;; ) {
|
||||
digs[pos++] = num % base;
|
||||
if ( num < base )
|
||||
break;
|
||||
num /= base;
|
||||
}
|
||||
|
||||
while ( width-- > pos )
|
||||
putch(padc, putdat);
|
||||
|
||||
while ( pos-- > 0 )
|
||||
putch(digs[pos] + (digs[pos] >= 10 ? hex_A - 10 : '0'), putdat);
|
||||
}
|
||||
|
||||
static void
|
||||
vprintfmt(void(*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
|
||||
{
|
||||
register const char* p;
|
||||
const char* last_fmt;
|
||||
register int ch;
|
||||
int err;
|
||||
unsigned long long num;
|
||||
int base;
|
||||
int lflag;
|
||||
int width;
|
||||
int precision;
|
||||
int altflag;
|
||||
char padc;
|
||||
int hex_A = 'a';
|
||||
for ( ;; ) {
|
||||
while ( (ch = *(unsigned char *)fmt) != '%' ) {
|
||||
if ( ch == '\0' )
|
||||
return;
|
||||
++fmt;
|
||||
putch(ch, putdat);
|
||||
}
|
||||
++fmt;
|
||||
|
||||
// Process a %-escape sequence
|
||||
last_fmt = fmt;
|
||||
padc = ' ';
|
||||
width = -1;
|
||||
precision = -1;
|
||||
lflag = 0;
|
||||
altflag = 0;
|
||||
|
||||
reswitch:
|
||||
switch ( ch = *(unsigned char *)fmt++ ) {
|
||||
// flag to pad on the right
|
||||
case '-':
|
||||
padc = '-';
|
||||
goto reswitch;
|
||||
|
||||
// flag to pad with 0's instead of spaces
|
||||
case '0':
|
||||
padc = '0';
|
||||
goto reswitch;
|
||||
|
||||
// width field
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
for ( precision = 0;; ++fmt ) {
|
||||
precision = precision * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if ( ch < '0' || ch > '9' )
|
||||
break;
|
||||
}
|
||||
goto process_precision;
|
||||
|
||||
case '*':
|
||||
precision = va_arg(ap, int);
|
||||
goto process_precision;
|
||||
|
||||
case '.':
|
||||
if ( width < 0 )
|
||||
width = 0;
|
||||
goto reswitch;
|
||||
|
||||
case '#':
|
||||
altflag = 1;
|
||||
goto reswitch;
|
||||
|
||||
process_precision:
|
||||
if ( width < 0 ) {
|
||||
width = precision;
|
||||
precision = -1;
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
// long flag (doubled for long long)
|
||||
case 'l':
|
||||
lflag++;
|
||||
goto reswitch;
|
||||
|
||||
// character
|
||||
case 'c':
|
||||
putch(va_arg(ap, int), putdat);
|
||||
break;
|
||||
|
||||
// string
|
||||
case 's':
|
||||
if ( (p = va_arg(ap, char *)) == NULL )
|
||||
p = "(null)";
|
||||
if ( width > 0 && padc != '-' )
|
||||
for ( width -= strnlen(p, precision); width > 0; width-- )
|
||||
putch(padc, putdat);
|
||||
for ( ; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width-- ) {
|
||||
putch(ch, putdat);
|
||||
p++;
|
||||
}
|
||||
for ( ; width > 0; width-- )
|
||||
putch(' ', putdat);
|
||||
break;
|
||||
|
||||
// (signed) decimal
|
||||
case 'd':
|
||||
num = getint(&ap, lflag);
|
||||
if ( (long long)num < 0 ) {
|
||||
putch('-', putdat);
|
||||
num = -(long long)num;
|
||||
}
|
||||
base = 10;
|
||||
goto signed_number;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
// #ifndef nopfloat
|
||||
// double num = getdouble(&ap, lflag);
|
||||
// printdoubleF(putch, putdat, num, width, precision, padc);
|
||||
// #endif
|
||||
}
|
||||
break;
|
||||
|
||||
// unsigned decimal
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto unsigned_number;
|
||||
|
||||
// (unsigned) octal
|
||||
case 'o':
|
||||
// should do something with padding so it's always 3 octits
|
||||
base = 8;
|
||||
goto unsigned_number;
|
||||
|
||||
// pointer
|
||||
case 'p':
|
||||
// static_assert(sizeof(long) == sizeof(void*));
|
||||
lflag = 1;
|
||||
putch('0', putdat);
|
||||
putch('x', putdat);
|
||||
/* fall through to 'x' */
|
||||
|
||||
// (unsigned) hexadecimal
|
||||
case 'x':
|
||||
hex_A = 'a';
|
||||
base = 16;
|
||||
goto unsigned_number;
|
||||
|
||||
case 'X':
|
||||
hex_A = 'A';
|
||||
base = 16;
|
||||
unsigned_number:
|
||||
num = getuint(&ap, lflag);
|
||||
signed_number:
|
||||
printnum(putch, putdat, num, base, width, padc, hex_A);
|
||||
break;
|
||||
|
||||
// escaped '%' character
|
||||
case '%':
|
||||
putch(ch, putdat);
|
||||
break;
|
||||
|
||||
// unrecognized escape sequence - just print it literally
|
||||
default:
|
||||
putch('%', putdat);
|
||||
fmt = last_fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sc_printf(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vprintfmt(printf_putch, NULL, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
return 0; // incorrect return value, but who cares, anyway?
|
||||
}
|
||||
10
sim/tests/common/sc_print.h
Normal file
10
sim/tests/common/sc_print.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_print.h>
|
||||
///
|
||||
|
||||
#ifndef SC_PRINT_H
|
||||
#define SC_PRINT_H
|
||||
|
||||
extern int sc_printf(const char* fmt, ...);
|
||||
|
||||
#endif // SC_PRINT_H
|
||||
48
sim/tests/common/sc_test.h
Normal file
48
sim/tests/common/sc_test.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_test.h>
|
||||
///
|
||||
|
||||
#ifndef SC_TEST_H
|
||||
#define SC_TEST_H
|
||||
|
||||
#if defined(__ASSEMBLER__)
|
||||
.altmacro
|
||||
|
||||
.macro zero_int_reg regn
|
||||
mv x\regn, zero
|
||||
.endm
|
||||
|
||||
.macro zero_int_regs reg_first, reg_last
|
||||
.set regn, \reg_first
|
||||
.rept \reg_last - \reg_first + 1
|
||||
zero_int_reg %(regn)
|
||||
.set regn, regn+1
|
||||
.endr
|
||||
.endm
|
||||
|
||||
#define report_results(result) \
|
||||
li a0, result; \
|
||||
la t0, sc_exit; \
|
||||
jr t0;
|
||||
|
||||
.pushsection sc_test_section, "ax"
|
||||
sc_exit: la t0, SIM_EXIT; jr t0;
|
||||
.balign 32
|
||||
.popsection
|
||||
#define sc_pass report_results(0x0)
|
||||
#define sc_fail report_results(0x1)
|
||||
|
||||
#else
|
||||
|
||||
extern void sc_exit(unsigned result, unsigned res0, unsigned res1, unsigned res2, unsigned res3)
|
||||
__attribute__ ((noinline, noreturn));
|
||||
|
||||
static inline void __attribute__ ((noreturn))
|
||||
report_results(unsigned result, unsigned res0, unsigned res1, unsigned res2, unsigned res3)
|
||||
{
|
||||
sc_exit(result, res0, res1, res2, res3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SC_TEST_H
|
||||
20
sim/tests/common/scr1_specific.h
Normal file
20
sim/tests/common/scr1_specific.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCR1__SPECIFIC
|
||||
#define __SCR1__SPECIFIC
|
||||
|
||||
#define mcounten 0x7E0
|
||||
|
||||
// Memory-mapped registers
|
||||
#define mtime_ctrl 0x00490000
|
||||
#define mtime_div 0x00490004
|
||||
#define mtime 0x00490008
|
||||
#define mtimeh 0x0049000C
|
||||
#define mtimecmp 0x00490010
|
||||
#define mtimecmph 0x00490014
|
||||
|
||||
#define SCR1_MTIME_CTRL_EN 0
|
||||
#define SCR1_MTIME_CTRL_CLKSRC 1
|
||||
|
||||
#define SCR1_MTIME_CTRL_WR_MASK 0x3
|
||||
#define SCR1_MTIME_DIV_WR_MASK 0x3FF
|
||||
|
||||
#endif // _SCR1__SPECIFIC
|
||||
13
sim/tests/hello/Makefile
Normal file
13
sim/tests/hello/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
src_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
c_src := sc_print.c hello.c
|
||||
|
||||
include $(inc_dir)/common.mk
|
||||
|
||||
default: log_requested_tgt $(bld_dir)/hello.elf $(bld_dir)/hello.hex $(bld_dir)/hello.dump
|
||||
|
||||
log_requested_tgt:
|
||||
echo hello.hex>> $(bld_dir)/test_info
|
||||
|
||||
clean:
|
||||
$(RM) $(c_objs) $(asm_objs) $(bld_dir)/hello.elf $(bld_dir)/hello.hex $(bld_dir)/hello.dump
|
||||
7
sim/tests/hello/hello.c
Normal file
7
sim/tests/hello/hello.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "sc_print.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
sc_printf("Hello from SCR1!\n");
|
||||
return 0;
|
||||
}
|
||||
26
sim/tests/isr_sample/Makefile
Normal file
26
sim/tests/isr_sample/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
src_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
LDFLAGS := -nostartfiles -nostdlib -march=rv32$(ARCH)_zicsr_zifencei -mabi=$(ABI)
|
||||
ADD_ASM_MACRO := -DASM
|
||||
|
||||
ifeq ($(IPIC) ,1)
|
||||
ADD_ASM_MACRO += -DIPIC_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(VECT_IRQ) ,1)
|
||||
ADD_ASM_MACRO += -DVECT_IRQ_ENABLED
|
||||
endif
|
||||
asm_src := isr_sample.S
|
||||
|
||||
# override ld script
|
||||
ld_script := $(inc_dir)/link.ld
|
||||
|
||||
include $(inc_dir)/common.mk
|
||||
|
||||
default: log_requested_tgt $(bld_dir)/isr_sample.elf $(bld_dir)/isr_sample.hex $(bld_dir)/isr_sample.dump
|
||||
|
||||
log_requested_tgt:
|
||||
echo isr_sample.hex >> $(bld_dir)/test_info
|
||||
|
||||
clean:
|
||||
$(RM)$(asm_objs) $(bld_dir)/isr_sample.elf $(bld_dir)/isr_sample.hex $(bld_dir)/isr_sample.dump
|
||||
291
sim/tests/isr_sample/isr_sample.S
Normal file
291
sim/tests/isr_sample/isr_sample.S
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "riscv_macros.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
.altmacro
|
||||
// global interrupt bit
|
||||
#define MSIE (1 << IRQ_M_SOFT) //machine software interrupt enable
|
||||
#define MTIE (1 << IRQ_M_TIMER) //machine timer interrupt enable
|
||||
#define MEIE (1 << IRQ_M_EXT) //machine external interrupt enable
|
||||
#define MCAUSE_EXT_IRQ (1 << 31 | IRQ_M_EXT)
|
||||
#define MCAUSE_SOFT_IRQ (1 << 31 | IRQ_M_SOFT)
|
||||
#define MCAUSE_TMR_IRQ (1 << 31 | IRQ_M_TIMER)
|
||||
|
||||
// IPIC
|
||||
#define IRQ_LINES_ADDR 0xF0000100 // simulation
|
||||
#define TRIG_EXT_IRQ_ADDR 0xF0000100 // external irq is triggered when tb memory is set to non-zero
|
||||
#define TRIG_SW_IRQ_ADDR 0xF0000200 // software irq is triggered when tb memory is set to non-zero
|
||||
|
||||
#define IPIC_EOI 0xBF4 // end of interrupt
|
||||
#define IPIC_SOI 0xBF5 // start of interrupt
|
||||
#define IPIC_IDX 0xBF6 // index register
|
||||
#define IPIC_ICSR 0xBF7 // interrupt control status register
|
||||
|
||||
// IPIC Interrupt Constrol Status Register
|
||||
#define IPIC_ICSR_IP (1 << 0) // interrupt pending
|
||||
#define IPIC_ICSR_IE (1 << 1) // interrupt enable
|
||||
#define IPIC_ICSR_IM (1 << 2) // interrupt mode (0/1: level/edge)
|
||||
#define IPIC_ICSR_INV (1 << 3) // line inversion
|
||||
#define IPIC_ICSR_IS (1 << 4) // in service
|
||||
|
||||
// Interrupt lines in use
|
||||
#define IPIC_IRQ_LINE9 9
|
||||
#define EXT_IRQ_LINE_COMMON 0
|
||||
|
||||
#include "timer.h"
|
||||
#include "reloc.h"
|
||||
|
||||
.macro jmp_sc_exit
|
||||
la t0, sc_exit
|
||||
jr t0
|
||||
.endm
|
||||
|
||||
.section .text.init
|
||||
.option norvc
|
||||
.globl _start
|
||||
// -----------------------------------------------------------------
|
||||
// Trap handlers
|
||||
// 0xXXXXXX00
|
||||
.option norvc
|
||||
.org (64*3)
|
||||
|
||||
//0xXXXXXXC0
|
||||
.balign 64
|
||||
machine_trap_entry:
|
||||
vec_usr_soft:
|
||||
#ifdef VECT_IRQ_ENABLED
|
||||
trap_entry:
|
||||
j _trap_fail
|
||||
vec_supervisor_soft:
|
||||
j _trap_fail
|
||||
vec_reserved1:
|
||||
j _trap_fail
|
||||
vec_machine_soft:
|
||||
j vec_machine_soft_handler
|
||||
vec_usr_tmr:
|
||||
j _trap_fail
|
||||
vec_supervisor_tmr:
|
||||
j _trap_fail
|
||||
vec_reserved2:
|
||||
j _trap_fail
|
||||
vec_machine_tmr:
|
||||
j vec_machine_tmr_handler
|
||||
vec_usr_ext:
|
||||
j _trap_fail
|
||||
vec_supervisor_ext:
|
||||
j _trap_fail
|
||||
vec_reserved3:
|
||||
j _trap_fail
|
||||
vec_machine_ext:
|
||||
j vec_machine_ext_handler
|
||||
vec_reserved4:
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
#else
|
||||
trap_entry:
|
||||
j direct_irq_handler
|
||||
vec_supervisor_soft:
|
||||
j _trap_fail
|
||||
vec_reserved1:
|
||||
j _trap_fail
|
||||
vec_machine_soft:
|
||||
j _trap_fail
|
||||
vec_usr_tmr:
|
||||
j _trap_fail
|
||||
vec_supervisor_tmr:
|
||||
j _trap_fail
|
||||
vec_reserved2:
|
||||
j _trap_fail
|
||||
vec_machine_tmr:
|
||||
j _trap_fail
|
||||
vec_usr_ext:
|
||||
j _trap_fail
|
||||
vec_supervisor_ext:
|
||||
j _trap_fail
|
||||
vec_reserved3:
|
||||
j _trap_fail
|
||||
vec_machine_ext:
|
||||
j _trap_fail
|
||||
vec_reserved4:
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
j _trap_fail
|
||||
|
||||
#endif // ifdef VECT_IRQ_ENABLED
|
||||
|
||||
|
||||
.balign 64
|
||||
_start:
|
||||
la t0, machine_trap_entry
|
||||
csrw mtvec, t0
|
||||
|
||||
la t0, test_start
|
||||
jr (t0)
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
.option norvc
|
||||
.balign 64
|
||||
test_start:
|
||||
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0 // set mtvec to trap_entry
|
||||
#ifdef VECT_IRQ_ENABLED
|
||||
csrsi mtvec, 1 // set vectored mode
|
||||
#else
|
||||
csrsi mtvec, 0 // set direct mode
|
||||
#endif
|
||||
|
||||
/// configuring timer interrupt ///
|
||||
_reset_mtimecmp; // reset timer
|
||||
_run_timer; // run timer
|
||||
csrs mstatus, MSTATUS_MIE // enable global interrupt
|
||||
li a0, MTIE
|
||||
csrs mie, a0 // enable timer interrupt
|
||||
li t2, 0 // reset timer counter = 0 (updated in isr)
|
||||
_read_mtime s1 // read timer value
|
||||
addi s1, s1, 256
|
||||
_write_mtimecmp_32 s1
|
||||
wfi
|
||||
|
||||
|
||||
/// configuring external interrupt ///
|
||||
csrw mie, zero // disable all interrupts
|
||||
li t0, IRQ_LINES_ADDR
|
||||
sh zero, (t0) // set all exterinal interrupt lines low
|
||||
#ifdef IPIC_ENABLED
|
||||
li t0, IPIC_IRQ_LINE9
|
||||
csrw IPIC_IDX, t0 // set IPIC to expect interupt on line 9...
|
||||
li t0, (IPIC_ICSR_IE | IPIC_ICSR_IM)
|
||||
csrw IPIC_ICSR, t0 // ....enable interrupt,set edge interrupt mode
|
||||
#endif
|
||||
li t0, MEIE
|
||||
csrs mie, t0 // enable external interrupt
|
||||
li t0, TRIG_EXT_IRQ_ADDR
|
||||
#ifdef IPIC_ENABLED
|
||||
li t1, (1 << IPIC_IRQ_LINE9)
|
||||
#else
|
||||
li t1, (1 << EXT_IRQ_LINE_COMMON)
|
||||
#endif
|
||||
sh t1, (t0) //send command to generate external interrupt on line 9 to testbench
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop //wait for external interrupt
|
||||
|
||||
|
||||
/// configuring software interrupt ///
|
||||
csrw mie, zero // disable all interrupts
|
||||
li t0, TRIG_SW_IRQ_ADDR
|
||||
li t1, 0x00000001
|
||||
sh t1, (t0) //send command to generate software interrupt
|
||||
li t0, MSIE
|
||||
csrs mie, t0 // enable software interrupt
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop //wait for software interrupt
|
||||
|
||||
li s1, 3
|
||||
li a0, 0
|
||||
beq t2, s1, 1f
|
||||
li a0, -1
|
||||
1:
|
||||
jmp_sc_exit
|
||||
|
||||
|
||||
#ifndef VECT_IRQ_ENABLED
|
||||
|
||||
direct_irq_handler:
|
||||
csrr a1, mcause
|
||||
li a5, MCAUSE_TMR_IRQ //0x80000007 -- mcause = tmr.irq
|
||||
beq a1, a5, vec_machine_tmr_handler
|
||||
li a5, MCAUSE_SOFT_IRQ //0x80000003 -- mcause = soft.irq
|
||||
beq a1, a5, vec_machine_soft_handler
|
||||
li a5, MCAUSE_EXT_IRQ //0x8000000B -- mcause = ext.irq
|
||||
beq a1, a5, vec_machine_ext_handler
|
||||
mret
|
||||
#endif
|
||||
|
||||
vec_machine_tmr_handler:
|
||||
csrr a1, mcause
|
||||
li a5, MCAUSE_TMR_IRQ //0x80000007 -- mcause = tmr.irq
|
||||
li a0, -1
|
||||
bne a1, a5, check_fail
|
||||
csrr t1, mip
|
||||
li t0, MIP_MTIP
|
||||
and t0, t1, t0
|
||||
beqz t0, check_fail
|
||||
#ifdef IPIC_ENABLED
|
||||
csrw IPIC_SOI, zero
|
||||
csrw IPIC_EOI, zero
|
||||
#endif
|
||||
_reset_mtimecmp
|
||||
csrr t1, mip
|
||||
andi t1, t1, MIP_MTIP
|
||||
bne t1, zero, check_fail
|
||||
addi t2, t2, 1 // tmr irq counter update
|
||||
mret
|
||||
|
||||
vec_machine_ext_handler:
|
||||
|
||||
csrr a1, mcause
|
||||
li a5, MCAUSE_EXT_IRQ //0x8000000B -- mcause = ext.irq
|
||||
li a0, -1
|
||||
bne a1, a5, check_fail
|
||||
csrr t1, mip
|
||||
li t0, MIP_MEIP
|
||||
and t0, t1, t0
|
||||
beqz t0, check_fail
|
||||
#ifdef IPIC_ENABLED
|
||||
csrw IPIC_SOI, zero
|
||||
csrw IPIC_EOI, zero
|
||||
#endif
|
||||
li t0, MEIE
|
||||
csrc mie, t0 // disable software interrupt
|
||||
|
||||
li t0, TRIG_EXT_IRQ_ADDR
|
||||
li t1, EXT_IRQ_LINE_COMMON
|
||||
sh t1, (t0) // send command to disable external interrupt
|
||||
|
||||
csrr t1, mip
|
||||
li t0, MIP_MEIP
|
||||
bne t1, zero, check_fail
|
||||
addi t2, t2, 1 // ext irq counter update
|
||||
mret
|
||||
|
||||
vec_machine_soft_handler:
|
||||
csrr a1, mcause
|
||||
li a5, MCAUSE_SOFT_IRQ //0x80000003 -- mcause = soft.irq
|
||||
li a0, -1
|
||||
bne a1, a5, check_fail
|
||||
csrr t1, mip
|
||||
li t0, MIP_MSIP
|
||||
and t0, t1, t0
|
||||
beqz t0, check_fail
|
||||
#ifdef IPIC_ENABLED
|
||||
csrw IPIC_SOI, zero
|
||||
csrw IPIC_EOI, zero
|
||||
#endif
|
||||
li t0, MSIE
|
||||
csrc mie, t0 // disable software interrupt
|
||||
li t0, TRIG_SW_IRQ_ADDR
|
||||
li t1, 0x00000000
|
||||
sh t1, (t0) // send command to stop generating software interrupt
|
||||
li t0, MIP_MSIP
|
||||
csrc mip, t0
|
||||
csrr t1, mip
|
||||
li t0, MIP_MSIP
|
||||
and t1, t1, t0
|
||||
bne t1, zero, check_fail
|
||||
addi t2, t2, 1 // ext irq counter update
|
||||
mret
|
||||
|
||||
check_fail:
|
||||
la t0, sc_exit
|
||||
jr t0
|
||||
|
||||
_trap_fail:
|
||||
li a0, -1
|
||||
j check_fail
|
||||
180
sim/tests/isr_sample/timer.h
Normal file
180
sim/tests/isr_sample/timer.h
Normal file
@@ -0,0 +1,180 @@
|
||||
#ifndef __TIMER__H
|
||||
#define __TIMER__H
|
||||
|
||||
#define MEM_MTIME_MASK 0xF0000000
|
||||
#define MEM_MTIME_CTRL 0x00490000
|
||||
#define MEM_MTIME_DIV 0x00490004
|
||||
#define MEM_MTIME 0x00490008
|
||||
#define MEM_MTIMEH 0x0049000C
|
||||
#define MEM_MTIMECMP 0x00490010
|
||||
#define MEM_MTIMECMPH 0x00490014
|
||||
|
||||
#define TMP t0
|
||||
#define TMP2 t1
|
||||
#define TMP3 t2
|
||||
|
||||
#if defined(__ASSEMBLER__)
|
||||
|
||||
// Reset
|
||||
.macro _reset_mtime
|
||||
li TMP, MEM_MTIME
|
||||
sw zero, 0(TMP)
|
||||
sw zero, 4(TMP)
|
||||
.endm
|
||||
|
||||
.macro _reset_mtimecmp
|
||||
li TMP, MEM_MTIMECMP
|
||||
not TMP2, zero
|
||||
sw TMP2, 0(TMP)
|
||||
sw TMP2, 4(TMP)
|
||||
.endm
|
||||
|
||||
// Write
|
||||
.macro _write_mtime_ctrl reg
|
||||
li TMP, MEM_MTIME_CTRL
|
||||
sw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _write_mtime_div reg
|
||||
li TMP, MEM_MTIME_DIV
|
||||
sw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _write_mtimecmp_32 reg
|
||||
li TMP, MEM_MTIMECMP
|
||||
li TMP2, -1
|
||||
sw TMP2, 0(TMP)
|
||||
sw zero, 4(TMP)
|
||||
sw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _write_mtime reg
|
||||
li TMP, MEM_MTIME
|
||||
sw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _read_mtime reg
|
||||
li TMP, MEM_MTIME
|
||||
lw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
// Read
|
||||
.macro _read_mtimecmp reg
|
||||
li TMP, MEM_MTIMECMP
|
||||
lw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _read_mtime_ctrl reg
|
||||
li TMP, MEM_MTIME_CTRL
|
||||
lw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _read_mtime_div reg
|
||||
li TMP, MEM_MTIME_DIV
|
||||
lw \reg, 0(TMP)
|
||||
.endm
|
||||
|
||||
// Misc
|
||||
.macro _run_timer
|
||||
li TMP, MEM_MTIME_CTRL
|
||||
lw TMP2, 0(TMP)
|
||||
li TMP3, (1 << SCR1_MTIME_CTRL_EN)
|
||||
or TMP2, TMP2, TMP3
|
||||
sw TMP2, 0(TMP)
|
||||
.endm
|
||||
|
||||
.macro _stop_timer
|
||||
li TMP, MEM_MTIME_CTRL
|
||||
lw TMP2, 0(TMP)
|
||||
li TMP3, (1 << SCR1_MTIME_CTRL_EN)
|
||||
not TMP3, TMP3
|
||||
and TMP2, TMP2, TMP3
|
||||
sw TMP2, 0(TMP)
|
||||
.endm
|
||||
|
||||
#else /// #if defined(__ASSEMBLER__)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "scr1_specific.h"
|
||||
|
||||
static inline void reset_mtime(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime = (volatile uint32_t *)MEM_MTIME;
|
||||
mem_mtime[0] = 0;
|
||||
mem_mtime[1] = 0;
|
||||
}
|
||||
|
||||
static inline void reset_mtimecmp(void)
|
||||
{
|
||||
volatile uint32_t *reset_mtimecmp = (volatile uint32_t *)MEM_MTIMECMP;
|
||||
reset_mtimecmp[0] = -1;
|
||||
reset_mtimecmp[1] = -1;
|
||||
}
|
||||
|
||||
static inline void write_mtime_ctrl(uint32_t val)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_ctrl = (volatile uint32_t *)MEM_MTIME_CTRL;
|
||||
*mem_mtime_ctrl = val;
|
||||
}
|
||||
|
||||
static inline void write_mtime_div(uint32_t val)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_div = (volatile uint32_t *)MEM_MTIME_DIV;
|
||||
*mem_mtime_div = val;
|
||||
}
|
||||
|
||||
|
||||
static inline void write_mtimecmp_32(uint32_t val)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_cmp = (volatile uint32_t *)MEM_MTIMECMP;
|
||||
mem_mtime_cmp[0] = -1;
|
||||
mem_mtime_cmp[1] = 0;
|
||||
mem_mtime_cmp[0] = val;
|
||||
}
|
||||
|
||||
static inline void write_mtime(uint32_t val)
|
||||
{
|
||||
volatile uint32_t *mem_mtime = (volatile uint32_t *)MEM_MTIME;
|
||||
*mem_mtime = val;
|
||||
}
|
||||
|
||||
static inline uint32_t read_mtime(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime = (volatile uint32_t *)MEM_MTIME;
|
||||
return *mem_mtime;
|
||||
}
|
||||
|
||||
static inline uint32_t read_mtimecmp(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_cmp = (volatile uint32_t *)MEM_MTIMECMP;
|
||||
return *mem_mtime_cmp;
|
||||
}
|
||||
|
||||
static inline uint32_t read_mtime_ctrl(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_ctrl = (volatile uint32_t *)MEM_MTIME_CTRL;
|
||||
return *mem_mtime_ctrl;
|
||||
}
|
||||
|
||||
static inline uint32_t read_mtime_div(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_div = (volatile uint32_t *)MEM_MTIME_DIV;
|
||||
return *mem_mtime_div;
|
||||
}
|
||||
|
||||
static inline void run_timer(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_ctrl = (volatile uint32_t *)MEM_MTIME_CTRL;
|
||||
*mem_mtime_ctrl |= 1 << SCR1_MTIME_CTRL_EN;
|
||||
}
|
||||
|
||||
|
||||
static inline void stop_timer(void)
|
||||
{
|
||||
volatile uint32_t *mem_mtime_ctrl = (volatile uint32_t *)MEM_MTIME_CTRL;
|
||||
*mem_mtime_ctrl &= ~(1 << SCR1_MTIME_CTRL_EN);
|
||||
}
|
||||
|
||||
#endif /// #else #if defined(__ASSEMBLER__)
|
||||
|
||||
#endif // #ifndef __TIMER__H
|
||||
260
sim/tests/riscv_arch/Makefile
Normal file
260
sim/tests/riscv_arch/Makefile
Normal file
@@ -0,0 +1,260 @@
|
||||
## @file
|
||||
## Syntacore SCR* tests
|
||||
##
|
||||
## @copyright 2015-2018 Syntacore. All rights reserved.
|
||||
## RISCV-Compliance
|
||||
##
|
||||
|
||||
XLEN ?= 32
|
||||
ABI ?= ilp32
|
||||
ARCH ?=im
|
||||
override ARCH :=rv$(XLEN)$(ARCH)
|
||||
|
||||
$(info >>> ARCH := $(ARCH))
|
||||
|
||||
src_dir := $(CURDIR)
|
||||
RISCV_ARCH_TESTS := $(src_dir)/../../../dependencies/riscv-arch/
|
||||
|
||||
#I IM IMC IC
|
||||
#EM EMC EC
|
||||
|
||||
ifeq (e,$(findstring e, $(ARCH)))
|
||||
ifeq (e,$(findstring e,$(ARCH)))
|
||||
$(info >>> E32 TESTS)
|
||||
included_e += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/E/src/*))
|
||||
arch_set += $(included_e)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/E/*/*.reference_output)
|
||||
endif
|
||||
ifeq (c,$(findstring c,$(ARCH)))
|
||||
$(info >>> EC32 TESTS)
|
||||
included_ec += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/C/src/*))
|
||||
arch_set += $(included_ec)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/C/*/*.reference_output)
|
||||
endif
|
||||
ifeq (m,$(findstring m,$(ARCH)))
|
||||
$(info >>> EM32 TESTS)
|
||||
included_em += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/M/src/*))
|
||||
arch_set += $(included_em)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32e_unratified/M/*/*.reference_output)
|
||||
endif
|
||||
else ## ifdef SCR_BASE_RVE_EXT
|
||||
ifeq (i,$(findstring i, $(ARCH)))
|
||||
ifeq (i,$(findstring i,$(ARCH)))
|
||||
$(info >>> I32 TESTS)
|
||||
included_i += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/I/src/*))
|
||||
included_ip += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/privilege/src/*))
|
||||
included_i += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/Zifencei/src/*))
|
||||
included_i += $(included_ip)
|
||||
arch_set += $(included_i)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/I/*/*.reference_output)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/privilege/*/*.reference_output)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/Zifencei/*/*.reference_output)
|
||||
endif
|
||||
ifeq (c,$(findstring c,$(ARCH)))
|
||||
$(info >>> IC32 TESTS)
|
||||
included_ic += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/C/src/*))
|
||||
arch_set += $(included_ic)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/C/*/*.reference_output)
|
||||
endif
|
||||
ifeq (m,$(findstring m,$(ARCH)))
|
||||
$(info >>> IM32 TESTS)
|
||||
included_im += $(filter %.S,\
|
||||
$(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/M/src/*))
|
||||
arch_set += $(included_im)
|
||||
reference_src += $(wildcard $(RISCV_ARCH_TESTS)/riscv-test-suite/rv32i_m/M/*/*.reference_output)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
$(info >>>$(ARCH) set included)
|
||||
|
||||
ifeq ($(arch_set),)
|
||||
$(info >>> No arch tests included)
|
||||
endif
|
||||
|
||||
$(info >>>>> arch set: $(arch_set))
|
||||
|
||||
dst_dir := $(bld_dir)
|
||||
test_name := riscv_arch
|
||||
bld_dir := $(addprefix $(dst_dir)/, $(test_name))
|
||||
obj_dir := $(bld_dir)/riscv_arch_objs
|
||||
|
||||
ifeq ($(ARCH),$(filter $(ARCH),rv32im))
|
||||
cut_list += misalign-blt-01 misalign-jal-01 misalign-beq-01 misalign2-jalr-01 misalign-bgeu-01 misalign-bltu-01 misalign-bge-01 misalign-bne-01 # privilege test used mtvec
|
||||
endif
|
||||
ifeq ($(ARCH),$(filter $(ARCH),rv32ic))
|
||||
cut_list += misalign-lw-01 misalign-sh-01 misalign-lhu-01 misalign-lh-01 ecall misalign-sw-01 # privilege test used mtvec
|
||||
endif
|
||||
|
||||
cut_list += bne-01 blt-01 beq-01 bge-01 jal-01 bltu-01 bgeu-01 # i - base
|
||||
cut_list += ebreak cebreak-01 cswsp-01 # C - base
|
||||
testnames := $(basename $(notdir $(arch_set)))
|
||||
filtered := $(filter-out $(cut_list),$(testnames))
|
||||
objs := $(addprefix $(bld_dir)/,$(filtered:%=%.o))
|
||||
test_elf := $(addprefix $(dst_dir)/arch_,$(filtered:%=%.elf))
|
||||
test_hex := $(addprefix $(dst_dir)/arch_,$(filtered:%=%.hex))
|
||||
test_dump := $(addprefix $(bld_dir)/arch_,$(filtered:%=%.dump))
|
||||
|
||||
arch_macros_file := $(root_dir)/sim/tests/riscv_arch/model_test.h
|
||||
arch_output ?= true
|
||||
|
||||
ifeq (e,$(findstring e,$(ARCH)))
|
||||
EXT_CFLAGS += -DRVTEST_E
|
||||
endif
|
||||
|
||||
# Set name file for RV32I
|
||||
testnames_i := $(basename $(notdir $(included_i)))
|
||||
testnames_im := $(basename $(notdir $(included_im)))
|
||||
testnames_ic := $(basename $(notdir $(included_ic)))
|
||||
testnames_ib := $(basename $(notdir $(included_ib)))
|
||||
filtered_i := $(filter-out $(cut_list),$(testnames_i))
|
||||
filtered_im := $(filter-out $(cut_list),$(testnames_im))
|
||||
filtered_ic := $(filter-out $(cut_list),$(testnames_ic))
|
||||
filtered_ib := $(filter-out $(cut_list),$(testnames_ib))
|
||||
|
||||
# Set name file for RVE
|
||||
testnames_e := $(basename $(notdir $(included_e)))
|
||||
testnames_em := $(basename $(notdir $(included_em)))
|
||||
testnames_ec := $(basename $(notdir $(included_ec)))
|
||||
filtered_e := $(filter-out $(cut_list),$(testnames_e))
|
||||
filtered_em := $(filter-out $(cut_list),$(testnames_em))
|
||||
filtered_ec := $(filter-out $(cut_list),$(testnames_ec))
|
||||
|
||||
CFLAGS := -I$(inc_dir) -I$(src_dir) -DASM -mabi=$(ABI) $(EXT_CFLAGS) -DXLEN=$(XLEN) -D__riscv_xlen=$(XLEN) -w
|
||||
LDFLAGS := -static -fvisibility=hidden -nostdlib -nostartfiles -T$(inc_dir)/link.ld -march=$(ARCH) -mabi=$(ABI)
|
||||
GCCVERSIONGT7 := $(shell expr `$(RISCV_GCC) -dumpfullversion | cut -f1 -d'.'` \> 7)
|
||||
ifeq "$(GCCVERSIONGT7)" "1"
|
||||
LDFLAGS += -mno-relax
|
||||
endif
|
||||
VPATH += $(src_dir) $(bld_dir) $(obj_dir) $(asm_path) $(ref_path) $(RISCV_ARCH_TESTS)
|
||||
|
||||
ifeq ($(arch_output), true)
|
||||
CFLAGS += -D_ARCH_OUTPUT
|
||||
endif
|
||||
|
||||
default: clean log_requested_tgt check_version cp_asm ref_data $(test_elf) $(test_hex) $(test_dump)
|
||||
|
||||
define compile_template
|
||||
$(obj_dir)/$(1).o: $(obj_dir) cp_asm
|
||||
$(RISCV_GCC) -c $$(bld_dir)/arch_asm/$(1).S $$(CFLAGS) -Wa,$(2) $(2) -o $$@
|
||||
endef
|
||||
|
||||
define preprocessing
|
||||
for test_asm in $(1); do \
|
||||
march_tmp=$$test_asm ; \
|
||||
march_tmp=$${march_tmp%/src*} ; \
|
||||
march_tmp=$$(basename $$march_tmp) ; \
|
||||
file_name="$$(basename $${test_asm})" ; \
|
||||
$(RISCV_GCC) $(CFLAGS) -Wa,$(2) $(2) -E $$test_asm \
|
||||
-o $(bld_dir)/arch_asm/$$file_name ; \
|
||||
done
|
||||
endef
|
||||
|
||||
define preprocessing_privilege
|
||||
for test_asm in $(1); do \
|
||||
march_tmp=$$test_asm ; \
|
||||
march_tmp=$${march_tmp%/src*} ; \
|
||||
march_tmp=$$(basename $$march_tmp) ; \
|
||||
file_name="$$(basename $${test_asm})" ; \
|
||||
$(RISCV_GCC) $(CFLAGS) -Drvtest_mtrap_routine=True -Dmhandler -Wa,$(2) $(2) -E $$test_asm \
|
||||
-o $(bld_dir)/arch_asm/$$file_name ; \
|
||||
done
|
||||
endef
|
||||
|
||||
$(foreach SRC,$(filtered_i),$(eval $(call compile_template,$(SRC),-march=rv32i_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_im),$(eval $(call compile_template,$(SRC),-march=rv32im_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_ic),$(eval $(call compile_template,$(SRC),-march=rv32ic_zicsr_zifencei)))
|
||||
|
||||
$(foreach SRC,$(filtered_e),$(eval $(call compile_template,$(SRC),-march=rv32e_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_em),$(eval $(call compile_template,$(SRC),-march=rv32em_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_ec),$(eval $(call compile_template,$(SRC),-march=rv32ec_zicsr_zifencei)))
|
||||
|
||||
log_requested_tgt: $(bld_dir)
|
||||
$(foreach test_name, $(filtered), $(eval $(shell echo arch_$(test_name).hex >> $(bld_dir)/../test_info)))
|
||||
|
||||
$(bld_dir) :
|
||||
mkdir -p $(bld_dir)
|
||||
|
||||
$(obj_dir) : | ref_data
|
||||
mkdir -p $(obj_dir)
|
||||
|
||||
$(dst_dir)/arch_%.elf: $(obj_dir)/%.o | $(dep_files)
|
||||
$(RISCV_GCC) $^ $(LDFLAGS) -o $@ -g
|
||||
|
||||
$(dst_dir)/arch_%.hex: $(dst_dir)/arch_%.elf
|
||||
$(RISCV_OBJCOPY) $^ $@
|
||||
|
||||
$(bld_dir)/arch_%.dump: $(dst_dir)/arch_%.elf
|
||||
$(RISCV_OBJDUMP) -D -w -x -S $^ > $@
|
||||
|
||||
ref_data:
|
||||
mkdir -p $(bld_dir)/ref_data
|
||||
for files in $(reference_src) ; do \
|
||||
sed_input=$$files ; \
|
||||
sed_output=$$(basename $${files%.*}) ; \
|
||||
sed "s/\r$$//; \
|
||||
s/\(........\)/\1,/g; \
|
||||
s/.$$//; s/\(.*\),\(.*\),\(.*\),\(.*\)/\4,\3,\2,\1/;" \
|
||||
$$sed_input > $(bld_dir)/ref_data/$$sed_output; \
|
||||
done
|
||||
|
||||
cp_asm:
|
||||
mkdir -p $(bld_dir)/arch_asm
|
||||
$(call preprocessing,$(included_i),-march=rv32i)
|
||||
$(call preprocessing_privilege,$(included_ip),-march=rv32i)
|
||||
$(call preprocessing,$(included_im),-march=rv32im)
|
||||
$(call preprocessing,$(included_ic),-march=rv32ic)
|
||||
$(call preprocessing,$(included_e),-march=rv32e)
|
||||
$(call preprocessing,$(included_em),-march=rv32em)
|
||||
$(call preprocessing,$(included_ec),-march=rv32ec)
|
||||
|
||||
riscv_arch_tests_dir := $(if $(RISCV_ARCH_TESTS), $(RISCV_ARCH_TESTS), ./undefined)
|
||||
riscv_tests_commit := 9141cf9274b610d059199e8aa2e21f54a0bc6a6e
|
||||
## commit hash readed from local copy of https://github.com/riscv/riscv-arch-test.git
|
||||
tmp_commit = $(shell cd $(riscv_arch_tests_dir) 2>/dev/null && git log -1 | grep "commit" | cut -f2 -d ' ')
|
||||
is_commit_good = $(if $(subst $(riscv_tests_commit),,$(tmp_commit)),false,true)
|
||||
|
||||
# Color
|
||||
RED=\033[0;31m
|
||||
NC=\033[0m
|
||||
|
||||
check_version : $(riscv_arch_tests_dir)
|
||||
@if [ ! -d $(riscv_arch_tests_dir) ]; then \
|
||||
echo -e "$(RED)==========================================================================" &&\
|
||||
echo " Error! Environment variable RISCV_ARCH_TESTS='$(riscv_arch_tests_dir)' " &&\
|
||||
echo " directory not exist!" && \
|
||||
echo "==========================================================================$(NC)" ; \
|
||||
fi
|
||||
ifneq ($(is_commit_good),true)
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Warning! Execution of test code is not guaranteed "
|
||||
@echo " while using the current commit of repository located at : $(riscv_arch_tests_dir) ."
|
||||
@echo " "
|
||||
@echo " riscv_arch repository must point to commit $(riscv_tests_commit)!"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
endif
|
||||
|
||||
$(riscv_arch_tests_dir) :.
|
||||
ifndef RISCV_ARCH_TESTS
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Error! Environment variable RISCV_ARCH_TESTS not set!"
|
||||
@echo " You must set the environment variable RISCV_ARCH_TESTS"
|
||||
@echo " The variable should point to the local copy of the"
|
||||
@echo " repository https://github.com/riscv/riscv-arch-test.git"
|
||||
@echo " with the commit $(riscv_tests_commit)"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) -R $(test_elf) $(test_hex) $(bld_dir)
|
||||
|
||||
.PHONY: check_version clean ref_data cp_asm default
|
||||
1041
sim/tests/riscv_arch/arch_test.h
Normal file
1041
sim/tests/riscv_arch/arch_test.h
Normal file
File diff suppressed because it is too large
Load Diff
1495
sim/tests/riscv_arch/encoding.h
Normal file
1495
sim/tests/riscv_arch/encoding.h
Normal file
File diff suppressed because it is too large
Load Diff
103
sim/tests/riscv_arch/model_test.h
Normal file
103
sim/tests/riscv_arch/model_test.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// RISC-V Compliance Test Header File
|
||||
// Copyright (c) 2017, Codasip Ltd. All Rights Reserved.
|
||||
// See LICENSE for license details.
|
||||
//
|
||||
// Description: Common header file for RV32I tests
|
||||
|
||||
#ifndef _COMPLIANCE_TEST_H
|
||||
#define _COMPLIANCE_TEST_H
|
||||
|
||||
#include "riscv_test.h"
|
||||
#include "encoding.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// RV Compliance Macros
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RV_COMPLIANCE_HALT \
|
||||
|
||||
#define RV_COMPLIANCE_RV32M \
|
||||
RVTEST_RV32M \
|
||||
|
||||
#define RV_COMPLIANCE_CODE_BEGIN \
|
||||
RVTEST_CODE_BEGIN_OLD \
|
||||
|
||||
#define RV_COMPLIANCE_CODE_END \
|
||||
RVTEST_CODE_END_OLD \
|
||||
|
||||
#define RV_COMPLIANCE_DATA_BEGIN \
|
||||
RVTEST_DATA_BEGIN_OLD \
|
||||
|
||||
#define RV_COMPLIANCE_DATA_END \
|
||||
RVTEST_DATA_END_OLD \
|
||||
|
||||
#endif// RISC-V Compliance IO Test Header File
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _COMPLIANCE_IO_H
|
||||
#define _COMPLIANCE_IO_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// RV IO Macros (Non functional)
|
||||
//-----------------------------------------------------------------------
|
||||
#ifdef _ARCH_OUTPUT
|
||||
|
||||
#define RVTEST_IO_PUSH(_SP) \
|
||||
la _SP, begin_regstate; \
|
||||
sw x3, 0(_SP); \
|
||||
sw x4, 4(_SP); \
|
||||
sw x5, 8(_SP);
|
||||
|
||||
#define RVTEST_IO_POP(_SP) \
|
||||
la _SP, begin_regstate; \
|
||||
lw x3, 0(_SP); \
|
||||
lw x4, 4(_SP); \
|
||||
lw x5, 8(_SP);
|
||||
|
||||
#define RVTEST_IO_WRITE_STR(_SP, _STR) \
|
||||
.section .data.string; \
|
||||
20001: \
|
||||
.string _STR; \
|
||||
.section .text.init; \
|
||||
RVTEST_IO_PUSH(_SP) \
|
||||
li x3, 0xF0000000; \
|
||||
la x4, 20001b; \
|
||||
2: lb x5, 0(x4); \
|
||||
sb x5, 0(x3); \
|
||||
beq x5, zero, 1f; \
|
||||
add x4, x4, 1; \
|
||||
j 2b; \
|
||||
1: RVTEST_IO_POP(_SP)
|
||||
|
||||
#else // #ifdef _ARCH_OUTPUT
|
||||
|
||||
#define RVTEST_IO_WRITE_STR(_SP, _STR)
|
||||
|
||||
#endif // #end #ifdef _ARCH_OUTPUT
|
||||
|
||||
#define RVTEST_IO_INIT
|
||||
#define RVTEST_IO_CHECK()
|
||||
#define RVTEST_IO_ASSERT_GPR_EQ(_SP, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_SFPR_EQ(_F, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_DFPR_EQ(_D, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_EQ(_R, _I)
|
||||
|
||||
#endif // _COMPLIANCE_IO_H
|
||||
253
sim/tests/riscv_arch/riscv_test.h
Normal file
253
sim/tests/riscv_arch/riscv_test.h
Normal file
@@ -0,0 +1,253 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef _ENV_PHYSICAL_SINGLE_CORE_H
|
||||
#define _ENV_PHYSICAL_SINGLE_CORE_H
|
||||
|
||||
#include "encoding.h"
|
||||
#include "sc_test.h"
|
||||
.noaltmacro
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Begin Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_RV64U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
|
||||
#else
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
|
||||
#endif
|
||||
|
||||
#define INIT_PMP \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
li t0, -1; /* Set up a PMP to permit all accesses */ \
|
||||
csrw pmpaddr0, t0; \
|
||||
li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X; \
|
||||
csrw pmpcfg0, t0; \
|
||||
.align 2; \
|
||||
1:
|
||||
|
||||
#define INIT_SATP \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
csrwi satp, 0; \
|
||||
.align 2; \
|
||||
1:
|
||||
|
||||
#define DELEGATE_NO_TRAPS \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
csrwi medeleg, 0; \
|
||||
csrwi mideleg, 0; \
|
||||
csrwi mie, 0; \
|
||||
.align 2; \
|
||||
1:
|
||||
|
||||
#define RVTEST_ENABLE_SUPERVISOR \
|
||||
li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
li a0, SIP_SSIP | SIP_STIP; \
|
||||
csrs mideleg, a0; \
|
||||
|
||||
#define RVTEST_ENABLE_MACHINE \
|
||||
li a0, MSTATUS_MPP; \
|
||||
csrs mstatus, a0; \
|
||||
|
||||
#define RVTEST_FP_ENABLE \
|
||||
li a0, MSTATUS_FS & (MSTATUS_FS >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
csrwi fcsr, 0
|
||||
|
||||
#define RISCV_MULTICORE_DISABLE \
|
||||
csrr a0, mhartid; \
|
||||
1: bnez a0, 1b
|
||||
|
||||
#define EXTRA_TVEC_USER
|
||||
#define EXTRA_TVEC_MACHINE
|
||||
#define EXTRA_INIT
|
||||
#define EXTRA_INIT_TIMER
|
||||
|
||||
#define PRIV_MISA_S 0
|
||||
//
|
||||
// undefine some unusable CSR Accesses if no PRIV Mode present
|
||||
//
|
||||
#if defined(PRIV_MISA_S)
|
||||
# if (PRIV_MISA_S==0)
|
||||
# undef INIT_SATP
|
||||
# define INIT_SATP
|
||||
# undef INIT_PMP
|
||||
# define INIT_PMP
|
||||
# undef DELEGATE_NO_TRAPS
|
||||
# define DELEGATE_NO_TRAPS
|
||||
# undef RVTEST_ENABLE_SUPERVISOR
|
||||
# define RVTEST_ENABLE_SUPERVISOR
|
||||
# endif
|
||||
#endif
|
||||
#if defined(PRIV_MISA_U)
|
||||
# if (PRIV_MISA_U==0)
|
||||
# endif
|
||||
#endif
|
||||
#if defined(TRAPHANDLER)
|
||||
#include TRAPHANDLER
|
||||
#endif
|
||||
|
||||
#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */
|
||||
|
||||
#define RVTEST_CODE_BEGIN_OLD \
|
||||
.section .text.init; \
|
||||
.balign 512; \
|
||||
.weak stvec_handler; \
|
||||
.weak mtvec_handler; \
|
||||
.globl _start; \
|
||||
_start: \
|
||||
/* reset vector */ \
|
||||
j reset_vector; \
|
||||
.balign 64; \
|
||||
trap_vector: \
|
||||
/* test whether the test came from pass/fail */ \
|
||||
csrr a4, mcause; \
|
||||
li a5, CAUSE_USER_ECALL; \
|
||||
beq a4, a5, write_tohost; \
|
||||
li a5, CAUSE_SUPERVISOR_ECALL; \
|
||||
beq a4, a5, write_tohost; \
|
||||
li a5, CAUSE_MACHINE_ECALL; \
|
||||
beq a4, a5, write_tohost; \
|
||||
/* if an mtvec_handler is defined, jump to it */ \
|
||||
la a4, mtvec_handler; \
|
||||
beqz a4, 1f; \
|
||||
jr a4; \
|
||||
/* was it an interrupt or an exception? */ \
|
||||
1: csrr a4, mcause; \
|
||||
bgez a4, handle_exception; \
|
||||
INTERRUPT_HANDLER; \
|
||||
handle_exception: \
|
||||
/* we don't know how to handle whatever the exception was */ \
|
||||
other_exception: \
|
||||
/* some unhandlable exception occurred */ \
|
||||
1: ori TESTNUM, TESTNUM, 1337; \
|
||||
write_tohost: \
|
||||
tail sc_exit; \
|
||||
reset_vector: \
|
||||
RISCV_MULTICORE_DISABLE; \
|
||||
INIT_SATP; \
|
||||
INIT_PMP; \
|
||||
DELEGATE_NO_TRAPS; \
|
||||
li TESTNUM, 0; \
|
||||
la t0, trap_vector; \
|
||||
csrw mtvec, t0; \
|
||||
CHECK_XLEN; \
|
||||
/* if an stvec_handler is defined, delegate exceptions to it */ \
|
||||
la t0, stvec_handler; \
|
||||
beqz t0, 1f; \
|
||||
csrw stvec, t0; \
|
||||
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; \
|
||||
1: csrwi mstatus, 0; \
|
||||
init; \
|
||||
EXTRA_INIT; \
|
||||
EXTRA_INIT_TIMER; \
|
||||
la t0, 1f; \
|
||||
csrw mepc, t0; \
|
||||
csrr a0, mhartid; \
|
||||
mret; \
|
||||
1: \
|
||||
begin_testcode:
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// End Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_CODE_END_OLD \
|
||||
end_testcode: \
|
||||
ecall;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Pass/Fail Macro
|
||||
//-----------------------------------------------------------------------
|
||||
#define RVTEST_SYNC fence
|
||||
//#define RVTEST_SYNC nop
|
||||
|
||||
#define RVTEST_PASS \
|
||||
RVTEST_SYNC; \
|
||||
li TESTNUM, 1; \
|
||||
SWSIG (0, TESTNUM); \
|
||||
ecall
|
||||
|
||||
#define TESTNUM gp
|
||||
#define RVTEST_FAIL \
|
||||
RVTEST_SYNC; \
|
||||
1: beqz TESTNUM, 1b; \
|
||||
sll TESTNUM, TESTNUM, 1; \
|
||||
or TESTNUM, TESTNUM, 1; \
|
||||
SWSIG (0, TESTNUM); \
|
||||
la x1, end_testcode; \
|
||||
jr x1;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Data Section Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define EXTRA_DATA
|
||||
|
||||
#define RVTEST_DATA_BEGIN_OLD \
|
||||
.align 4; .global begin_signature; begin_signature:
|
||||
|
||||
#define RVTEST_DATA_END_OLD \
|
||||
.balign 4; .global end_signature; end_signature: \
|
||||
EXTRA_DATA \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.align 8; .global tohost; tohost: .dword 0; \
|
||||
.align 8; .global fromhost; fromhost: .dword 0; \
|
||||
.popsection; \
|
||||
.align 8; .global begin_regstate; begin_regstate: \
|
||||
.word 128; \
|
||||
.align 8; .global end_regstate; end_regstate: \
|
||||
.word 4;
|
||||
|
||||
#endif
|
||||
199
sim/tests/riscv_compliance/Makefile
Normal file
199
sim/tests/riscv_compliance/Makefile
Normal file
@@ -0,0 +1,199 @@
|
||||
## @file
|
||||
## Syntacore SCR* tests
|
||||
##
|
||||
## @copyright 2015-2018 Syntacore. All rights reserved.
|
||||
## RISCV-Compliance
|
||||
##
|
||||
|
||||
ARCH ?=im
|
||||
override ARCH:=rv32$(ARCH)
|
||||
|
||||
src_dir := $(CURDIR)
|
||||
RISCV_COMPLIANCE_TESTS := $(src_dir)/../../../dependencies/riscv-compliance/
|
||||
|
||||
#I IM IMC IC
|
||||
#EM EMC EC
|
||||
|
||||
ifeq (rv32e,$(findstring rv32e,$(ARCH)))
|
||||
$(info >>> RV32E - no compliance tests)
|
||||
else ## ifdef SCR_BASE_RVE_EXT
|
||||
#ifeq (rv32i,$(findstring rv32i,$(ARCH)))
|
||||
ifeq ($(ARCH),$(filter $(ARCH),rv32i rv32im rv32imc rv32ic))
|
||||
$(info >>> I32 TESTS)
|
||||
included_i += $(filter %.S,\
|
||||
$(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32i/src/*))
|
||||
included_i += $(filter %.S,\
|
||||
$(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32Zicsr/src/*))
|
||||
included_i += $(filter %.S,\
|
||||
$(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32Zifencei/src/*))
|
||||
compliance_set += $(included_i)
|
||||
endif
|
||||
|
||||
#$(if or ifeq(rv32im,$(findstring rv32im,$(ARCH))), (rv32imc,$(findstring rv32imc,$(ARCH))))
|
||||
ifeq ($(ARCH),$(filter $(ARCH), rv32im rv32imc))
|
||||
$(info >>> IM32 TESTS)
|
||||
included_im += $(filter %.S,\
|
||||
$(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32im/src/*))
|
||||
compliance_set += $(included_im)
|
||||
endif ##
|
||||
|
||||
ifeq (rv32imc,$(findstring rv32imc,$(ARCH)))
|
||||
$(info >>> IMC32 TESTS)
|
||||
included_imc += $(filter %.S,\
|
||||
$(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32imc/src/*))
|
||||
compliance_set += $(included_imc)
|
||||
endif ## ifeq (rv32imc,$(findstring rv32imc,$(ARCH)))
|
||||
ifeq (rv32ic,$(findstring rv32ic,$(ARCH)))
|
||||
endif
|
||||
endif ##
|
||||
|
||||
|
||||
$(info >>>$(ARCH) set included)
|
||||
|
||||
ifeq ($(compliance_set),)
|
||||
$(info >>> No compliance tests included)
|
||||
endif
|
||||
|
||||
$(info >>>>> compliance set: $(compliance_set))
|
||||
|
||||
dst_dir := $(bld_dir)
|
||||
test_name := riscv_compliance
|
||||
bld_dir := $(addprefix $(dst_dir)/, $(test_name))
|
||||
obj_dir := $(bld_dir)/riscv_compliance_objs
|
||||
|
||||
#cut_list += scall csr shamt simple
|
||||
cut_list += I-MISALIGN_JMP-01 I-MISALIGN_LDST-01 I-EBREAK-01 I-ECALL-01
|
||||
reference_src += $(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32i*/*/*.reference_output)
|
||||
reference_src += $(wildcard $(RISCV_COMPLIANCE_TESTS)/riscv-test-suite/rv32Zi*/*/*.reference_output)
|
||||
testnames := $(basename $(notdir $(compliance_set)))
|
||||
filtered := $(filter-out $(cut_list),$(testnames))
|
||||
objs := $(addprefix $(bld_dir)/,$(filtered:%=%.o))
|
||||
test_elf := $(addprefix $(dst_dir)/compliance_,$(filtered:%=%.elf))
|
||||
test_hex := $(addprefix $(dst_dir)/compliance_,$(filtered:%=%.hex))
|
||||
test_dump := $(addprefix $(bld_dir)/compliance_,$(filtered:%=%.dump))
|
||||
|
||||
compliance_macros_file := $(root_dir)/sim/tests/riscv_compliance/compliance_io.h
|
||||
compliance_output ?= true
|
||||
|
||||
testnames_i := $(basename $(notdir $(included_i)))
|
||||
testnames_im := $(basename $(notdir $(included_im)))
|
||||
testnames_imc := $(basename $(notdir $(included_imc)))
|
||||
filtered_i := $(filter-out $(cut_list),$(testnames_i))
|
||||
filtered_im := $(filter-out $(cut_list),$(testnames_im))
|
||||
filtered_imc := $(filter-out $(cut_list),$(testnames_imc))
|
||||
|
||||
# ARCH_FLAGS := -Wa,-march=rv32im -march=rv32im
|
||||
# ARCH_FLAGS_C := -Wa,-march=rv32imc -march=rv32imc
|
||||
CFLAGS := -I$(inc_dir) -I$(src_dir) -DASM -mabi=ilp32 -D__riscv_xlen=32 -w
|
||||
LDFLAGS := -static -fvisibility=hidden -nostdlib -nostartfiles -T$(inc_dir)/link.ld -march=$(ARCH)_zicsr_zifencei -mabi=ilp32
|
||||
GCCVERSIONGT7 := $(shell expr `$(RISCV_GCC) -dumpfullversion | cut -f1 -d'.'` \> 7)
|
||||
ifeq "$(GCCVERSIONGT7)" "1"
|
||||
LDFLAGS += -mno-relax
|
||||
endif
|
||||
VPATH += $(src_dir) $(bld_dir) $(obj_dir) $(asm_path) $(ref_path) $(RISCV_COMPLIANCE_TESTS)
|
||||
|
||||
ifeq ($(compliance_output), true)
|
||||
CFLAGS += -D_COMPLIANCE_OUTPUT
|
||||
endif
|
||||
|
||||
default: clean log_requested_tgt check_version cp_asm ref_data $(test_elf) $(test_hex) $(test_dump)
|
||||
|
||||
define compile_template
|
||||
$(obj_dir)/$(1).o: $(obj_dir) cp_asm
|
||||
$(RISCV_GCC) -c $$(bld_dir)/compliance_asm/$(1).S $$(CFLAGS) -Wa,$(2) $(2) -o $$@
|
||||
endef
|
||||
|
||||
define preprocessing
|
||||
for test_asm in $(1); do \
|
||||
march_tmp=$$test_asm ; \
|
||||
march_tmp=$${march_tmp%/src*} ; \
|
||||
march_tmp=$$(basename $$march_tmp) ; \
|
||||
file_name="$$(basename $${test_asm})" ; \
|
||||
$(RISCV_GCC) $(CFLAGS) -Wa,$(2) $(2) -E $$test_asm \
|
||||
-o $(bld_dir)/compliance_asm/$$file_name ; \
|
||||
done
|
||||
endef
|
||||
|
||||
$(foreach SRC,$(filtered_i),$(eval $(call compile_template,$(SRC),-march=rv32i_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_im),$(eval $(call compile_template,$(SRC),-march=rv32im_zicsr_zifencei)))
|
||||
$(foreach SRC,$(filtered_imc),$(eval $(call compile_template,$(SRC),-march=rv32imc_zicsr_zifencei)))
|
||||
|
||||
|
||||
log_requested_tgt: $(bld_dir)
|
||||
$(foreach test_name, $(filtered), $(eval $(shell echo compliance_$(test_name).hex >> $(bld_dir)/../test_info)))
|
||||
|
||||
$(bld_dir) :
|
||||
mkdir -p $(bld_dir)
|
||||
|
||||
$(obj_dir) : | ref_data
|
||||
mkdir -p $(obj_dir)
|
||||
|
||||
$(dst_dir)/compliance_%.elf: $(obj_dir)/%.o | $(dep_files)
|
||||
$(RISCV_GCC) $^ $(LDFLAGS) -o $@ -g
|
||||
|
||||
$(dst_dir)/compliance_%.hex: $(dst_dir)/compliance_%.elf
|
||||
$(RISCV_OBJCOPY) $^ $@
|
||||
|
||||
$(bld_dir)/compliance_%.dump: $(dst_dir)/compliance_%.elf
|
||||
$(RISCV_OBJDUMP) -D -w -x -S $^ > $@
|
||||
|
||||
ref_data:
|
||||
mkdir -p $(bld_dir)/ref_data
|
||||
for files in $(reference_src) ; do \
|
||||
sed_input=$$files ; \
|
||||
sed_output=$$(basename $${files%.*}) ; \
|
||||
sed "s/\r$$//; \
|
||||
s/\(........\)/\1,/g; \
|
||||
s/.$$//; s/\(.*\),\(.*\),\(.*\),\(.*\)/\4,\3,\2,\1/;" \
|
||||
$$sed_input > $(bld_dir)/ref_data/$$sed_output; \
|
||||
done
|
||||
|
||||
cp_asm:
|
||||
mkdir -p $(bld_dir)/compliance_asm
|
||||
$(call preprocessing,$(included_i),-march=rv32i_zicsr_zifencei)
|
||||
$(call preprocessing,$(included_im),-march=rv32im_zicsr_zifencei)
|
||||
$(call preprocessing,$(included_imc),-march=rv32imc_zicsr_zifencei)
|
||||
|
||||
|
||||
riscv_compliance_tests_dir := $(if $(RISCV_COMPLIANCE_TESTS), $(RISCV_COMPLIANCE_TESTS), ./undefined)
|
||||
riscv_tests_commit := d51259b2a949be3af02e776c39e135402675ac9b
|
||||
## commit hash readed from local copy of https://github.com/riscv/riscv-compliance
|
||||
tmp_commit = $(shell cd $(riscv_compliance_tests_dir) 2>/dev/null && git log -1 | grep "commit" | cut -f2 -d ' ')
|
||||
is_commit_good = $(if $(subst $(riscv_tests_commit),,$(tmp_commit)),false,true)
|
||||
|
||||
# Color
|
||||
RED=\033[0;31m
|
||||
NC=\033[0m
|
||||
|
||||
check_version : $(riscv_compliance_tests_dir)
|
||||
@if [ ! -d $(riscv_compliance_tests_dir) ]; then \
|
||||
echo -e "$(RED)==========================================================================" &&\
|
||||
echo " Error! Environment variable RISCV_COMPLIANCE_TESTS='$(riscv_compliance_tests_dir)' " &&\
|
||||
echo " directory not exist!" && \
|
||||
echo "==========================================================================$(NC)" ; \
|
||||
fi
|
||||
ifneq ($(is_commit_good),true)
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Warning! Execution of test code is not guaranteed "
|
||||
@echo " while using the current commit of repository located at : $(riscv_compliance_tests_dir) ."
|
||||
@echo " "
|
||||
@echo " riscv_compliance repository must point to commit $(riscv_tests_commit)!"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
endif
|
||||
|
||||
$(riscv_compliance_tests_dir) :.
|
||||
ifndef RISCV_COMPLIANCE_TESTS
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Error! Environment variable RISCV_COMPLIANCE_TESTS not set!"
|
||||
@echo " You must set the environment variable RISCV_COMPLIANCE_TESTS"
|
||||
@echo " The variable should point to the local copy of the"
|
||||
@echo " repository https://github.com/riscv/riscv-compliance"
|
||||
@echo " with the commit $(riscv_tests_commit)"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) -R $(test_elf) $(test_hex) $(bld_dir)
|
||||
|
||||
.PHONY: check_version clean ref_data cp_asm default
|
||||
683
sim/tests/riscv_compliance/aw_test_macros.h
Normal file
683
sim/tests/riscv_compliance/aw_test_macros.h
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
COPY OF /riscv-compliance/riscv-test-env/aw_test_macros.h
|
||||
*/
|
||||
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef __TEST_MACROS_SCALAR_H
|
||||
#define __TEST_MACROS_SCALAR_H
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Helper macros
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
|
||||
|
||||
#define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1: srli a0, a0, 31; la t0, begin_signature; sw a0, 0(t0)
|
||||
|
||||
#define TESTNUM gp
|
||||
|
||||
#define SWSIG( testnum, testreg ) \
|
||||
la x28, test_res; \
|
||||
sw testreg, (testnum<<2)(x28); \
|
||||
|
||||
#
|
||||
# Address = base+(testnum<<2)
|
||||
# sw testreg, (testnum<<2)(basereg)
|
||||
#
|
||||
#define TEST_CASE( testnum, testreg, correctval, code... ) \
|
||||
test_ ## testnum: \
|
||||
code; \
|
||||
li x29, MASK_XLEN(correctval); \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG(testnum,testreg); \
|
||||
bne testreg, x29, fail;
|
||||
|
||||
# We use a macro hack to simpify code generation for various numbers
|
||||
# of bubble cycles.
|
||||
|
||||
#define TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_1 nop; TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_2 nop; TEST_INSERT_NOPS_1
|
||||
#define TEST_INSERT_NOPS_3 nop; TEST_INSERT_NOPS_2
|
||||
#define TEST_INSERT_NOPS_4 nop; TEST_INSERT_NOPS_3
|
||||
#define TEST_INSERT_NOPS_5 nop; TEST_INSERT_NOPS_4
|
||||
#define TEST_INSERT_NOPS_6 nop; TEST_INSERT_NOPS_5
|
||||
#define TEST_INSERT_NOPS_7 nop; TEST_INSERT_NOPS_6
|
||||
#define TEST_INSERT_NOPS_8 nop; TEST_INSERT_NOPS_7
|
||||
#define TEST_INSERT_NOPS_9 nop; TEST_INSERT_NOPS_8
|
||||
#define TEST_INSERT_NOPS_10 nop; TEST_INSERT_NOPS_9
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UI MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for instructions with immediate operand
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
|
||||
|
||||
#define TEST_IMM_OP( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x30, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x1, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
inst x30, x1, SEXT_IMM(imm); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x30, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x30, x1, SEXT_IMM(imm); \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZEROSRC1( testnum, inst, result, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
inst x1, x0, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZERODEST( testnum, inst, val1, imm ) \
|
||||
TEST_CASE( testnum, x0, 0, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x0, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_R_OP( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
li x1, val1; \
|
||||
inst x30, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_SRC1_EQ_DEST( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, val1; \
|
||||
inst x1, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_DEST_BYPASS( testnum, nop_cycles, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
inst x30, x1; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x30, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register-register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x30, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x1, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x2, x1, x2; \
|
||||
)
|
||||
|
||||
#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 x2, MASK_XLEN(val2); \
|
||||
inst x30, x1, x2; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x30, 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, x30, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x30, x1, x2; \
|
||||
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, x30, result, \
|
||||
li x4, 0; \
|
||||
1: li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x30, x1, x2; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, x0, x1; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, 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 x2, MASK_XLEN(val2); \
|
||||
inst x0, x1, x2; \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test memory instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_LD_OP( testnum, inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
la x1, base; \
|
||||
inst x30, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x30, result, \
|
||||
la x1, base; \
|
||||
li x2, result; \
|
||||
store_inst x2, offset(x1); \
|
||||
load_inst x30, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_LD_DEST_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
inst x30, offset(x1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x30, 0; \
|
||||
li x29, result; \
|
||||
bne x6, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b; \
|
||||
|
||||
#define TEST_LD_SRC1_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x30, offset(x1); \
|
||||
li x29, result; \
|
||||
bne x30, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC12_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x30, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x30, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC21_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x30, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x30, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_OP_TAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 2f; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
1: bne x0, TESTNUM, 3f; \
|
||||
2: inst x1, x2, 1b; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_OP_NOTTAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 1f; \
|
||||
bne x0, TESTNUM, 2f; \
|
||||
1: bne x0, TESTNUM, fail; \
|
||||
2: inst x1, x2, 1b; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test jump instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_JR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x6; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_JALR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x19, x6, 0; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UF MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests floating-point instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define qNaNf 0f:7fc00000
|
||||
#define sNaNf 0f:7f800001
|
||||
#define qNaN 0d:7ff8000000000000
|
||||
#define sNaN 0d:7ff0000000000001
|
||||
|
||||
#define TEST_FP_OP_S_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
flw f0, 0(a0); \
|
||||
flw f1, 4(a0); \
|
||||
flw f2, 8(a0); \
|
||||
lw a3, 12(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
.pushsection .data; \
|
||||
.align 2; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.float val3; \
|
||||
.result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FP_OP_D_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld f0, 0(a0); \
|
||||
fld f1, 8(a0); \
|
||||
fld f2, 16(a0); \
|
||||
ld a3, 24(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.result; \
|
||||
.popsection
|
||||
|
||||
// TODO: assign a separate mem location for the comparison address?
|
||||
#define TEST_FP_OP_D32_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld f0, 0(a0); \
|
||||
fld f1, 8(a0); \
|
||||
fld f2, 16(a0); \
|
||||
lw a3, 24(a0); \
|
||||
lw t1, 28(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne t1, t2, fail; \
|
||||
bne a1, a2, fail; \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FCVT_S_D32( testnum, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
|
||||
fcvt.s.d f3, f0; fcvt.d.s f3, f3; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
#define TEST_FCVT_S_D( testnum, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
|
||||
fcvt.s.d f3, f0; fcvt.d.s f3, f3; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FCVT_D_S( testnum, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, 0, float result, val1, 0.0, 0.0, \
|
||||
fcvt.d.s f3, f0; fcvt.s.d f3, f3; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D32( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
// ^: store computation result in address from a0, load high-word into t2
|
||||
|
||||
#define TEST_FP_OP1_D( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D32_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
// ^: store computation result in address from a0, load high-word into t2
|
||||
|
||||
#define TEST_FP_OP1_D_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_D32( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
// ^: store computation result in address from a0, load high-word into t2
|
||||
|
||||
#define TEST_FP_OP2_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_S( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_D32( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
// ^: store computation result in address from a0, load high-word into t2
|
||||
|
||||
#define TEST_FP_OP3_D( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_INT_OP_S( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_INT_OP_D32( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, f1; li t2, 0)
|
||||
|
||||
#define TEST_FP_INT_OP_D( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_CMP_OP_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FP_CMP_OP_D32( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1; li t2, 0)
|
||||
|
||||
#define TEST_FP_CMP_OP_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FCLASS_S(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.s.x fa0, a0; \
|
||||
fclass.s a0, fa0)
|
||||
|
||||
#define TEST_FCLASS_D32(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld fa0, 0(a0); \
|
||||
fclass.d a0, fa0) \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.dword input; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FCLASS_D(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.d.x fa0, a0; \
|
||||
fclass.d a0, fa0)
|
||||
|
||||
#define TEST_INT_FP_OP_S( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
lw a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.s a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
.pushsection .data; \
|
||||
.align 2; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_INT_FP_OP_D32( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
lw a3, 0(a0); \
|
||||
lw a4, 4(a0); \
|
||||
li a1, val1; \
|
||||
inst f0, a1; \
|
||||
\
|
||||
fsd f0, 0(a0); \
|
||||
lw a1, 4(a0); \
|
||||
lw a0, 0(a0); \
|
||||
\
|
||||
fsflags x0; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a4, fail; \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_INT_FP_OP_D( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
ld a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.d a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double result; \
|
||||
.popsection
|
||||
|
||||
// We need some special handling here to allow 64-bit comparison in 32-bit arch
|
||||
// TODO: find a better name and clean up when intended for general usage?
|
||||
#define TEST_CASE_D32( testnum, testreg1, testreg2, correctval, code... ) \
|
||||
test_ ## testnum: \
|
||||
code; \
|
||||
la x31, test_ ## testnum ## _data ; \
|
||||
lw x29, 0(x31); \
|
||||
lw x31, 4(x31); \
|
||||
li TESTNUM, testnum; \
|
||||
SWSIG (testnum, TESTNUM);\
|
||||
bne testreg1, x29, fail;\
|
||||
bne testreg2, x31, fail;\
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## testnum ## _data: \
|
||||
.dword correctval; \
|
||||
.popsection
|
||||
|
||||
// ^ x30 is used in some other macros, to avoid issues we use x31 for upper word
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Pass and fail code (assumes test num is in TESTNUM)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_PASSFAIL \
|
||||
bne x0, TESTNUM, pass; \
|
||||
fail: \
|
||||
RVTEST_FAIL; \
|
||||
pass: \
|
||||
RVTEST_PASS \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test data section
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_DATA
|
||||
|
||||
#endif
|
||||
70
sim/tests/riscv_compliance/compliance_io.h
Normal file
70
sim/tests/riscv_compliance/compliance_io.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// RISC-V Compliance IO Test Header File
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _COMPLIANCE_IO_H
|
||||
#define _COMPLIANCE_IO_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// RV IO Macros (Non functional)
|
||||
//-----------------------------------------------------------------------
|
||||
#ifdef _COMPLIANCE_OUTPUT
|
||||
|
||||
#define RVTEST_IO_PUSH(_SP) \
|
||||
la _SP, begin_regstate; \
|
||||
sw x3, 0(_SP); \
|
||||
sw x4, 4(_SP); \
|
||||
sw x5, 8(_SP);
|
||||
|
||||
#define RVTEST_IO_POP(_SP) \
|
||||
la _SP, begin_regstate; \
|
||||
lw x3, 0(_SP); \
|
||||
lw x4, 4(_SP); \
|
||||
lw x5, 8(_SP);
|
||||
|
||||
#define RVTEST_IO_WRITE_STR(_SP, _STR) \
|
||||
.section .data.string; \
|
||||
20001: \
|
||||
.string _STR; \
|
||||
.section .text; \
|
||||
RVTEST_IO_PUSH(_SP) \
|
||||
li x3, 0xF0000000; \
|
||||
la x4, 20001b; \
|
||||
2: lb x5, 0(x4); \
|
||||
sb x5, 0(x3); \
|
||||
beq x5, zero, 1f; \
|
||||
add x4, x4, 1; \
|
||||
j 2b; \
|
||||
1: RVTEST_IO_POP(_SP)
|
||||
|
||||
#else // #ifdef _COMPLIANCE_OUTPUT
|
||||
|
||||
#define RVTEST_IO_WRITE_STR(_SP, _STR)
|
||||
|
||||
#endif // #end #ifdef _COMPLIANCE_OUTPUT
|
||||
|
||||
#define RVTEST_IO_INIT
|
||||
#define RVTEST_IO_CHECK()
|
||||
#define RVTEST_IO_ASSERT_GPR_EQ(_SP, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_SFPR_EQ(_F, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_DFPR_EQ(_D, _R, _I)
|
||||
#define RVTEST_IO_ASSERT_EQ(_R, _I)
|
||||
|
||||
#endif // _COMPLIANCE_IO_H
|
||||
31
sim/tests/riscv_compliance/compliance_test.h
Normal file
31
sim/tests/riscv_compliance/compliance_test.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// RISC-V Compliance Test Header File
|
||||
// Copyright (c) 2017, Codasip Ltd. All Rights Reserved.
|
||||
// See LICENSE for license details.
|
||||
//
|
||||
// Description: Common header file for RV32I tests
|
||||
|
||||
#ifndef _COMPLIANCE_TEST_H
|
||||
#define _COMPLIANCE_TEST_H
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// RV Compliance Macros
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RV_COMPLIANCE_HALT \
|
||||
|
||||
#define RV_COMPLIANCE_RV32M \
|
||||
RVTEST_RV32M \
|
||||
|
||||
#define RV_COMPLIANCE_CODE_BEGIN \
|
||||
RVTEST_CODE_BEGIN \
|
||||
|
||||
#define RV_COMPLIANCE_CODE_END \
|
||||
RVTEST_CODE_END \
|
||||
|
||||
#define RV_COMPLIANCE_DATA_BEGIN \
|
||||
RVTEST_DATA_BEGIN \
|
||||
|
||||
#define RV_COMPLIANCE_DATA_END \
|
||||
RVTEST_DATA_END \
|
||||
|
||||
#endif
|
||||
7
sim/tests/riscv_compliance/riscv_test.h
Normal file
7
sim/tests/riscv_compliance/riscv_test.h
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef _RISCV_TEST_H
|
||||
#define _RISCV_TEST_H
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#endif
|
||||
463
sim/tests/riscv_compliance/riscv_test_macros.h
Normal file
463
sim/tests/riscv_compliance/riscv_test_macros.h
Normal file
@@ -0,0 +1,463 @@
|
||||
// RISC-V Compliance IO Test Header File
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "riscv_macros.h"
|
||||
|
||||
//
|
||||
// In general the following registers are reserved
|
||||
// ra, a0, t0, t1
|
||||
// Additionally on an assertion violation, t1, t2 are overwritten
|
||||
// x1, x10, x5, x6, x7 respectively
|
||||
// Floating registers reserved
|
||||
// f5
|
||||
//
|
||||
|
||||
#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
|
||||
|
||||
#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
|
||||
|
||||
// Base function for integer operations
|
||||
#define TEST_CASE(testreg, destreg, correctval, swreg, offset, code... ) \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) \
|
||||
|
||||
// Base functions for single precision floating point operations
|
||||
#define TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg1, 0(a0); \
|
||||
flw reg2, 4(a0); \
|
||||
lw t1, 8(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
lw t1, 0(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 1; \
|
||||
test_ ## test_num ## _data: \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg, 0(a0); \
|
||||
lw t1, 4(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg1, 0(a0); \
|
||||
flw reg2, 4(a0); \
|
||||
flw reg3, 8(a0); \
|
||||
lw t1, 12(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 4; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.float val3; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg, 0(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 1; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, code...) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
li reg, val; \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
lw a1, 0(a0); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 1; \
|
||||
test_ ## test_num ## _data: \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
// Base functions for double precision floating point operations - rv32d
|
||||
#define TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg1, 0(a0); \
|
||||
fld reg2, 8(a0); \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 16(a0); \
|
||||
lw t2, 20(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 3; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
.pushsection .data; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 0(a0); \
|
||||
lw t2, 4(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 1; \
|
||||
test_ ## test_num ## _data: \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg, 0(a0); \
|
||||
lw t1, 8(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg1, 0(a0); \
|
||||
fld reg2, 8(a0); \
|
||||
fld reg3, 16(a0); \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 24(a0); \
|
||||
lw t2, 28(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.align 4; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
.pushsection .data; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
//Tests for a instructions with register-register operand
|
||||
#define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg1, MASK_XLEN(val1); \
|
||||
li reg2, MASK_XLEN(val2); \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC1( inst, destreg, reg, correctval, val1, val2, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val1); \
|
||||
li reg, MASK_XLEN(val2); \
|
||||
inst destreg, destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC2( inst, destreg, reg, correctval, val1, val2, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val1); \
|
||||
li destreg, MASK_XLEN(val2); \
|
||||
inst destreg, reg, destreg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC12( inst, destreg, correctval, val, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val1); \
|
||||
inst destreg, destreg, destreg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO1( inst, destreg, reg, correctval, val, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, x0, reg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO2( inst, destreg, reg, correctval, val, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO12( inst, destreg, correctval, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
inst destreg, x0, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERODEST( inst, reg1, reg2, val1, val2, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, x0, 0, swreg, offset, \
|
||||
li reg1, MASK_XLEN(val1); \
|
||||
li reg2, MASK_XLEN(val2); \
|
||||
inst x0, reg1, reg2; \
|
||||
)
|
||||
|
||||
//Tests for a instructions with register-immediate operand
|
||||
#define TEST_IMM_OP( inst, destreg, reg, correctval, val, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC( inst, destreg, correctval, val, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val); \
|
||||
inst destreg, destreg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZEROSRC( inst, destreg, correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
inst destreg, x0, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZERODEST( inst, reg, val, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, x0, 0, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst x0, reg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ONEREG( inst, destreg, correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
inst destreg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_AUIPC(inst, destreg, correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
1: \
|
||||
inst destreg, imm; \
|
||||
la swreg, 1b; \
|
||||
sub destreg, destreg, swreg; \
|
||||
)
|
||||
|
||||
//Tests for a compressed instruction
|
||||
#define TEST_CR_OP( inst, destreg, reg, correctval, val1, val2, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val1); \
|
||||
li destreg, MASK_XLEN(val2); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_CI_OP( inst, destreg, correctval, val, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg, destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val); \
|
||||
inst destreg, imm; \
|
||||
)
|
||||
|
||||
#define TEST_CI_OP_NOREG(inst, correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg,x0, correctval, swreg, offset, \
|
||||
inst imm; \
|
||||
)
|
||||
|
||||
//Tests for floating point instructions - single precision
|
||||
#define TEST_FP_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_FP_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FP_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \
|
||||
TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \
|
||||
inst destreg, reg1, reg2, reg3; \
|
||||
)
|
||||
|
||||
#define TEST_FP_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FP_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
//Tests for floating point instructions - double precision
|
||||
#define TEST_FPD_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \
|
||||
TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \
|
||||
inst destreg, reg1, reg2, reg3; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_CADDI16SP(correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg,x2, correctval, swreg, offset, \
|
||||
c.addi16sp x2, imm; \
|
||||
)
|
||||
|
||||
#define TEST_CADDI4SPN(destreg, correctval, imm, swreg, offset, testreg) \
|
||||
TEST_CASE(testreg,destreg, correctval, swreg, offset, \
|
||||
c.addi4spn destreg, x2, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_CJL(inst, reg, val, swreg, offset) \
|
||||
li x10, val; \
|
||||
la reg, 1f; \
|
||||
inst reg; \
|
||||
li x10, 0x123ab; \
|
||||
1: \
|
||||
sw x10, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, x10, val); \
|
||||
|
||||
#define ABS(x) ((x >> 11) ^ x) - (x >> 11)
|
||||
|
||||
#define TEST_CJ(inst, reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
inst 1f; \
|
||||
li reg, 0x123ab; \
|
||||
1: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_CL(inst, reg, imm, swreg, offset) \
|
||||
la reg, test_data; \
|
||||
inst reg, imm(reg); \
|
||||
sw reg, offset(swreg); \
|
||||
|
||||
// lw reg, imm(x2)
|
||||
// c.lwsp reg, imm(x2)
|
||||
#define TEST_CLWSP(reg, imm, swreg, offset) \
|
||||
la x2, test_data; \
|
||||
c.lwsp reg, imm(x2); \
|
||||
sw reg, offset(swreg); \
|
||||
|
||||
#define TEST_CSW(test_data, inst, reg1, reg2, val, imm, swreg, offset) \
|
||||
li reg1, val; \
|
||||
la reg2, test_data; \
|
||||
inst reg1, imm(reg2); \
|
||||
lw reg1, imm(reg2); \
|
||||
sw reg1, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg1, val); \
|
||||
|
||||
#define TEST_CSWSP(test_data, reg, val, imm, swreg, offset) \
|
||||
la x2, test_data; \
|
||||
li reg, val; \
|
||||
c.swsp reg, imm(x2); \
|
||||
lw reg, imm(x2); \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_CBEQZ(reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
c.sub reg, reg; \
|
||||
c.beqz reg, 3f; \
|
||||
li reg, 0x123ab; \
|
||||
3: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, 0x0); \
|
||||
|
||||
#define TEST_CBNEZ(reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
c.bnez reg, 4f; \
|
||||
li reg, 0x0; \
|
||||
4: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
fmv.x.s destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
fmv.s.x destreg, reg; \
|
||||
)
|
||||
|
||||
#define SWSIG(a,b)
|
||||
|
||||
593
sim/tests/riscv_compliance/test_macros.h
Normal file
593
sim/tests/riscv_compliance/test_macros.h
Normal file
@@ -0,0 +1,593 @@
|
||||
|
||||
// RISC-V Compliance Test Header File
|
||||
// Copyright (c) 2017, Codasip Ltd. All Rights Reserved.
|
||||
// See LICENSE for license details.
|
||||
//
|
||||
// Description: Common header file for RV32I tests
|
||||
|
||||
#ifndef _TEST_MACROS_H
|
||||
#define _TEST_MACROS_H
|
||||
|
||||
#include "riscv_macros.h"
|
||||
|
||||
// RISC-V Compliance IO Test Header File
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2018 Imperas Software Ltd., www.imperas.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// In general the following registers are reserved
|
||||
// ra, a0, t0, t1
|
||||
// Additionally on an assertion violation, t1, t2 are overwritten
|
||||
// x1, x10, x5, x6, x7 respectively
|
||||
// Floating registers reserved
|
||||
// f5
|
||||
//
|
||||
|
||||
#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
|
||||
|
||||
#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
|
||||
|
||||
// Base function for integer operations
|
||||
#define TEST_CASE(destreg, correctval, swreg, offset, code... ) \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
|
||||
// Base functions for single precision floating point operations
|
||||
#define TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg1, 0(a0); \
|
||||
flw reg2, 4(a0); \
|
||||
lw t1, 8(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
lw t1, 0(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg, 0(a0); \
|
||||
lw t1, 4(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 4; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg1, 0(a0); \
|
||||
flw reg2, 4(a0); \
|
||||
flw reg3, 8(a0); \
|
||||
lw t1, 12(a0); \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, t1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 16; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.float val3; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
flw reg, 0(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.float val; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, code...) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
li reg, val; \
|
||||
code; \
|
||||
fsw destreg, offset(swreg); \
|
||||
lw a1, 0(a0); \
|
||||
RVTEST_IO_ASSERT_SFPR_EQ(destreg, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
// Base functions for double precision floating point operations - rv32d
|
||||
#define TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg1, 0(a0); \
|
||||
fld reg2, 8(a0); \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 16(a0); \
|
||||
lw t2, 20(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
.pushsection .data; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 0(a0); \
|
||||
lw t2, 4(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 2; \
|
||||
test_ ## test_num ## _data: \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg, 0(a0); \
|
||||
lw t1, 8(a0); \
|
||||
code; \
|
||||
sw destreg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, destreg, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 4; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val; \
|
||||
.word correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, code... ) \
|
||||
la a0, test_ ## test_num ## _data; \
|
||||
fld reg1, 0(a0); \
|
||||
fld reg2, 8(a0); \
|
||||
fld reg3, 16(a0); \
|
||||
code; \
|
||||
fsd destreg, offset(swreg); \
|
||||
lw t1, 24(a0); \
|
||||
lw t2, 28(a0); \
|
||||
la a0, store_ ## test_num ## _data; \
|
||||
fsd destreg, 0(a0); \
|
||||
lw a1, 0(a0); \
|
||||
lw a2, 4(a0); \
|
||||
RVTEST_IO_ASSERT_DFPR_EQ(destreg, t2, t1, a2, a1, correctval) \
|
||||
.pushsection .data; \
|
||||
.balign 16; \
|
||||
test_ ## test_num ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.dword correctval; \
|
||||
.popsection; \
|
||||
.pushsection .data; \
|
||||
store_ ## test_num ## _data: \
|
||||
.fill 1, 8, -1; \
|
||||
.popsection
|
||||
|
||||
//Tests for a instructions with register-register operand
|
||||
#define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li reg1, MASK_XLEN(val1); \
|
||||
li reg2, MASK_XLEN(val2); \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC1( inst, destreg, reg, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val1); \
|
||||
li reg, MASK_XLEN(val2); \
|
||||
inst destreg, destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC2( inst, destreg, reg, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val1); \
|
||||
li destreg, MASK_XLEN(val2); \
|
||||
inst destreg, reg, destreg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC12( inst, destreg, correctval, val, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val1); \
|
||||
inst destreg, destreg, destreg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO1( inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, x0, reg; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO2( inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERO12( inst, destreg, correctval, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
inst destreg, x0, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERODEST( inst, reg1, reg2, val1, val2, swreg, offset) \
|
||||
TEST_CASE( x0, 0, swreg, offset, \
|
||||
li reg1, MASK_XLEN(val1); \
|
||||
li reg2, MASK_XLEN(val2); \
|
||||
inst x0, reg1, reg2; \
|
||||
)
|
||||
|
||||
//Tests for a instructions with register-immediate operand
|
||||
#define TEST_IMM_OP( inst, destreg, reg, correctval, val, imm, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC( inst, destreg, correctval, val, imm, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val); \
|
||||
inst destreg, destreg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZEROSRC( inst, destreg, correctval, imm, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
inst destreg, x0, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZERODEST( inst, reg, val, imm, swreg, offset) \
|
||||
TEST_CASE ( x0, 0, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst x0, reg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ONEREG( inst, destreg, correctval, imm, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
inst destreg, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_AUIPC(inst, destreg, correctval, imm, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
1: \
|
||||
inst destreg, SEXT_IMM(imm); \
|
||||
la swreg, 1b; \
|
||||
sub destreg, destreg, swreg; \
|
||||
)
|
||||
|
||||
//Tests for a compressed instruction
|
||||
#define TEST_CR_OP( inst, destreg, reg, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE ( destreg, correctval, swreg, offset, \
|
||||
li reg, MASK_XLEN(val1); \
|
||||
li destreg, MASK_XLEN(val2); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_CI_OP( inst, destreg, correctval, val, imm, swreg, offset) \
|
||||
TEST_CASE( destreg, correctval, swreg, offset, \
|
||||
li destreg, MASK_XLEN(val); \
|
||||
inst destreg, imm; \
|
||||
)
|
||||
|
||||
#define TEST_CI_OP_NOREG(inst, correctval, imm, swreg, offset) \
|
||||
TEST_CASE (x0, correctval, swreg, offset, \
|
||||
inst imm; \
|
||||
)
|
||||
|
||||
//Tests for floating point instructions - single precision
|
||||
#define TEST_FP_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE_FP(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_FP_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FP_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \
|
||||
TEST_CASE_FP_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \
|
||||
inst destreg, reg1, reg2, reg3; \
|
||||
)
|
||||
|
||||
#define TEST_FP_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_I(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FP_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_I2(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
//Tests for floating point instructions - double precision
|
||||
#define TEST_FPD_OP(test_num, inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset) \
|
||||
TEST_CASE_FPD(test_num, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, \
|
||||
inst destreg, reg1, reg2; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_ONEREG(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD(test_num, destreg, reg, reg, correctval, val, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_4REG(test_num, inst, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset) \
|
||||
TEST_CASE_FPD_4REG(test_num, destreg, reg1, reg2, reg3, correctval, val1, val2, val3, swreg, offset, \
|
||||
inst destreg, reg1, reg2, reg3; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_I(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD_I(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
li reg, MASK_XLEN(val); \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FPD_I2(test_num, inst, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FPD_I2(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
inst destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_CADDI16SP(correctval, imm, swreg, offset) \
|
||||
TEST_CASE(x2, correctval, swreg, offset, \
|
||||
c.addi16sp x2, imm; \
|
||||
)
|
||||
|
||||
#define TEST_CADDI4SPN(destreg, correctval, imm, swreg, offset) \
|
||||
TEST_CASE(destreg, correctval, swreg, offset, \
|
||||
c.addi4spn destreg, x2, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_CJL(inst, reg, val, swreg, offset) \
|
||||
li x10, val; \
|
||||
la reg, 1f; \
|
||||
inst reg; \
|
||||
li x10, 0x123ab; \
|
||||
1: \
|
||||
sw x10, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, x10, val); \
|
||||
|
||||
#define ABS(x) ((x >> 11) ^ x) - (x >> 11)
|
||||
|
||||
#define TEST_CJ(inst, reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
inst 1f; \
|
||||
li reg, 0x123ab; \
|
||||
1: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_CL(inst, reg, imm, swreg, offset) \
|
||||
la reg, test_data; \
|
||||
inst reg, imm(reg); \
|
||||
sw reg, offset(swreg); \
|
||||
|
||||
// lw reg, imm(x2)
|
||||
// c.lwsp reg, imm(x2)
|
||||
#define TEST_CLWSP(reg, imm, swreg, offset) \
|
||||
la x2, test_data; \
|
||||
c.lwsp reg, imm(x2); \
|
||||
sw reg, offset(swreg); \
|
||||
|
||||
#define TEST_CSW(test_data, inst, reg1, reg2, val, imm, swreg, offset) \
|
||||
li reg1, val; \
|
||||
la reg2, test_data; \
|
||||
inst reg1, imm(reg2); \
|
||||
lw reg1, imm(reg2); \
|
||||
sw reg1, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg1, val); \
|
||||
|
||||
#define TEST_CSWSP(test_data, reg, val, imm, swreg, offset) \
|
||||
la x2, test_data; \
|
||||
li reg, val; \
|
||||
c.swsp reg, imm(x2); \
|
||||
lw reg, imm(x2); \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_CBEQZ(reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
c.sub reg, reg; \
|
||||
c.beqz reg, 3f; \
|
||||
li reg, 0x123ab; \
|
||||
3: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, 0x0); \
|
||||
|
||||
#define TEST_CBNEZ(reg, val, swreg, offset) \
|
||||
li reg, val; \
|
||||
c.bnez reg, 4f; \
|
||||
li reg, 0x0; \
|
||||
4: \
|
||||
sw reg, offset(swreg); \
|
||||
RVTEST_IO_ASSERT_GPR_EQ(x31, reg, val); \
|
||||
|
||||
#define TEST_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_FMVXS(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
fmv.x.s destreg, reg; \
|
||||
)
|
||||
|
||||
#define TEST_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset) \
|
||||
TEST_CASE_FP_FMVSX(test_num, destreg, reg, correctval, val, swreg, offset, \
|
||||
fmv.s.x destreg, reg; \
|
||||
)
|
||||
|
||||
#define SWSIG(a,b)
|
||||
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define SATP_MODE SATP64_MODE
|
||||
#else
|
||||
#define SATP_MODE SATP32_MODE
|
||||
#endif
|
||||
|
||||
#define SATP32_MODE 0x80000000
|
||||
#define SATP32_ASID 0x7FC00000
|
||||
#define SATP32_PPN 0x003FFFFF
|
||||
#define SATP64_MODE 0xF000000000000000
|
||||
#define SATP64_ASID 0x0FFFF00000000000
|
||||
#define SATP64_PPN 0x00000FFFFFFFFFFF
|
||||
|
||||
#define SATP_MODE_OFF 0
|
||||
#define SATP_MODE_SV32 1
|
||||
#define SATP_MODE_SV39 8
|
||||
#define SATP_MODE_SV48 9
|
||||
#define SATP_MODE_SV57 10
|
||||
#define SATP_MODE_SV64 11
|
||||
|
||||
#define TEST_FP_OP2_D32( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
#define TEST_CASE_D32( testnum, testreg1, testreg2, correctval, code... ) \
|
||||
test_ ## testnum: \
|
||||
code; \
|
||||
la x31, test_ ## testnum ## _data ; \
|
||||
lw x29, 0(x31); \
|
||||
lw x31, 4(x31); \
|
||||
li TESTNUM, testnum; \
|
||||
bne testreg1, x29, fail;\
|
||||
bne testreg2, x31, fail;\
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.dword correctval; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FP_OP_D32_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld f0, 0(a0); \
|
||||
fld f1, 8(a0); \
|
||||
fld f2, 16(a0); \
|
||||
lw a3, 24(a0); \
|
||||
lw t1, 28(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne t1, t2, fail; \
|
||||
bne a1, a2, fail; \
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FP_OP1_D32( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
#define TEST_FCLASS_D32(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld fa0, 0(a0); \
|
||||
fclass.d a0, fa0) \
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.dword input; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FP_CMP_OP_D32( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1; li t2, 0)
|
||||
|
||||
#define TEST_INT_FP_OP_D32( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
lw a3, 0(a0); \
|
||||
lw a4, 4(a0); \
|
||||
li a1, val1; \
|
||||
inst f0, a1; \
|
||||
\
|
||||
fsd f0, 0(a0); \
|
||||
lw a1, 4(a0); \
|
||||
lw a0, 0(a0); \
|
||||
\
|
||||
fsflags x0; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a4, fail; \
|
||||
.pushsection .data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double result; \
|
||||
.popsection
|
||||
|
||||
#define TEST_FCVT_S_D32( testnum, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
|
||||
fcvt.s.d f3, f0; fcvt.d.s f3, f3; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
#define TEST_FP_OP3_D32( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, double result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
#define TEST_FP_OP1_D32_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D32_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fsd f3, 0(a0); lw t2, 4(a0); lw a0, 0(a0))
|
||||
|
||||
|
||||
#endif
|
||||
93
sim/tests/riscv_isa/Makefile
Normal file
93
sim/tests/riscv_isa/Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
|
||||
include rv32_tests.inc
|
||||
|
||||
ARCH_tmp := imf
|
||||
|
||||
ifneq (,$(findstring c,$(ARCH_lowercase)))
|
||||
ARCH_tmp := $(ARCH_tmp)c
|
||||
endif
|
||||
|
||||
override ARCH := $(ARCH_tmp)
|
||||
|
||||
src_dir := $(CURDIR)
|
||||
obj_dir := $(bld_dir)/riscv_objs
|
||||
test_list := $(patsubst %.S, %, $(notdir $(rv32_isa_tests)))
|
||||
objs := $(addprefix $(obj_dir)/,$(test_list:%=%.o))
|
||||
test_elf := $(addprefix $(bld_dir)/,$(test_list:%=%.elf))
|
||||
test_hex := $(addprefix $(bld_dir)/,$(test_list:%=%.hex))
|
||||
test_dump := $(addprefix $(bld_dir)/,$(test_list:%=%.dump))
|
||||
|
||||
CFLAGS := -I$(inc_dir) -I$(src_dir) -DASM -Wa,-march=rv32$(ARCH)_zicsr_zifencei -march=rv32$(ARCH)_zicsr_zifencei -mabi=ilp32f -D__riscv_xlen=32
|
||||
LDFLAGS := -static -fvisibility=hidden -nostdlib -nostartfiles -T$(inc_dir)/link.ld -march=rv32$(ARCH)_zicsr_zifencei -mabi=ilp32f
|
||||
RISCV_TESTS := $(src_dir)/../../../dependencies/riscv-tests/
|
||||
|
||||
VPATH += $(src_dir) $(bld_dir) $(obj_dir) $(RISCV_TESTS)
|
||||
|
||||
default: log_requested_tgt check_riscv_tests $(test_elf) $(test_hex) $(test_dump)
|
||||
|
||||
define compile_template
|
||||
$(obj_dir)/$$(basename $(notdir $(SRC))).o: $$(SRC) | $(obj_dir)
|
||||
$(RISCV_GCC) -c $$< $(CFLAGS) -o $$@
|
||||
endef
|
||||
|
||||
$(foreach SRC,$(rv32_isa_tests), $(eval $(compile_template)))
|
||||
|
||||
log_requested_tgt:
|
||||
$(foreach test_name, $(test_list), $(eval $(shell echo $(test_name).hex >> $(bld_dir)/test_info)))
|
||||
|
||||
$(obj_dir) :
|
||||
mkdir -p $(obj_dir)
|
||||
|
||||
$(bld_dir)/%.elf: $(obj_dir)/%.o | $(obj_dir)
|
||||
$(RISCV_GCC) $^ $(LDFLAGS) -o $@
|
||||
|
||||
$(bld_dir)/%.hex: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJCOPY) $^ $@
|
||||
|
||||
$(bld_dir)/%.dump: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJDUMP) -D -w -x -S $^ > $@
|
||||
|
||||
clean:
|
||||
$(RM) $(test_elf) $(test_hex) $(test_dump) $(objs)
|
||||
$(RM) -R $(obj_dir)
|
||||
|
||||
|
||||
.PHONY: check_riscv_tests
|
||||
|
||||
riscv_tests_dir := $(if $(RISCV_TESTS), $(RISCV_TESTS), ./undefined)
|
||||
riscv_tests_commit := 5f8a4918c6482e65c67a2b7decd5c2af3e3fe0e5
|
||||
## commit hash readed from local copy of https://github.com/riscv/riscv-tests
|
||||
tmp_commit = $(shell cd $(riscv_tests_dir) 2>/dev/null && git log -1 | grep "commit" | cut -f2 -d ' ')
|
||||
is_commit_good = $(if $(subst $(riscv_tests_commit),,$(tmp_commit)),false,true)
|
||||
|
||||
# Color
|
||||
RED=\033[0;31m
|
||||
NC=\033[0m
|
||||
|
||||
check_riscv_tests : $(riscv_tests_dir)
|
||||
@if [ ! -d $(riscv_tests_dir) ]; then \
|
||||
echo -e "$(RED)==========================================================================" &&\
|
||||
echo " Error! Environment variable RISCV_TESTS='$(riscv_tests_dir)' " &&\
|
||||
echo " directory not exist!" && \
|
||||
echo "==========================================================================$(NC)" ; \
|
||||
fi
|
||||
ifneq ($(is_commit_good),true)
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Warning! Execution of test code is not guaranteed "
|
||||
@echo " while using the current commit of repositorylocated at : $(riscv_tests_dir) ."
|
||||
@echo " "
|
||||
@echo " Riscv-tests repository must point to commit $(riscv_tests_commit)!"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
endif
|
||||
|
||||
$(riscv_tests_dir) :.
|
||||
ifndef RISCV_TESTS
|
||||
@echo -e "$(RED)=========================================================================="
|
||||
@echo " Error! Environment variable RISCV_TESTS not set!"
|
||||
@echo " You must set the environment variable RISCV_TESTS"
|
||||
@echo " The variable should point to the local copy of the"
|
||||
@echo " repository https://github.com/riscv/riscv-tests"
|
||||
@echo " with the commit $(riscv_tests_commit)"
|
||||
@echo -e "==========================================================================$(NC)"
|
||||
exit 1
|
||||
endif
|
||||
6
sim/tests/riscv_isa/riscv_test.h
Normal file
6
sim/tests/riscv_isa/riscv_test.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __RISCV__TEST__H
|
||||
#define __RISCV__TEST__H
|
||||
|
||||
#include "riscv_macros.h"
|
||||
|
||||
#endif // #ifndef __RISCV__TEST__H
|
||||
66
sim/tests/riscv_isa/rv32_tests.inc
Normal file
66
sim/tests/riscv_isa/rv32_tests.inc
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
ARCH_lowercase = $(shell echo $(ARCH) | tr A-Z a-z)
|
||||
|
||||
|
||||
rv32_isa_tests += isa/rv32ui/add.S \
|
||||
isa/rv32ui/addi.S \
|
||||
isa/rv32ui/and.S \
|
||||
isa/rv32ui/andi.S \
|
||||
isa/rv32ui/auipc.S \
|
||||
isa/rv32ui/beq.S \
|
||||
isa/rv32ui/bge.S \
|
||||
isa/rv32ui/bgeu.S \
|
||||
isa/rv32ui/blt.S \
|
||||
isa/rv32ui/bltu.S \
|
||||
isa/rv32ui/bne.S \
|
||||
isa/rv32mi/csr.S \
|
||||
isa/rv32ui/fence_i.S \
|
||||
isa/rv32mi/illegal.S \
|
||||
isa/rv32ui/jal.S \
|
||||
isa/rv32ui/jalr.S \
|
||||
isa/rv32ui/lb.S \
|
||||
isa/rv32ui/lbu.S \
|
||||
isa/rv32ui/lh.S \
|
||||
isa/rv32ui/lhu.S \
|
||||
isa/rv32ui/lui.S \
|
||||
isa/rv32ui/lw.S \
|
||||
isa/rv32mi/ma_addr.S \
|
||||
isa/rv32mi/ma_fetch.S \
|
||||
isa/rv32mi/mcsr.S \
|
||||
isa/rv32ui/or.S \
|
||||
isa/rv32ui/ori.S \
|
||||
isa/rv32ui/sb.S \
|
||||
isa/rv32mi/sbreak.S \
|
||||
isa/rv32mi/scall.S \
|
||||
isa/rv32ui/sh.S \
|
||||
isa/rv32mi/shamt.S \
|
||||
isa/rv32ui/simple.S \
|
||||
isa/rv32ui/sll.S \
|
||||
isa/rv32ui/slli.S \
|
||||
isa/rv32ui/slt.S \
|
||||
isa/rv32ui/slti.S \
|
||||
isa/rv32ui/sltiu.S \
|
||||
isa/rv32ui/sltu.S \
|
||||
isa/rv32ui/sra.S \
|
||||
isa/rv32ui/srai.S \
|
||||
isa/rv32ui/srl.S \
|
||||
isa/rv32ui/srli.S \
|
||||
isa/rv32ui/sub.S \
|
||||
isa/rv32ui/sw.S \
|
||||
isa/rv32ui/xor.S \
|
||||
isa/rv32ui/xori.S
|
||||
|
||||
ifneq (,$(findstring m,$(ARCH_lowercase)))
|
||||
rv32_isa_tests += isa/rv32um/div.S \
|
||||
isa/rv32um/divu.S \
|
||||
isa/rv32um/mul.S \
|
||||
isa/rv32um/mulh.S \
|
||||
isa/rv32um/mulhsu.S \
|
||||
isa/rv32um/mulhu.S \
|
||||
isa/rv32um/rem.S \
|
||||
isa/rv32um/remu.S
|
||||
endif ## ifeq (m,$(findstring m,$(ARCH_lowercase)))
|
||||
|
||||
ifneq (,$(findstring c,$(ARCH_lowercase)))
|
||||
rv32_isa_tests += isa/rv32uc/rvc.S
|
||||
endif ## ifeq (m,$(findstring c,$(ARCH_lowercase)))
|
||||
7
sim/tests/riscv_isa/test_macros.h
Normal file
7
sim/tests/riscv_isa/test_macros.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef __TEST__MACROS__H
|
||||
#define __TEST__MACROS__H
|
||||
|
||||
#define sptbr satp
|
||||
#define mbadaddr mtval
|
||||
|
||||
#endif
|
||||
56
sim/verilator_wrap/scr1_ahb_wrapper.c
Normal file
56
sim/verilator_wrap/scr1_ahb_wrapper.c
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <verilated.h>
|
||||
#include "Vscr1_top_tb_ahb.h"
|
||||
#ifdef VCD_TRACE
|
||||
#include "verilated_vcd_c.h"
|
||||
#endif // #ifdef VCD_TRACE
|
||||
|
||||
#define STRINGIFY(s) _STRINGIFY(s)
|
||||
#define _STRINGIFY(s) #s
|
||||
|
||||
Vscr1_top_tb_ahb *top;
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
top = new Vscr1_top_tb_ahb;
|
||||
|
||||
#ifdef VCD_TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
#ifdef TRACE_LVLV
|
||||
top->trace(tfp, TRACE_LVLV);
|
||||
#else
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy by default
|
||||
#endif // #ifdef TRACE_LVLV
|
||||
|
||||
#ifdef VCD_FNAME
|
||||
tfp->open(STRINGIFY(VCD_FNAME));
|
||||
#else
|
||||
tfp->open("./simx.vcd");
|
||||
#endif // #ifdef VCD_FNAME
|
||||
#endif // #ifdef VCD_TRACE
|
||||
|
||||
while (!Verilated::gotFinish()) {
|
||||
if ((main_time % 10) == 1) {
|
||||
top->clk = 1;
|
||||
}
|
||||
if ((main_time % 10) == 6) {
|
||||
top->clk = 0;
|
||||
}
|
||||
top->eval();
|
||||
main_time++;
|
||||
#ifdef VCD_TRACE
|
||||
tfp->dump(main_time);
|
||||
#endif // #ifdef VCD_TRACE
|
||||
}
|
||||
top->final();
|
||||
#ifdef VCD_TRACE
|
||||
tfp->close();
|
||||
#endif // #ifdef VCD_TRACE
|
||||
delete top;
|
||||
}
|
||||
|
||||
55
sim/verilator_wrap/scr1_axi_wrapper.c
Normal file
55
sim/verilator_wrap/scr1_axi_wrapper.c
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <verilated.h>
|
||||
#include "Vscr1_top_tb_axi.h"
|
||||
#ifdef VCD_TRACE
|
||||
#include "verilated_vcd_c.h"
|
||||
#endif // #ifdef VCD_TRACE
|
||||
|
||||
#define STRINGIFY(s) _STRINGIFY(s)
|
||||
#define _STRINGIFY(s) #s
|
||||
|
||||
Vscr1_top_tb_axi *top;
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
top = new Vscr1_top_tb_axi;
|
||||
#ifdef VCD_TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
#ifdef TRACE_LVLV
|
||||
top->trace(tfp, TRACE_LVLV);
|
||||
#else
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy by default
|
||||
#endif // #ifdef TRACE_LVLV
|
||||
|
||||
#ifdef VCD_FNAME
|
||||
tfp->open(STRINGIFY(VCD_FNAME));
|
||||
#else
|
||||
tfp->open("./simx.vcd");
|
||||
#endif // #ifdef VCD_FNAME
|
||||
#endif // #ifdef VCD_TRACE
|
||||
|
||||
while (!Verilated::gotFinish()) {
|
||||
if ((main_time % 10) == 1) {
|
||||
top->clk = 1;
|
||||
}
|
||||
if ((main_time % 10) == 6) {
|
||||
top->clk = 0;
|
||||
}
|
||||
top->eval();
|
||||
main_time++;
|
||||
#ifdef VCD_TRACE
|
||||
tfp->dump(main_time);
|
||||
#endif // #ifdef VCD_TRACE
|
||||
}
|
||||
top->final();
|
||||
#ifdef VCD_TRACE
|
||||
tfp->close();
|
||||
#endif // #ifdef VCD_TRACE
|
||||
delete top;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user