Init
This commit is contained in:
24
sim/tests/common/LICENSE
Normal file
24
sim/tests/common/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2015, The Regents of the University of California (Regents).
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the Regents nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
47
sim/tests/common/common.mk
Normal file
47
sim/tests/common/common.mk
Normal file
@@ -0,0 +1,47 @@
|
||||
ADD_ASM_MACRO ?= -D__ASSEMBLY__=1
|
||||
|
||||
FLAGS = -O3 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las $(ADD_FLAGS)
|
||||
FLAGS_STR = "$(FLAGS)"
|
||||
|
||||
CFLAGS_COMMON = -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=$(TCM)
|
||||
CFLAGS_ARCH = -Wa,-march=rv32$(ARCH)_zicsr_zifencei -march=rv32$(ARCH)_zicsr_zifencei -mabi=$(ABI)
|
||||
|
||||
CFLAGS := $(FLAGS) $(EXT_CFLAGS) \
|
||||
$(CFLAGS_COMMON) \
|
||||
$(CFLAGS_ARCH) \
|
||||
-DFLAGS_STR=\"$(FLAGS_STR)\" \
|
||||
$(ADD_CFLAGS)
|
||||
|
||||
LDFLAGS ?= -nostartfiles -nostdlib -lc -lgcc -march=rv32$(ARCH)_zicsr_zifencei -mabi=$(ABI) --specs=nano.specs $(ADD_LDFLAGS)
|
||||
|
||||
ifeq (,$(findstring 0,$(TCM)))
|
||||
ld_script ?= $(inc_dir)/link_tcm.ld
|
||||
asm_src ?= crt_tcm.S
|
||||
else
|
||||
ld_script ?= $(inc_dir)/link.ld
|
||||
asm_src ?= crt.S
|
||||
endif
|
||||
|
||||
#this is optional assembly files from project
|
||||
asm_src += $(asm_src_in_project)
|
||||
|
||||
VPATH += $(src_dir) $(inc_dir) $(ADD_VPATH)
|
||||
incs += -I$(src_dir) -I$(inc_dir) $(ADD_incs)
|
||||
|
||||
c_objs := $(addprefix $(bld_dir)/,$(patsubst %.c, %.o, $(c_src)))
|
||||
asm_objs := $(addprefix $(bld_dir)/,$(patsubst %.S, %.o, $(asm_src)))
|
||||
|
||||
$(bld_dir)/%.o: %.S
|
||||
$(RISCV_GCC) $(CFLAGS) $(ADD_ASM_MACRO) -c $(incs) $< -o $@
|
||||
|
||||
$(bld_dir)/%.o: %.c
|
||||
$(RISCV_GCC) $(CFLAGS) -c $(incs) $< -o $@
|
||||
|
||||
$(bld_dir)/%.elf: $(ld_script) $(c_objs) $(asm_objs)
|
||||
$(RISCV_GCC) -o $@ -T $^ $(LDFLAGS)
|
||||
|
||||
$(bld_dir)/%.hex: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJCOPY) $^ $@
|
||||
|
||||
$(bld_dir)/%.dump: $(bld_dir)/%.elf
|
||||
$(RISCV_OBJDUMP) -D -w -x -S $^ > $@
|
||||
146
sim/tests/common/crt.S
Normal file
146
sim/tests/common/crt.S
Normal file
@@ -0,0 +1,146 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <crt.S>
|
||||
///
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
# define LREG lw
|
||||
# define SREG sw
|
||||
# define REGBYTES 4
|
||||
|
||||
.globl _start
|
||||
.globl main
|
||||
.globl trap_entry
|
||||
.globl handle_trap
|
||||
.globl sc_exit
|
||||
.weak trap_entry, handle_trap
|
||||
|
||||
.text
|
||||
.org (64*3)
|
||||
.balign 64
|
||||
machine_trap_entry:
|
||||
j trap_entry
|
||||
|
||||
.balign 64
|
||||
|
||||
_start:
|
||||
#ifndef __RVE_EXT
|
||||
zero_int_regs 1, 31
|
||||
#else
|
||||
zero_int_regs 1, 15
|
||||
#endif
|
||||
# Global pointer init
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
# clear bss
|
||||
la a1, __BSS_START__
|
||||
la a2, __BSS_END__
|
||||
j 4f
|
||||
3: sw zero, 0(a1)
|
||||
add a1, a1, 4
|
||||
4: bne a1, a2, 3b
|
||||
la sp, __C_STACK_TOP__
|
||||
|
||||
// Timer init
|
||||
li t0, mtime_ctrl
|
||||
li t1, (1 << SCR1_MTIME_CTRL_EN) // enable, use internal clock
|
||||
sw t1, (t0)
|
||||
li t0, mtime_div
|
||||
li t1, (100-1) // divide by 100
|
||||
sw t1, (t0)
|
||||
li t0, mtimecmp
|
||||
li t1, -1
|
||||
sw t1, (t0) // max value for mtimecmp
|
||||
sw t1, 4(t0)
|
||||
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
call main
|
||||
tail sc_exit
|
||||
|
||||
trap_entry:
|
||||
addi sp, sp, -272
|
||||
|
||||
SREG x1, 1*REGBYTES(sp)
|
||||
SREG x2, 2*REGBYTES(sp)
|
||||
SREG x3, 3*REGBYTES(sp)
|
||||
SREG x4, 4*REGBYTES(sp)
|
||||
SREG x5, 5*REGBYTES(sp)
|
||||
SREG x6, 6*REGBYTES(sp)
|
||||
SREG x7, 7*REGBYTES(sp)
|
||||
SREG x8, 8*REGBYTES(sp)
|
||||
SREG x9, 9*REGBYTES(sp)
|
||||
SREG x10, 10*REGBYTES(sp)
|
||||
SREG x11, 11*REGBYTES(sp)
|
||||
SREG x12, 12*REGBYTES(sp)
|
||||
SREG x13, 13*REGBYTES(sp)
|
||||
SREG x14, 14*REGBYTES(sp)
|
||||
SREG x15, 15*REGBYTES(sp)
|
||||
#ifndef __RVE_EXT
|
||||
SREG x16, 16*REGBYTES(sp)
|
||||
SREG x17, 17*REGBYTES(sp)
|
||||
SREG x18, 18*REGBYTES(sp)
|
||||
SREG x19, 19*REGBYTES(sp)
|
||||
SREG x20, 20*REGBYTES(sp)
|
||||
SREG x21, 21*REGBYTES(sp)
|
||||
SREG x22, 22*REGBYTES(sp)
|
||||
SREG x23, 23*REGBYTES(sp)
|
||||
SREG x24, 24*REGBYTES(sp)
|
||||
SREG x25, 25*REGBYTES(sp)
|
||||
SREG x26, 26*REGBYTES(sp)
|
||||
SREG x27, 27*REGBYTES(sp)
|
||||
SREG x28, 28*REGBYTES(sp)
|
||||
SREG x29, 29*REGBYTES(sp)
|
||||
SREG x30, 30*REGBYTES(sp)
|
||||
SREG x31, 31*REGBYTES(sp)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
|
||||
LREG x1, 1*REGBYTES(sp)
|
||||
LREG x2, 2*REGBYTES(sp)
|
||||
LREG x3, 3*REGBYTES(sp)
|
||||
LREG x4, 4*REGBYTES(sp)
|
||||
LREG x5, 5*REGBYTES(sp)
|
||||
LREG x6, 6*REGBYTES(sp)
|
||||
LREG x7, 7*REGBYTES(sp)
|
||||
LREG x8, 8*REGBYTES(sp)
|
||||
LREG x9, 9*REGBYTES(sp)
|
||||
LREG x10, 10*REGBYTES(sp)
|
||||
LREG x11, 11*REGBYTES(sp)
|
||||
LREG x12, 12*REGBYTES(sp)
|
||||
LREG x13, 13*REGBYTES(sp)
|
||||
LREG x14, 14*REGBYTES(sp)
|
||||
LREG x15, 15*REGBYTES(sp)
|
||||
#ifndef __RVE_EXT
|
||||
LREG x16, 16*REGBYTES(sp)
|
||||
LREG x17, 17*REGBYTES(sp)
|
||||
LREG x18, 18*REGBYTES(sp)
|
||||
LREG x19, 19*REGBYTES(sp)
|
||||
LREG x20, 20*REGBYTES(sp)
|
||||
LREG x21, 21*REGBYTES(sp)
|
||||
LREG x22, 22*REGBYTES(sp)
|
||||
LREG x23, 23*REGBYTES(sp)
|
||||
LREG x24, 24*REGBYTES(sp)
|
||||
LREG x25, 25*REGBYTES(sp)
|
||||
LREG x26, 26*REGBYTES(sp)
|
||||
LREG x27, 27*REGBYTES(sp)
|
||||
LREG x28, 28*REGBYTES(sp)
|
||||
LREG x29, 29*REGBYTES(sp)
|
||||
LREG x30, 30*REGBYTES(sp)
|
||||
LREG x31, 31*REGBYTES(sp)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
addi sp, sp, 272
|
||||
mret
|
||||
|
||||
handle_trap:
|
||||
j SIM_EXIT
|
||||
|
||||
// end of crt.S
|
||||
155
sim/tests/common/crt_tcm.S
Normal file
155
sim/tests/common/crt_tcm.S
Normal file
@@ -0,0 +1,155 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <crt_tcm.S>
|
||||
///
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "reloc.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
# define LREG lw
|
||||
# define SREG sw
|
||||
# define REGBYTES 4
|
||||
|
||||
.globl _start
|
||||
.globl main
|
||||
.globl trap_entry
|
||||
.globl handle_trap
|
||||
.globl sc_exit
|
||||
.weak trap_entry, handle_trap
|
||||
|
||||
.section .text.init
|
||||
.org (64*3)
|
||||
.align 6;
|
||||
machine_trap_entry:
|
||||
j trap_entry
|
||||
|
||||
.align 6
|
||||
_start:
|
||||
#ifndef __RVE_EXT
|
||||
zero_int_regs 1, 31
|
||||
#else
|
||||
zero_int_regs 1, 15
|
||||
#endif
|
||||
# Global pointer init
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
RELOC_PROC;
|
||||
|
||||
// init tdata
|
||||
mv a1, tp
|
||||
la a2, _tdata_end
|
||||
j 6f
|
||||
5: lw a3, 0(a0)
|
||||
sw a3, 0(a1)
|
||||
add a0, a0, 4
|
||||
add a1, a1, 4
|
||||
6: bne a0, a2, 5b
|
||||
// clear tbss
|
||||
j 8f
|
||||
7: sw zero, 0(a1)
|
||||
add a1, a1, 4
|
||||
8: bne a1, a4, 7b
|
||||
|
||||
// Timer init
|
||||
li t0, mtime_ctrl
|
||||
li t1, (1 << SCR1_MTIME_CTRL_EN) // enable, use internal clock
|
||||
sw t1, (t0)
|
||||
li t0, mtime_div
|
||||
li t1, (100-1) // divide by 100
|
||||
sw t1, (t0)
|
||||
li t0, mtimecmp
|
||||
li t1, -1
|
||||
sw t1, (t0) // max value for mtimecmp
|
||||
sw t1, 4(t0)
|
||||
|
||||
li a0, 0
|
||||
li a1, 0
|
||||
call main
|
||||
tail sc_exit
|
||||
|
||||
trap_entry:
|
||||
addi sp, sp, -272
|
||||
|
||||
SREG x1, 1*REGBYTES(sp)
|
||||
SREG x2, 2*REGBYTES(sp)
|
||||
SREG x3, 3*REGBYTES(sp)
|
||||
SREG x4, 4*REGBYTES(sp)
|
||||
SREG x5, 5*REGBYTES(sp)
|
||||
SREG x6, 6*REGBYTES(sp)
|
||||
SREG x7, 7*REGBYTES(sp)
|
||||
SREG x8, 8*REGBYTES(sp)
|
||||
SREG x9, 9*REGBYTES(sp)
|
||||
SREG x10, 10*REGBYTES(sp)
|
||||
SREG x11, 11*REGBYTES(sp)
|
||||
SREG x12, 12*REGBYTES(sp)
|
||||
SREG x13, 13*REGBYTES(sp)
|
||||
SREG x14, 14*REGBYTES(sp)
|
||||
SREG x15, 15*REGBYTES(sp)
|
||||
#ifndef __RVE_EXT
|
||||
SREG x16, 16*REGBYTES(sp)
|
||||
SREG x17, 17*REGBYTES(sp)
|
||||
SREG x18, 18*REGBYTES(sp)
|
||||
SREG x19, 19*REGBYTES(sp)
|
||||
SREG x20, 20*REGBYTES(sp)
|
||||
SREG x21, 21*REGBYTES(sp)
|
||||
SREG x22, 22*REGBYTES(sp)
|
||||
SREG x23, 23*REGBYTES(sp)
|
||||
SREG x24, 24*REGBYTES(sp)
|
||||
SREG x25, 25*REGBYTES(sp)
|
||||
SREG x26, 26*REGBYTES(sp)
|
||||
SREG x27, 27*REGBYTES(sp)
|
||||
SREG x28, 28*REGBYTES(sp)
|
||||
SREG x29, 29*REGBYTES(sp)
|
||||
SREG x30, 30*REGBYTES(sp)
|
||||
SREG x31, 31*REGBYTES(sp)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
call handle_trap
|
||||
|
||||
LREG x1, 1*REGBYTES(sp)
|
||||
LREG x2, 2*REGBYTES(sp)
|
||||
LREG x3, 3*REGBYTES(sp)
|
||||
LREG x4, 4*REGBYTES(sp)
|
||||
LREG x5, 5*REGBYTES(sp)
|
||||
LREG x6, 6*REGBYTES(sp)
|
||||
LREG x7, 7*REGBYTES(sp)
|
||||
LREG x8, 8*REGBYTES(sp)
|
||||
LREG x9, 9*REGBYTES(sp)
|
||||
LREG x10, 10*REGBYTES(sp)
|
||||
LREG x11, 11*REGBYTES(sp)
|
||||
LREG x12, 12*REGBYTES(sp)
|
||||
LREG x13, 13*REGBYTES(sp)
|
||||
LREG x14, 14*REGBYTES(sp)
|
||||
LREG x15, 15*REGBYTES(sp)
|
||||
#ifndef __RVE_EXT
|
||||
LREG x16, 16*REGBYTES(sp)
|
||||
LREG x17, 17*REGBYTES(sp)
|
||||
LREG x18, 18*REGBYTES(sp)
|
||||
LREG x19, 19*REGBYTES(sp)
|
||||
LREG x20, 20*REGBYTES(sp)
|
||||
LREG x21, 21*REGBYTES(sp)
|
||||
LREG x22, 22*REGBYTES(sp)
|
||||
LREG x23, 23*REGBYTES(sp)
|
||||
LREG x24, 24*REGBYTES(sp)
|
||||
LREG x25, 25*REGBYTES(sp)
|
||||
LREG x26, 26*REGBYTES(sp)
|
||||
LREG x27, 27*REGBYTES(sp)
|
||||
LREG x28, 28*REGBYTES(sp)
|
||||
LREG x29, 29*REGBYTES(sp)
|
||||
LREG x30, 30*REGBYTES(sp)
|
||||
LREG x31, 31*REGBYTES(sp)
|
||||
#endif // __RVE_EXT
|
||||
|
||||
addi sp, sp, 272
|
||||
mret
|
||||
|
||||
handle_trap:
|
||||
j SIM_EXIT
|
||||
|
||||
// end of crt.S
|
||||
113
sim/tests/common/csr.h
Normal file
113
sim/tests/common/csr.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <csr.h>
|
||||
/// Architecture specific CSR's defs and inlines
|
||||
|
||||
#ifndef SCR_CSR_H
|
||||
#define SCR_CSR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __xstringify(s) __stringify(s)
|
||||
#define __stringify(s) #s
|
||||
|
||||
#ifdef read_csr
|
||||
#undef read_csr
|
||||
#endif
|
||||
|
||||
#ifdef write_csr
|
||||
#undef write_csr
|
||||
#endif
|
||||
|
||||
#ifdef swap_csr
|
||||
#undef swap_csr
|
||||
#endif
|
||||
|
||||
#ifdef set_csr
|
||||
#undef set_csr
|
||||
#endif
|
||||
|
||||
#ifdef clear_csr
|
||||
#undef clear_csr
|
||||
#endif
|
||||
|
||||
#ifdef rdtime
|
||||
#undef rdtime
|
||||
#endif
|
||||
|
||||
#ifdef rdcycle
|
||||
#undef rdcycle
|
||||
#endif
|
||||
|
||||
#ifdef rdinstret
|
||||
#undef rdinstret
|
||||
#endif
|
||||
|
||||
#define read_csr(reg) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " __xstringify(reg) : "=r"(__tmp)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define write_csr(reg, val) \
|
||||
do { \
|
||||
if (__builtin_constant_p(val) && (val) == 0) \
|
||||
asm volatile ("csrw " __xstringify(reg) ", zero" ::); \
|
||||
else if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " __xstringify(reg) ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " __xstringify(reg) ", %0" :: "r"(val)); \
|
||||
} while (0)
|
||||
|
||||
#define swap_csr(reg, val) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(val) && (val) == 0) \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", zero" : "=r"(__tmp) :); \
|
||||
else if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrrw %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(val)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define set_csr(reg, bit) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (bit) < 32) \
|
||||
asm volatile ("csrrs %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define clear_csr(reg, bit) \
|
||||
({ \
|
||||
unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (bit) < 32) \
|
||||
asm volatile ("csrrc %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc %0, " __xstringify(reg) ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; \
|
||||
})
|
||||
|
||||
#define rdtime() read_csr(time)
|
||||
#define rdcycle() read_csr(cycle)
|
||||
#define rdinstret() read_csr(instret)
|
||||
|
||||
static inline unsigned long __attribute__((const)) hartid()
|
||||
{
|
||||
unsigned long res;
|
||||
asm ("csrr %0, mhartid" : "=r"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline unsigned long __attribute__((const)) impid()
|
||||
{
|
||||
unsigned long res;
|
||||
asm ("csrr %0, mimpid" : "=r"(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // SCR_CSR_H
|
||||
99
sim/tests/common/link.ld
Normal file
99
sim/tests/common/link.ld
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
* @file <link.ld>
|
||||
* @brief bare metal tests' linker script
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 64K
|
||||
}
|
||||
|
||||
STACK_SIZE = 1024;
|
||||
|
||||
CL_SIZE = 32;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* code segment */
|
||||
.text.init 0 : {
|
||||
FILL(0);
|
||||
. = 0x100 - 12;
|
||||
SIM_EXIT = .;
|
||||
LONG(0x13);
|
||||
SIM_STOP = .;
|
||||
LONG(0x6F);
|
||||
LONG(-1);
|
||||
. = 0x100;
|
||||
PROVIDE(__TEXT_START__ = .);
|
||||
*(.text.init)
|
||||
} >RAM
|
||||
|
||||
.text : {
|
||||
*crt.o(.text .text.*)
|
||||
*(.text .text.*)
|
||||
*(sc_test_section)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__TEXT_END__ = .);
|
||||
} >RAM
|
||||
|
||||
/* data segment */
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
.sdata : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
/* thread-local data segment */
|
||||
.tdata : {
|
||||
PROVIDE(_tls_data = .);
|
||||
PROVIDE(_tdata_begin = .);
|
||||
*(.tdata .tdata.*)
|
||||
PROVIDE(_tdata_end = .);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
.tbss : {
|
||||
PROVIDE(__BSS_START__ = .);
|
||||
*(.tbss .tbss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(_tbss_end = .);
|
||||
} >RAM
|
||||
|
||||
/* bss segment */
|
||||
.sbss : {
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
} >RAM
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__BSS_END__ = .);
|
||||
} >RAM
|
||||
|
||||
_end = .;
|
||||
PROVIDE(__end = .);
|
||||
|
||||
/* End of uninitalized data segement */
|
||||
|
||||
.stack ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE : {
|
||||
FILL(0);
|
||||
PROVIDE(__STACK_START__ = .);
|
||||
. += STACK_SIZE;
|
||||
PROVIDE(__C_STACK_TOP__ = .);
|
||||
PROVIDE(__STACK_END__ = .);
|
||||
} >RAM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
||||
115
sim/tests/common/link_tcm.ld
Normal file
115
sim/tests/common/link_tcm.ld
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
* @file <link.ld>
|
||||
* @brief bare metal tests' linker script
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
RAM (rwx) : ORIGIN = 0x0, LENGTH = 64K
|
||||
TCM (rwx) : ORIGIN = 0x00480000, LENGTH = 64K
|
||||
}
|
||||
|
||||
STACK_SIZE = 1024;
|
||||
|
||||
CL_SIZE = 32;
|
||||
|
||||
SECTIONS {
|
||||
|
||||
/* code segment */
|
||||
.text.init ORIGIN(RAM) : {
|
||||
FILL(0);
|
||||
. = 0x100 - 12;
|
||||
SIM_EXIT = .;
|
||||
LONG(0x13);
|
||||
SIM_STOP = .;
|
||||
LONG(0x6F);
|
||||
LONG(-1);
|
||||
. = 0x100;
|
||||
*crt_tcm.o(.text .text.*)
|
||||
*(.text.init)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >RAM
|
||||
|
||||
__reloc_start = .;
|
||||
|
||||
.text : {
|
||||
PROVIDE(__TEXT_START__ = .);
|
||||
*(.text .text.*)
|
||||
*(sc_test_section)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__TEXT_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.rodata ALIGN(CL_SIZE) : {
|
||||
__global_pointer$ = . + 0x800;
|
||||
*(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
LONG(0x13);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
|
||||
/* data segment */
|
||||
.data ALIGN(CL_SIZE) : {
|
||||
PROVIDE(__DATA_START__ = .);
|
||||
*(.data .data.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
|
||||
.sdata ALIGN(CL_SIZE) : {
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__DATA_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
/* thread-local data segment */
|
||||
.tdata ALIGN(CL_SIZE) : {
|
||||
PROVIDE(_tls_data = .);
|
||||
PROVIDE(_tdata_begin = .);
|
||||
*(.tdata .tdata.*)
|
||||
PROVIDE(_tdata_end = .);
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.tbss ALIGN(CL_SIZE) : {
|
||||
PROVIDE(_tbss_begin = .);
|
||||
*(.tbss .tbss.*)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(_tbss_end = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
/* bss segment */
|
||||
.sbss ALIGN(CL_SIZE) : {
|
||||
PROVIDE(__BSS_START__ = .);
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
. = ALIGN(CL_SIZE);
|
||||
} >TCM AT>RAM
|
||||
|
||||
.bss ALIGN(CL_SIZE) : {
|
||||
*(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)
|
||||
. = ALIGN(CL_SIZE);
|
||||
PROVIDE(__BSS_END__ = .);
|
||||
} >TCM AT>RAM
|
||||
|
||||
_end = .;
|
||||
PROVIDE(__end = .);
|
||||
|
||||
/* End of uninitalized data segement */
|
||||
|
||||
.stack ORIGIN(TCM) + LENGTH(TCM) - STACK_SIZE : {
|
||||
PROVIDE(__STACK_START__ = .);
|
||||
. += STACK_SIZE;
|
||||
PROVIDE(__C_STACK_TOP__ = .);
|
||||
PROVIDE(__STACK_END__ = .);
|
||||
} >TCM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame .eh_frame.*)
|
||||
}
|
||||
}
|
||||
37
sim/tests/common/reloc.h
Normal file
37
sim/tests/common/reloc.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef RELOC_H
|
||||
#define RELOC_H
|
||||
|
||||
#if (TCM == 1)
|
||||
#define RELOC_PROC \
|
||||
la a0, __reloc_start; \
|
||||
la a1, __TEXT_START__; \
|
||||
la a2, __DATA_END__; \
|
||||
beq a0, a1, 21f; \
|
||||
j 2f; \
|
||||
1: lw a3, 0(a0); \
|
||||
sw a3, 0(a1); \
|
||||
add a0, a0, 4; \
|
||||
add a1, a1, 4; \
|
||||
2: bne a1, a2, 1b; \
|
||||
/* clear bss */ \
|
||||
la a2, __BSS_START__; \
|
||||
21: la a1, __BSS_END__; \
|
||||
j 4f; \
|
||||
3: sw zero, 0(a2); \
|
||||
add a2, a2, 4; \
|
||||
4: bne a1, a2, 3b; \
|
||||
/* init stack */ \
|
||||
la sp, __C_STACK_TOP__; \
|
||||
/* init hart0 TLS */ \
|
||||
la a0, _tdata_begin; \
|
||||
la a2, _tbss_end; \
|
||||
sub a1, a2, a0; \
|
||||
la a4, __STACK_START__; \
|
||||
sub tp, a4, a1;
|
||||
#else // #if TCM
|
||||
|
||||
#define RELOC_PROC
|
||||
|
||||
#endif // #else #if TCM
|
||||
|
||||
#endif //
|
||||
1473
sim/tests/common/riscv_csr_encoding.h
Normal file
1473
sim/tests/common/riscv_csr_encoding.h
Normal file
File diff suppressed because it is too large
Load Diff
819
sim/tests/common/riscv_macros.h
Normal file
819
sim/tests/common/riscv_macros.h
Normal file
@@ -0,0 +1,819 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef __RISCV_MACROS_H
|
||||
#define __RISCV_MACROS_H
|
||||
|
||||
#include "riscv_csr_encoding.h"
|
||||
#include "sc_test.h"
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Begin Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_RV64U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32U \
|
||||
.macro init; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32UF \
|
||||
.macro init; \
|
||||
RVTEST_FP_ENABLE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV64S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32M \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_MACHINE; \
|
||||
.endm
|
||||
|
||||
#define RVTEST_RV32S \
|
||||
.macro init; \
|
||||
RVTEST_ENABLE_SUPERVISOR; \
|
||||
.endm
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bgez a0, 1f; RVTEST_PASS; 1:
|
||||
#else
|
||||
# define CHECK_XLEN li a0, 1; slli a0, a0, 31; bltz a0, 1f; RVTEST_PASS; 1:
|
||||
#endif
|
||||
|
||||
#define INIT_PMP \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
li t0, -1; /* Set up a PMP to permit all accesses */ \
|
||||
csrw pmpaddr0, t0; \
|
||||
li t0, PMP_NAPOT | PMP_R | PMP_W | PMP_X; \
|
||||
csrw pmpcfg0, t0; \
|
||||
.balign 4; \
|
||||
1:
|
||||
|
||||
#define INIT_SPTBR \
|
||||
la t0, 1f; \
|
||||
csrw mtvec, t0; \
|
||||
csrwi sptbr, 0; \
|
||||
.balign 4; \
|
||||
1:
|
||||
|
||||
#define DELEGATE_NO_TRAPS
|
||||
|
||||
#define RVTEST_ENABLE_SUPERVISOR \
|
||||
li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
li a0, SIP_SSIP | SIP_STIP; \
|
||||
csrs mideleg, a0; \
|
||||
|
||||
#define RVTEST_ENABLE_MACHINE \
|
||||
li a0, MSTATUS_MPP; \
|
||||
csrs mstatus, a0; \
|
||||
|
||||
#define RVTEST_FP_ENABLE \
|
||||
li a0, MSTATUS_FS & (MSTATUS_FS >> 1); \
|
||||
csrs mstatus, a0; \
|
||||
csrwi fcsr, 0
|
||||
|
||||
#define RISCV_MULTICORE_DISABLE \
|
||||
csrr a0, mhartid; \
|
||||
1: bnez a0, 1b
|
||||
|
||||
#define EXTRA_TVEC_USER
|
||||
#define EXTRA_TVEC_SUPERVISOR
|
||||
#define EXTRA_TVEC_HYPERVISOR
|
||||
#define EXTRA_TVEC_MACHINE
|
||||
#define EXTRA_INIT
|
||||
#define EXTRA_INIT_TIMER
|
||||
|
||||
#define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */
|
||||
|
||||
#define RVTEST_CODE_BEGIN \
|
||||
.section .text.init; \
|
||||
.org 0xC0, 0x00; \
|
||||
.balign 64; \
|
||||
.weak stvec_handler; \
|
||||
.weak mtvec_handler; \
|
||||
trap_vector: \
|
||||
/* test whether the test came from pass/fail */ \
|
||||
csrr a4, mcause; \
|
||||
li a5, CAUSE_USER_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
li a5, CAUSE_SUPERVISOR_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
li a5, CAUSE_MACHINE_ECALL; \
|
||||
beq a4, a5, _report; \
|
||||
/* if an mtvec_handler is defined, jump to it */ \
|
||||
la a4, mtvec_handler; \
|
||||
beqz a4, 1f; \
|
||||
jr a4; \
|
||||
/* was it an interrupt or an exception? */ \
|
||||
1: csrr a4, mcause; \
|
||||
bgez a4, handle_exception; \
|
||||
INTERRUPT_HANDLER; \
|
||||
handle_exception: \
|
||||
/* we don't know how to handle whatever the exception was */ \
|
||||
other_exception: \
|
||||
/* some unhandlable exception occurred */ \
|
||||
li a0, 0x1; \
|
||||
_report: \
|
||||
j sc_exit; \
|
||||
.balign 64; \
|
||||
.globl _start; \
|
||||
_start: \
|
||||
RISCV_MULTICORE_DISABLE; \
|
||||
/*INIT_SPTBR;*/ \
|
||||
/*INIT_PMP;*/ \
|
||||
DELEGATE_NO_TRAPS; \
|
||||
li TESTNUM, 0; \
|
||||
la t0, trap_vector; \
|
||||
csrw mtvec, t0; \
|
||||
CHECK_XLEN; \
|
||||
/* if an stvec_handler is defined, delegate exceptions to it */ \
|
||||
la t0, stvec_handler; \
|
||||
beqz t0, 1f; \
|
||||
csrw stvec, t0; \
|
||||
li t0, (1 << CAUSE_LOAD_PAGE_FAULT) | \
|
||||
(1 << CAUSE_STORE_PAGE_FAULT) | \
|
||||
(1 << CAUSE_FETCH_PAGE_FAULT) | \
|
||||
(1 << CAUSE_MISALIGNED_FETCH) | \
|
||||
(1 << CAUSE_USER_ECALL) | \
|
||||
(1 << CAUSE_BREAKPOINT); \
|
||||
csrw medeleg, t0; \
|
||||
csrr t1, medeleg; \
|
||||
bne t0, t1, other_exception; \
|
||||
1: csrwi mstatus, 0; \
|
||||
init; \
|
||||
EXTRA_INIT; \
|
||||
EXTRA_INIT_TIMER; \
|
||||
la t0, _run_test; \
|
||||
csrw mepc, t0; \
|
||||
csrr a0, mhartid; \
|
||||
mret; \
|
||||
.section .text; \
|
||||
_run_test:
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// End Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_CODE_END ecall: ecall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Pass/Fail Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define RVTEST_PASS \
|
||||
fence; \
|
||||
mv a1, TESTNUM; \
|
||||
li a0, 0x0; \
|
||||
ecall
|
||||
|
||||
#define TESTNUM x28
|
||||
#define RVTEST_FAIL \
|
||||
fence; \
|
||||
mv a1, TESTNUM; \
|
||||
li a0, 0x1; \
|
||||
ecall
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Data Section Macro
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
#define EXTRA_DATA
|
||||
|
||||
#define RVTEST_DATA_BEGIN \
|
||||
EXTRA_DATA \
|
||||
.pushsection .tohost,"aw",@progbits; \
|
||||
.balign 64; .global tohost; tohost: .dword 0; \
|
||||
.balign 64; .global fromhost; fromhost: .dword 0; \
|
||||
.popsection; \
|
||||
.balign 16; \
|
||||
.global begin_regstate; begin_regstate: .dword 0; .dword 0; .dword 0; \
|
||||
.balign 16; \
|
||||
.global begin_signature; begin_signature:
|
||||
|
||||
#define RVTEST_DATA_END .balign 16; .global end_signature; end_signature:
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Helper macros
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define MASK_XLEN(x) ((x) & ((1 << (__riscv_xlen - 1) << 1) - 1))
|
||||
|
||||
#define TEST_CASE( testnum, testreg, correctval, code... ) \
|
||||
test_ ## testnum: \
|
||||
code; \
|
||||
li x29, MASK_XLEN(correctval); \
|
||||
li TESTNUM, testnum; \
|
||||
bne testreg, x29, fail;
|
||||
|
||||
# We use a macro hack to simpify code generation for various numbers
|
||||
# of bubble cycles.
|
||||
|
||||
#define TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_1 nop; TEST_INSERT_NOPS_0
|
||||
#define TEST_INSERT_NOPS_2 nop; TEST_INSERT_NOPS_1
|
||||
#define TEST_INSERT_NOPS_3 nop; TEST_INSERT_NOPS_2
|
||||
#define TEST_INSERT_NOPS_4 nop; TEST_INSERT_NOPS_3
|
||||
#define TEST_INSERT_NOPS_5 nop; TEST_INSERT_NOPS_4
|
||||
#define TEST_INSERT_NOPS_6 nop; TEST_INSERT_NOPS_5
|
||||
#define TEST_INSERT_NOPS_7 nop; TEST_INSERT_NOPS_6
|
||||
#define TEST_INSERT_NOPS_8 nop; TEST_INSERT_NOPS_7
|
||||
#define TEST_INSERT_NOPS_9 nop; TEST_INSERT_NOPS_8
|
||||
#define TEST_INSERT_NOPS_10 nop; TEST_INSERT_NOPS_9
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UI MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for instructions with immediate operand
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define SEXT_IMM(x) ((x) | (-(((x) >> 11) & 1) << 11))
|
||||
|
||||
#define TEST_IMM_OP( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_OP_RVC( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, val1; \
|
||||
inst x1, imm; \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x1, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_SRC1_BYPASS( testnum, nop_cycles, inst, result, val1, imm ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x3, x1, SEXT_IMM(imm); \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZEROSRC1( testnum, inst, result, imm ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
inst x1, x0, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#define TEST_IMM_ZERODEST( testnum, inst, val1, imm ) \
|
||||
TEST_CASE( testnum, x0, 0, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x0, x1, SEXT_IMM(imm); \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for vector config instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_VSETCFGIVL( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12); \
|
||||
vsetcfg x1,nxpr,nfpr; \
|
||||
li x1, vl; \
|
||||
vsetvl x1,x1; \
|
||||
)
|
||||
|
||||
#define TEST_VVCFG( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12) | (nfpr << 6) | nxpr; \
|
||||
vsetcfg x1; \
|
||||
li x1, vl; \
|
||||
vsetvl x1,x1; \
|
||||
)
|
||||
|
||||
#define TEST_VSETVL( testnum, nxpr, nfpr, bank, vl, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, (bank << 12); \
|
||||
vsetcfg x1,nxpr,nfpr; \
|
||||
li x1, vl; \
|
||||
vsetvl x1, x1; \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_R_OP( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, val1; \
|
||||
inst x3, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_SRC1_EQ_DEST( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, val1; \
|
||||
inst x1, x1; \
|
||||
)
|
||||
|
||||
#define TEST_R_DEST_BYPASS( testnum, nop_cycles, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
inst x3, x1; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for an instruction with register-register operands
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_RR_OP( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x3, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x1, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x2, x1, x2; \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC12_EQ_DEST( testnum, inst, result, val1 ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
inst x1, x1, x1; \
|
||||
)
|
||||
|
||||
#define TEST_RR_DEST_BYPASS( testnum, nop_cycles, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x6, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x3, x1, x2; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x3, x1, x2; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_RR_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, result, val1, val2 ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
li x4, 0; \
|
||||
1: li x2, MASK_XLEN(val2); \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x3, x1, x2; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC1( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, x0, x1; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
|
||||
TEST_CASE( testnum, x2, result, \
|
||||
li x1, MASK_XLEN(val); \
|
||||
inst x2, x1, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZEROSRC12( testnum, inst, result ) \
|
||||
TEST_CASE( testnum, x1, result, \
|
||||
inst x1, x0, x0; \
|
||||
)
|
||||
|
||||
#define TEST_RR_ZERODEST( testnum, inst, val1, val2 ) \
|
||||
TEST_CASE( testnum, x0, 0, \
|
||||
li x1, MASK_XLEN(val1); \
|
||||
li x2, MASK_XLEN(val2); \
|
||||
inst x0, x1, x2; \
|
||||
)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test memory instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_LD_OP( testnum, inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
la x1, base; \
|
||||
inst x3, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_ST_OP( testnum, load_inst, store_inst, result, offset, base ) \
|
||||
TEST_CASE( testnum, x3, result, \
|
||||
la x1, base; \
|
||||
li x2, result; \
|
||||
store_inst x2, offset(x1); \
|
||||
load_inst x3, offset(x1); \
|
||||
)
|
||||
|
||||
#define TEST_LD_DEST_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
inst x3, offset(x1); \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
addi x6, x3, 0; \
|
||||
li x29, result; \
|
||||
bne x6, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b; \
|
||||
|
||||
#define TEST_LD_SRC1_BYPASS( testnum, nop_cycles, inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x1, base; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x3, offset(x1); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC12_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x3, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_ST_SRC21_BYPASS( testnum, src1_nops, src2_nops, load_inst, store_inst, result, offset, base ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x2, base; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, result; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
store_inst x1, offset(x2); \
|
||||
load_inst x3, offset(x2); \
|
||||
li x29, result; \
|
||||
bne x3, x29, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test branch instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_BR1_OP_TAKEN( testnum, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
inst x1, 2f; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
1: bne x0, TESTNUM, 3f; \
|
||||
2: inst x1, 1b; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
3:
|
||||
|
||||
#define TEST_BR1_OP_NOTTAKEN( testnum, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
inst x1, 1f; \
|
||||
bne x0, TESTNUM, 2f; \
|
||||
1: bne x0, TESTNUM, fail; \
|
||||
2: inst x1, 1b; \
|
||||
3:
|
||||
|
||||
#define TEST_BR1_SRC1_BYPASS( testnum, nop_cycles, inst, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x1, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_OP_TAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 2f; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
1: bne x0, TESTNUM, 3f; \
|
||||
2: inst x1, x2, 1b; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_OP_NOTTAKEN( testnum, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x1, val1; \
|
||||
li x2, val2; \
|
||||
inst x1, x2, 1f; \
|
||||
bne x0, TESTNUM, 2f; \
|
||||
1: bne x0, TESTNUM, fail; \
|
||||
2: inst x1, x2, 1b; \
|
||||
3:
|
||||
|
||||
#define TEST_BR2_SRC12_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_BR2_SRC21_BYPASS( testnum, src1_nops, src2_nops, inst, val1, val2 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: li x2, val2; \
|
||||
TEST_INSERT_NOPS_ ## src1_nops \
|
||||
li x1, val1; \
|
||||
TEST_INSERT_NOPS_ ## src2_nops \
|
||||
inst x1, x2, fail; \
|
||||
addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test jump instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_JR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x6; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
#define TEST_JALR_SRC1_BYPASS( testnum, nop_cycles, inst ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
li x4, 0; \
|
||||
1: la x6, 2f; \
|
||||
TEST_INSERT_NOPS_ ## nop_cycles \
|
||||
inst x19, x6, 0; \
|
||||
bne x0, TESTNUM, fail; \
|
||||
2: addi x4, x4, 1; \
|
||||
li x5, 2; \
|
||||
bne x4, x5, 1b \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# RV64UF MACROS
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests floating-point instructions
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define qNaNf 0f:7fc00000
|
||||
#define sNaNf 0f:7f800001
|
||||
#define qNaN 0d:7ff8000000000000
|
||||
#define sNaN 0d:7ff0000000000001
|
||||
|
||||
#define TEST_FP_OP_S_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
flw f0, 0(a0); \
|
||||
flw f1, 4(a0); \
|
||||
flw f2, 8(a0); \
|
||||
lw a3, 12(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
j 2f; \
|
||||
.balign 4; \
|
||||
.data; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float val1; \
|
||||
.float val2; \
|
||||
.float val3; \
|
||||
.result; \
|
||||
.text; \
|
||||
2:
|
||||
|
||||
#define TEST_FP_OP_D_INTERNAL( testnum, flags, result, val1, val2, val3, code... ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
fld f0, 0(a0); \
|
||||
fld f1, 8(a0); \
|
||||
fld f2, 16(a0); \
|
||||
ld a3, 24(a0); \
|
||||
code; \
|
||||
fsflags a1, x0; \
|
||||
li a2, flags; \
|
||||
bne a0, a3, fail; \
|
||||
bne a1, a2, fail; \
|
||||
j 2f; \
|
||||
.data; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double val1; \
|
||||
.double val2; \
|
||||
.double val3; \
|
||||
.result; \
|
||||
.text; \
|
||||
2:
|
||||
|
||||
#define TEST_FCVT_S_D( testnum, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, 0, double result, val1, 0.0, 0.0, \
|
||||
fcvt.s.d f3, f0; fcvt.d.s f3, f3; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FCVT_D_S( testnum, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, 0, float result, val1, 0.0, 0.0, \
|
||||
fcvt.d.s f3, f0; fcvt.s.d f3, f3; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_S_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP1_D_DWORD_RESULT( testnum, inst, flags, result, val1 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst f3, f0; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP2_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, 0.0, \
|
||||
inst f3, f0, f1; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_S( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, float result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.s a0, f3)
|
||||
|
||||
#define TEST_FP_OP3_D( testnum, inst, flags, result, val1, val2, val3 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, double result, val1, val2, val3, \
|
||||
inst f3, f0, f1, f2; fmv.x.d a0, f3)
|
||||
|
||||
#define TEST_FP_INT_OP_S( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_INT_OP_D( testnum, inst, flags, result, val1, rm ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, 0.0, 0.0, \
|
||||
inst a0, f0, rm)
|
||||
|
||||
#define TEST_FP_CMP_OP_S( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_S_INTERNAL( testnum, flags, word result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FP_CMP_OP_D( testnum, inst, flags, result, val1, val2 ) \
|
||||
TEST_FP_OP_D_INTERNAL( testnum, flags, dword result, val1, val2, 0.0, \
|
||||
inst a0, f0, f1)
|
||||
|
||||
#define TEST_FCLASS_S(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.s.x fa0, a0; \
|
||||
fclass.s a0, fa0)
|
||||
|
||||
#define TEST_FCLASS_D(testnum, correct, input) \
|
||||
TEST_CASE(testnum, a0, correct, li a0, input; fmv.d.x fa0, a0; \
|
||||
fclass.d a0, fa0)
|
||||
|
||||
#define TEST_INT_FP_OP_S( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
lw a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.s a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
j 1f; \
|
||||
.balign 4; \
|
||||
test_ ## testnum ## _data: \
|
||||
.float result; \
|
||||
1:
|
||||
|
||||
#define TEST_INT_FP_OP_D( testnum, inst, result, val1 ) \
|
||||
test_ ## testnum: \
|
||||
li TESTNUM, testnum; \
|
||||
la a0, test_ ## testnum ## _data ;\
|
||||
ld a3, 0(a0); \
|
||||
li a0, val1; \
|
||||
inst f0, a0; \
|
||||
fsflags x0; \
|
||||
fmv.x.d a0, f0; \
|
||||
bne a0, a3, fail; \
|
||||
j 1f; \
|
||||
.balign 8; \
|
||||
test_ ## testnum ## _data: \
|
||||
.double result; \
|
||||
1:
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Pass and fail code (assumes test num is in TESTNUM)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_PASSFAIL \
|
||||
bne x0, TESTNUM, pass; \
|
||||
fail: \
|
||||
RVTEST_FAIL; \
|
||||
pass: \
|
||||
RVTEST_PASS \
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Test data section
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#define TEST_DATA
|
||||
|
||||
#endif
|
||||
|
||||
282
sim/tests/common/sc_print.c
Normal file
282
sim/tests/common/sc_print.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_print.c>
|
||||
///
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "sc_print.h"
|
||||
|
||||
#define SC_SIM_OUTPORT (0xf0000000)
|
||||
#define CHAR_BIT (8)
|
||||
|
||||
static void
|
||||
sc_puts(long str, long strlen) {
|
||||
volatile char *out_ptr = (volatile char*)SC_SIM_OUTPORT;
|
||||
const char *in_ptr = (const char*)str;
|
||||
for (long len = strlen; len > 0; --len)
|
||||
*out_ptr = *in_ptr++;
|
||||
}
|
||||
|
||||
#undef putchar
|
||||
int
|
||||
putchar(int ch) {
|
||||
static __thread char buf[64] __attribute__((aligned(64)));
|
||||
static __thread int buflen = 0;
|
||||
|
||||
buf[buflen++] = ch;
|
||||
|
||||
if ( ch == '\n' || buflen == sizeof(buf) ) {
|
||||
sc_puts((long)buf, buflen);
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
printf_putch(int ch, void** data)
|
||||
{
|
||||
putchar(ch);
|
||||
}
|
||||
|
||||
static void
|
||||
print(const char *str)
|
||||
{
|
||||
sc_puts((long)str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
static long long
|
||||
getint(va_list *ap, int lflag)
|
||||
{
|
||||
if ( lflag >= 2 )
|
||||
return va_arg(*ap, long long);
|
||||
else if ( lflag )
|
||||
return va_arg(*ap, long);
|
||||
else
|
||||
return va_arg(*ap, int);
|
||||
}
|
||||
|
||||
|
||||
static unsigned long long
|
||||
getuint(va_list *ap, int lflag)
|
||||
{
|
||||
if ( lflag >= 2 )
|
||||
return va_arg(*ap, unsigned long long);
|
||||
else if ( lflag )
|
||||
return va_arg(*ap, unsigned long);
|
||||
else
|
||||
return va_arg(*ap, unsigned int);
|
||||
}
|
||||
|
||||
static inline void
|
||||
printnum(void(*putch)(int, void**),
|
||||
void **putdat,
|
||||
unsigned long long num,
|
||||
unsigned base,
|
||||
int width,
|
||||
int padc,
|
||||
int hex_A)
|
||||
{
|
||||
unsigned digs[sizeof(num) * CHAR_BIT];
|
||||
int pos = 0;
|
||||
|
||||
for ( ;; ) {
|
||||
digs[pos++] = num % base;
|
||||
if ( num < base )
|
||||
break;
|
||||
num /= base;
|
||||
}
|
||||
|
||||
while ( width-- > pos )
|
||||
putch(padc, putdat);
|
||||
|
||||
while ( pos-- > 0 )
|
||||
putch(digs[pos] + (digs[pos] >= 10 ? hex_A - 10 : '0'), putdat);
|
||||
}
|
||||
|
||||
static void
|
||||
vprintfmt(void(*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
|
||||
{
|
||||
register const char* p;
|
||||
const char* last_fmt;
|
||||
register int ch;
|
||||
int err;
|
||||
unsigned long long num;
|
||||
int base;
|
||||
int lflag;
|
||||
int width;
|
||||
int precision;
|
||||
int altflag;
|
||||
char padc;
|
||||
int hex_A = 'a';
|
||||
for ( ;; ) {
|
||||
while ( (ch = *(unsigned char *)fmt) != '%' ) {
|
||||
if ( ch == '\0' )
|
||||
return;
|
||||
++fmt;
|
||||
putch(ch, putdat);
|
||||
}
|
||||
++fmt;
|
||||
|
||||
// Process a %-escape sequence
|
||||
last_fmt = fmt;
|
||||
padc = ' ';
|
||||
width = -1;
|
||||
precision = -1;
|
||||
lflag = 0;
|
||||
altflag = 0;
|
||||
|
||||
reswitch:
|
||||
switch ( ch = *(unsigned char *)fmt++ ) {
|
||||
// flag to pad on the right
|
||||
case '-':
|
||||
padc = '-';
|
||||
goto reswitch;
|
||||
|
||||
// flag to pad with 0's instead of spaces
|
||||
case '0':
|
||||
padc = '0';
|
||||
goto reswitch;
|
||||
|
||||
// width field
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
for ( precision = 0;; ++fmt ) {
|
||||
precision = precision * 10 + ch - '0';
|
||||
ch = *fmt;
|
||||
if ( ch < '0' || ch > '9' )
|
||||
break;
|
||||
}
|
||||
goto process_precision;
|
||||
|
||||
case '*':
|
||||
precision = va_arg(ap, int);
|
||||
goto process_precision;
|
||||
|
||||
case '.':
|
||||
if ( width < 0 )
|
||||
width = 0;
|
||||
goto reswitch;
|
||||
|
||||
case '#':
|
||||
altflag = 1;
|
||||
goto reswitch;
|
||||
|
||||
process_precision:
|
||||
if ( width < 0 ) {
|
||||
width = precision;
|
||||
precision = -1;
|
||||
}
|
||||
goto reswitch;
|
||||
|
||||
// long flag (doubled for long long)
|
||||
case 'l':
|
||||
lflag++;
|
||||
goto reswitch;
|
||||
|
||||
// character
|
||||
case 'c':
|
||||
putch(va_arg(ap, int), putdat);
|
||||
break;
|
||||
|
||||
// string
|
||||
case 's':
|
||||
if ( (p = va_arg(ap, char *)) == NULL )
|
||||
p = "(null)";
|
||||
if ( width > 0 && padc != '-' )
|
||||
for ( width -= strnlen(p, precision); width > 0; width-- )
|
||||
putch(padc, putdat);
|
||||
for ( ; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width-- ) {
|
||||
putch(ch, putdat);
|
||||
p++;
|
||||
}
|
||||
for ( ; width > 0; width-- )
|
||||
putch(' ', putdat);
|
||||
break;
|
||||
|
||||
// (signed) decimal
|
||||
case 'd':
|
||||
num = getint(&ap, lflag);
|
||||
if ( (long long)num < 0 ) {
|
||||
putch('-', putdat);
|
||||
num = -(long long)num;
|
||||
}
|
||||
base = 10;
|
||||
goto signed_number;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
// #ifndef nopfloat
|
||||
// double num = getdouble(&ap, lflag);
|
||||
// printdoubleF(putch, putdat, num, width, precision, padc);
|
||||
// #endif
|
||||
}
|
||||
break;
|
||||
|
||||
// unsigned decimal
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto unsigned_number;
|
||||
|
||||
// (unsigned) octal
|
||||
case 'o':
|
||||
// should do something with padding so it's always 3 octits
|
||||
base = 8;
|
||||
goto unsigned_number;
|
||||
|
||||
// pointer
|
||||
case 'p':
|
||||
// static_assert(sizeof(long) == sizeof(void*));
|
||||
lflag = 1;
|
||||
putch('0', putdat);
|
||||
putch('x', putdat);
|
||||
/* fall through to 'x' */
|
||||
|
||||
// (unsigned) hexadecimal
|
||||
case 'x':
|
||||
hex_A = 'a';
|
||||
base = 16;
|
||||
goto unsigned_number;
|
||||
|
||||
case 'X':
|
||||
hex_A = 'A';
|
||||
base = 16;
|
||||
unsigned_number:
|
||||
num = getuint(&ap, lflag);
|
||||
signed_number:
|
||||
printnum(putch, putdat, num, base, width, padc, hex_A);
|
||||
break;
|
||||
|
||||
// escaped '%' character
|
||||
case '%':
|
||||
putch(ch, putdat);
|
||||
break;
|
||||
|
||||
// unrecognized escape sequence - just print it literally
|
||||
default:
|
||||
putch('%', putdat);
|
||||
fmt = last_fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sc_printf(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vprintfmt(printf_putch, NULL, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
return 0; // incorrect return value, but who cares, anyway?
|
||||
}
|
||||
10
sim/tests/common/sc_print.h
Normal file
10
sim/tests/common/sc_print.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_print.h>
|
||||
///
|
||||
|
||||
#ifndef SC_PRINT_H
|
||||
#define SC_PRINT_H
|
||||
|
||||
extern int sc_printf(const char* fmt, ...);
|
||||
|
||||
#endif // SC_PRINT_H
|
||||
48
sim/tests/common/sc_test.h
Normal file
48
sim/tests/common/sc_test.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Copyright by Syntacore LLC © 2016, 2017. See LICENSE for details
|
||||
/// @file <sc_test.h>
|
||||
///
|
||||
|
||||
#ifndef SC_TEST_H
|
||||
#define SC_TEST_H
|
||||
|
||||
#if defined(__ASSEMBLER__)
|
||||
.altmacro
|
||||
|
||||
.macro zero_int_reg regn
|
||||
mv x\regn, zero
|
||||
.endm
|
||||
|
||||
.macro zero_int_regs reg_first, reg_last
|
||||
.set regn, \reg_first
|
||||
.rept \reg_last - \reg_first + 1
|
||||
zero_int_reg %(regn)
|
||||
.set regn, regn+1
|
||||
.endr
|
||||
.endm
|
||||
|
||||
#define report_results(result) \
|
||||
li a0, result; \
|
||||
la t0, sc_exit; \
|
||||
jr t0;
|
||||
|
||||
.pushsection sc_test_section, "ax"
|
||||
sc_exit: la t0, SIM_EXIT; jr t0;
|
||||
.balign 32
|
||||
.popsection
|
||||
#define sc_pass report_results(0x0)
|
||||
#define sc_fail report_results(0x1)
|
||||
|
||||
#else
|
||||
|
||||
extern void sc_exit(unsigned result, unsigned res0, unsigned res1, unsigned res2, unsigned res3)
|
||||
__attribute__ ((noinline, noreturn));
|
||||
|
||||
static inline void __attribute__ ((noreturn))
|
||||
report_results(unsigned result, unsigned res0, unsigned res1, unsigned res2, unsigned res3)
|
||||
{
|
||||
sc_exit(result, res0, res1, res2, res3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // SC_TEST_H
|
||||
20
sim/tests/common/scr1_specific.h
Normal file
20
sim/tests/common/scr1_specific.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __SCR1__SPECIFIC
|
||||
#define __SCR1__SPECIFIC
|
||||
|
||||
#define mcounten 0x7E0
|
||||
|
||||
// Memory-mapped registers
|
||||
#define mtime_ctrl 0x00490000
|
||||
#define mtime_div 0x00490004
|
||||
#define mtime 0x00490008
|
||||
#define mtimeh 0x0049000C
|
||||
#define mtimecmp 0x00490010
|
||||
#define mtimecmph 0x00490014
|
||||
|
||||
#define SCR1_MTIME_CTRL_EN 0
|
||||
#define SCR1_MTIME_CTRL_CLKSRC 1
|
||||
|
||||
#define SCR1_MTIME_CTRL_WR_MASK 0x3
|
||||
#define SCR1_MTIME_DIV_WR_MASK 0x3FF
|
||||
|
||||
#endif // _SCR1__SPECIFIC
|
||||
Reference in New Issue
Block a user