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

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