This commit is contained in:
Mikhail Yenuchenko
2026-01-20 16:23:00 +03:00
commit c8ab0ca4f7
107 changed files with 285173 additions and 0 deletions

138
sim/Makefile Normal file
View 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;

View 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

View 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); */
}

View 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 */

View 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

View 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();
}

View 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

View 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
View 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.

View 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
View 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
View 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
View 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
View 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.*)
}
}

View 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
View 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 //

File diff suppressed because it is too large Load Diff

View 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
View 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?
}

View 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

View 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

View 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
View 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
View File

@@ -0,0 +1,7 @@
#include "sc_print.h"
int main()
{
sc_printf("Hello from SCR1!\n");
return 0;
}

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -0,0 +1,7 @@
#ifndef _RISCV_TEST_H
#define _RISCV_TEST_H
#include "test_macros.h"
#endif

View 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)

View 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

View 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

View File

@@ -0,0 +1,6 @@
#ifndef __RISCV__TEST__H
#define __RISCV__TEST__H
#include "riscv_macros.h"
#endif // #ifndef __RISCV__TEST__H

View 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)))

View File

@@ -0,0 +1,7 @@
#ifndef __TEST__MACROS__H
#define __TEST__MACROS__H
#define sptbr satp
#define mbadaddr mtval
#endif

View 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;
}

View 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;
}