Initial import

This commit is contained in:
Clifford Wolf 2015-06-06 14:01:37 +02:00
commit 77ba5a1897
60 changed files with 6250 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
firmware/firmware.bin
firmware/firmware.elf
firmware/firmware.hex
firmware/firmware.map
testbench.exe
testbench.vcd
tests/*.o
dhrystone/dhry.bin
dhrystone/dhry.elf
dhrystone/dhry.hex
dhrystone/dhry.map
dhrystone/*.d
dhrystone/*.o
fsm_encoding.os
synth_vivado.log
synth_vivado.v

37
Makefile Normal file
View File

@ -0,0 +1,37 @@
TEST_OBJS=$(addsuffix .o,$(basename $(wildcard tests/*.S)))
test: testbench.exe firmware/firmware.hex
vvp -N testbench.exe
testbench.exe: testbench.v picorv32.v
iverilog -o testbench.exe testbench.v picorv32.v
chmod -x testbench.exe
firmware/firmware.hex: firmware/firmware.bin firmware/makehex.py
python3 firmware/makehex.py $< > $@
firmware/firmware.bin: firmware/firmware.elf
riscv64-unknown-elf-objcopy -O binary $< $@
chmod -x $@
firmware/firmware.elf: $(TEST_OBJS) firmware/sections.lds firmware/start.S firmware/sieve.c firmware/stats.c
riscv64-unknown-elf-gcc -Os -m32 -march=RV32I -ffreestanding -nostdlib -o $@ \
-Wl,-Bstatic,-T,firmware/sections.lds,-Map,firmware/firmware.map,--strip-debug \
firmware/start.S firmware/sieve.c firmware/stats.c $(TEST_OBJS) -lgcc
chmod -x $@
tests/%.o: tests/%.S tests/riscv_test.h tests/test_macros.h
riscv64-unknown-elf-gcc -m32 -march=RV32I -c -o $@ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
-DTEST_FUNC_TXT='"$(notdir $(basename $<))"' -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
synth_vivado:
vivado -nojournal -log synth_vivado.log -mode batch -source synth_vivado.tcl
clean:
rm -vrf $(TEST_OBJS) firmware/firmware.elf firmware/firmware.bin firmware/firmware.hex \
firmware/firmware.map testbench.exe testbench.vcd .Xil fsm_encoding.os \
synth_vivado.log synth_vivado_*.backup.log synth_vivado.v
.PHONY: test synth_vivado clean

63
README.md Normal file
View File

@ -0,0 +1,63 @@
PicoRV32 - A Size-Optimized RISC-V CPU
======================================
PicoRV32 is a CPU core that implements the [RISC-V RV32I Instruction Set](http://riscv.org/).
Tools (gcc, binutils, etc..) can be obtained via the [RISC-V Website](http://riscv.org/download.html#tab_tools).
Features and Typical Applications:
----------------------------------
- Small (about 1000 LUTs in a 7-Series Xilinx FGPA)
- High fMAX (>250 MHz on 7-Series Xilinx FGPAs)
- Selectable native memory interface or AXI4-Lite master
This CPU is meant to be used as auxiliary processor in FPGA designs and ASICs. Due
to its high fMAX it can be integrated in most existing designs without crossing
clock domains. When operated on a lower frequency, it will have a lot of timing
slack and thus can be added to a design without compromising timing closure.
For even smaller size it is possible disable support for registers `x16`..`x31` as
well as `RDCYCLE[H]`, `RDTIME[H]`, and `RDINSTRET[H]` instructions, turning the
processor into an RV32E core.
*Note: In architectures that implement the register file in dedicated memory
resources, such as many FPGAs, disabling the 16 upper registers may not further
reduce the core size.*
The core exists in two variations: `picorv32` and `picorv32_axi`. The former
provides a simple native memory interface, that is easy to use in simple
environments, and the latter provides an AXI-4 Lite Master interface that can
easily be integrated with existing systems that are already using the AXI
standard.
A separate core `picorv32_axi_adapter` is provided to bridge between the native
memory interface and AXI4. This core can be used to create custom cores that
include one or more PicoRV32 cores together with local RAM, ROM, and
memory-mapped peripherals, communicating with each other using the native
interface, and communicating with the outside world via AXI4.
Performance:
------------
The average Cycles per Instruction (CPI) is 6 to 8, depending on the
application code. (Most instructions, including unconditional branches and
not-taken conditional branches execute in 5 cycles. Memory load/store, taken
conditional branches, JALR, and shift operations may take more than 5 cycles.)
Dhrystone benchmark results: 0.124 DMIPS/MHz (219 Dhrystones/Second/MHz)
*This numbers apply for setups with memory that can accomodate requests within
one clock cycle. Slower memory will degrade the performance of the processor.*
Todos:
------
- Optional IRQ support
- Optional write-through cache
- Optional support for compressed ISA

35
dhrystone/Makefile Normal file
View File

@ -0,0 +1,35 @@
OBJS = start.o dhry_1.o dhry_2.o stdlib.o
CFLAGS = -MD -O3 -m32 -march=RV32I -ffreestanding -nostdlib -DTIME
test: testbench.exe dhry.hex
vvp -N testbench.exe
testbench.exe: testbench.v ../picorv32.v
iverilog -o testbench.exe testbench.v ../picorv32.v
chmod -x testbench.exe
dhry.hex: dhry.bin ../firmware/makehex.py
python3 ../firmware/makehex.py $< > $@
dhry.bin: dhry.elf
riscv64-unknown-elf-objcopy -O binary $< $@
chmod -x $@
dhry.elf: $(OBJS) ../firmware/sections.lds
riscv64-unknown-elf-gcc $(CFLAGS) -Wl,-Bstatic,-T,../firmware/sections.lds,-Map,dhry.map,--strip-debug -o $@ $(OBJS) -lgcc
chmod -x $@
%.o: %.c
riscv64-unknown-elf-gcc -c $(CFLAGS) $<
%.o: %.S
riscv64-unknown-elf-gcc -c $(CFLAGS) $<
clean:
rm -rf *.o *.d dhry.elf dhry.map dhry.bin dhry.hex testbench.exe testbench.vcd
.PHONY: test clean
-include *.d

423
dhrystone/dhry.h Normal file
View File

@ -0,0 +1,423 @@
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry.h (part 1 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
* Siemens AG, AUT E 51
* Postfach 3220
* 8520 Erlangen
* Germany (West)
* Phone: [+49]-9131-7-20330
* (8-17 Central European Time)
* Usenet: ..!mcsun!unido!estevax!weicker
*
* Original Version (in Ada) published in
* "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
* pp. 1013 - 1030, together with the statistics
* on which the distribution of statements etc. is based.
*
* In this C version, the following C library functions are used:
* - strcpy, strcmp (inside the measurement loop)
* - printf, scanf (outside the measurement loop)
* In addition, Berkeley UNIX system calls "times ()" or "time ()"
* are used for execution time measurement. For measurements
* on other systems, these calls have to be changed.
*
* Collection of Results:
* Reinhold Weicker (address see above) and
*
* Rick Richardson
* PC Research. Inc.
* 94 Apple Orchard Drive
* Tinton Falls, NJ 07724
* Phone: (201) 389-8963 (9-17 EST)
* Usenet: ...!uunet!pcrat!rick
*
* Please send results to Rick Richardson and/or Reinhold Weicker.
* Complete information should be given on hardware and software used.
* Hardware information includes: Machine type, CPU, type and size
* of caches; for microprocessors: clock frequency, memory speed
* (number of wait states).
* Software information includes: Compiler (and runtime library)
* manufacturer and version, compilation switches, OS version.
* The Operating System version may give an indication about the
* compiler; Dhrystone itself performs no OS calls in the measurement loop.
*
* The complete output generated by the program should be mailed
* such that at least some checks for correctness can be made.
*
***************************************************************************
*
* History: This version C/2.1 has been made for two reasons:
*
* 1) There is an obvious need for a common C version of
* Dhrystone, since C is at present the most popular system
* programming language for the class of processors
* (microcomputers, minicomputers) where Dhrystone is used most.
* There should be, as far as possible, only one C version of
* Dhrystone such that results can be compared without
* restrictions. In the past, the C versions distributed
* by Rick Richardson (Version 1.1) and by Reinhold Weicker
* had small (though not significant) differences.
*
* 2) As far as it is possible without changes to the Dhrystone
* statistics, optimizing compilers should be prevented from
* removing significant statements.
*
* This C version has been developed in cooperation with
* Rick Richardson (Tinton Falls, NJ), it incorporates many
* ideas from the "Version 1.1" distributed previously by
* him over the UNIX network Usenet.
* I also thank Chaim Benedelac (National Semiconductor),
* David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
* Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
* for their help with comments on earlier versions of the
* benchmark.
*
* Changes: In the initialization part, this version follows mostly
* Rick Richardson's version distributed via Usenet, not the
* version distributed earlier via floppy disk by Reinhold Weicker.
* As a concession to older compilers, names have been made
* unique within the first 8 characters.
* Inside the measurement loop, this version follows the
* version previously distributed by Reinhold Weicker.
*
* At several places in the benchmark, code has been added,
* but within the measurement loop only in branches that
* are not executed. The intention is that optimizing compilers
* should be prevented from moving code out of the measurement
* loop, or from removing code altogether. Since the statements
* that are executed within the measurement loop have NOT been
* changed, the numbers defining the "Dhrystone distribution"
* (distribution of statements, operand types and locality)
* still hold. Except for sophisticated optimizing compilers,
* execution times for this version should be the same as
* for previous versions.
*
* Since it has proven difficult to subtract the time for the
* measurement loop overhead in a correct way, the loop check
* has been made a part of the benchmark. This does have
* an impact - though a very minor one - on the distribution
* statistics which have been updated for this version.
*
* All changes within the measurement loop are described
* and discussed in the companion paper "Rationale for
* Dhrystone version 2".
*
* Because of the self-imposed limitation that the order and
* distribution of the executed statements should not be
* changed, there are still cases where optimizing compilers
* may not generate code for some statements. To a certain
* degree, this is unavoidable for small synthetic benchmarks.
* Users of the benchmark are advised to check code listings
* whether code is generated for all statements of Dhrystone.
*
* Version 2.1 is identical to version 2.0 distributed via
* the UNIX network Usenet in March 1988 except that it corrects
* some minor deficiencies that were found by users of version 2.0.
* The only change within the measurement loop is that a
* non-executed "else" part was added to the "if" statement in
* Func_3, and a non-executed "else" part removed from Proc_3.
*
***************************************************************************
*
* Defines: The following "Defines" are possible:
* -DREG=register (default: Not defined)
* As an approximation to what an average C programmer
* might do, the "register" storage class is applied
* (if enabled by -DREG=register)
* - for local variables, if they are used (dynamically)
* five or more times
* - for parameters if they are used (dynamically)
* six or more times
* Note that an optimal "register" strategy is
* compiler-dependent, and that "register" declarations
* do not necessarily lead to faster execution.
* -DNOSTRUCTASSIGN (default: Not defined)
* Define if the C compiler does not support
* assignment of structures.
* -DNOENUMS (default: Not defined)
* Define if the C compiler does not support
* enumeration types.
* -DTIMES (default)
* -DTIME
* The "times" function of UNIX (returning process times)
* or the "time" function (returning wallclock time)
* is used for measurement.
* For single user machines, "time ()" is adequate. For
* multi-user machines where you cannot get single-user
* access, use the "times ()" function. If you have
* neither, use a stopwatch in the dead of night.
* "printf"s are provided marking the points "Start Timer"
* and "Stop Timer". DO NOT use the UNIX "time(1)"
* command, as this will measure the total time to
* run this program, which will (erroneously) include
* the time to allocate storage (malloc) and to perform
* the initialization.
* -DHZ=nnn
* In Berkeley UNIX, the function "times" returns process
* time in 1/HZ seconds, with HZ = 60 for most systems.
* CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
* A VALUE.
*
***************************************************************************
*
* Compilation model and measurement (IMPORTANT):
*
* This C version of Dhrystone consists of three files:
* - dhry.h (this file, containing global definitions and comments)
* - dhry_1.c (containing the code corresponding to Ada package Pack_1)
* - dhry_2.c (containing the code corresponding to Ada package Pack_2)
*
* The following "ground rules" apply for measurements:
* - Separate compilation
* - No procedure merging
* - Otherwise, compiler optimizations are allowed but should be indicated
* - Default results are those without register declarations
* See the companion paper "Rationale for Dhrystone Version 2" for a more
* detailed discussion of these ground rules.
*
* For 16-Bit processors (e.g. 80186, 80286), times for all compilation
* models ("small", "medium", "large" etc.) should be given if possible,
* together with a definition of these models for the compiler system used.
*
**************************************************************************
*
* Dhrystone (C version) statistics:
*
* [Comment from the first distribution, updated for version 2.
* Note that because of language differences, the numbers are slightly
* different from the Ada version.]
*
* The following program contains statements of a high level programming
* language (here: C) in a distribution considered representative:
*
* assignments 52 (51.0 %)
* control statements 33 (32.4 %)
* procedure, function calls 17 (16.7 %)
*
* 103 statements are dynamically executed. The program is balanced with
* respect to the three aspects:
*
* - statement type
* - operand type
* - operand locality
* operand global, local, parameter, or constant.
*
* The combination of these three aspects is balanced only approximately.
*
* 1. Statement Type:
* ----------------- number
*
* V1 = V2 9
* (incl. V1 = F(..)
* V = Constant 12
* Assignment, 7
* with array element
* Assignment, 6
* with record component
* --
* 34 34
*
* X = Y +|-|"&&"|"|" Z 5
* X = Y +|-|"==" Constant 6
* X = X +|- 1 3
* X = Y *|/ Z 2
* X = Expression, 1
* two operators
* X = Expression, 1
* three operators
* --
* 18 18
*
* if .... 14
* with "else" 7
* without "else" 7
* executed 3
* not executed 4
* for ... 7 | counted every time
* while ... 4 | the loop condition
* do ... while 1 | is evaluated
* switch ... 1
* break 1
* declaration with 1
* initialization
* --
* 34 34
*
* P (...) procedure call 11
* user procedure 10
* library procedure 1
* X = F (...)
* function call 6
* user function 5
* library function 1
* --
* 17 17
* ---
* 103
*
* The average number of parameters in procedure or function calls
* is 1.82 (not counting the function values as implicit parameters).
*
*
* 2. Operators
* ------------
* number approximate
* percentage
*
* Arithmetic 32 50.8
*
* + 21 33.3
* - 7 11.1
* * 3 4.8
* / (int div) 1 1.6
*
* Comparison 27 42.8
*
* == 9 14.3
* /= 4 6.3
* > 1 1.6
* < 3 4.8
* >= 1 1.6
* <= 9 14.3
*
* Logic 4 6.3
*
* && (AND-THEN) 1 1.6
* | (OR) 1 1.6
* ! (NOT) 2 3.2
*
* -- -----
* 63 100.1
*
*
* 3. Operand Type (counted once per operand reference):
* ---------------
* number approximate
* percentage
*
* Integer 175 72.3 %
* Character 45 18.6 %
* Pointer 12 5.0 %
* String30 6 2.5 %
* Array 2 0.8 %
* Record 2 0.8 %
* --- -------
* 242 100.0 %
*
* When there is an access path leading to the final operand (e.g. a record
* component), only the final data type on the access path is counted.
*
*
* 4. Operand Locality:
* -------------------
* number approximate
* percentage
*
* local variable 114 47.1 %
* global variable 22 9.1 %
* parameter 45 18.6 %
* value 23 9.5 %
* reference 22 9.1 %
* function result 6 2.5 %
* constant 55 22.7 %
* --- -------
* 242 100.0 %
*
*
* The program does not compute anything meaningful, but it is syntactically
* and semantically correct. All variables have a value assigned to them
* before they are used as a source operand.
*
* There has been no explicit effort to account for the effects of a
* cache, or to balance the use of long or short displacements for code or
* data.
*
***************************************************************************
*/
/* Compiler and system dependent definitions: */
#ifndef TIME
#define TIMES
#endif
/* Use times(2) time function unless */
/* explicitly defined otherwise */
#ifdef TIMES
#include <sys/types.h>
#include <sys/times.h>
/* for "times" */
#endif
#define Mic_secs_Per_Second 1000000.0
/* Berkeley UNIX C returns process times in seconds/HZ */
#ifdef NOSTRUCTASSIGN
#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
#else
#define structassign(d, s) d = s
#endif
#ifdef NOENUM
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
typedef int Enumeration;
#else
typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
Enumeration;
#endif
/* for boolean and enumeration types in Ada, Pascal */
/* General definitions: */
#include <stdio.h>
/* for strcpy, strcmp */
#define Null 0
/* Value of a Null pointer */
#define true 1
#define false 0
typedef int One_Thirty;
typedef int One_Fifty;
typedef char Capital_Letter;
typedef int Boolean;
typedef char Str_30 [31];
typedef int Arr_1_Dim [50];
typedef int Arr_2_Dim [50] [50];
typedef struct record
{
struct record *Ptr_Comp;
Enumeration Discr;
union {
struct {
Enumeration Enum_Comp;
int Int_Comp;
char Str_Comp [31];
} var_1;
struct {
Enumeration E_Comp_2;
char Str_2_Comp [31];
} var_2;
struct {
char Ch_1_Comp;
char Ch_2_Comp;
} var_3;
} variant;
} Rec_Type, *Rec_Pointer;

412
dhrystone/dhry_1.c Normal file
View File

@ -0,0 +1,412 @@
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_1.c (part 2 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
****************************************************************************
*/
#include "dhry.h"
/* Global Variables: */
Rec_Pointer Ptr_Glob,
Next_Ptr_Glob;
int Int_Glob;
Boolean Bool_Glob;
char Ch_1_Glob,
Ch_2_Glob;
int Arr_1_Glob [50];
int Arr_2_Glob [50] [50];
extern char *malloc ();
Enumeration Func_1 ();
/* forward declaration necessary since Enumeration may not simply be int */
#ifndef REG
Boolean Reg = false;
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#else
Boolean Reg = true;
#endif
/* variables for time measurement: */
#ifdef TIMES
struct tms time_info;
extern int times ();
/* see library function "times" */
#define Too_Small_Time 120
/* Measurements should last at least about 2 seconds */
#endif
#ifdef TIME
extern long time();
extern long insn();
/* see library function "time" */
#define Too_Small_Time 2
/* Measurements should last at least 2 seconds */
#endif
long Begin_Time,
End_Time,
User_Time;
long Begin_Insn,
End_Insn,
User_Insn;
float Microseconds,
Dhrystones_Per_Second;
/* end of variables for time measurement */
main ()
/*****/
/* main program, corresponds to procedures */
/* Main and Proc_0 in the Ada version */
{
One_Fifty Int_1_Loc;
REG One_Fifty Int_2_Loc;
One_Fifty Int_3_Loc;
REG char Ch_Index;
Enumeration Enum_Loc;
Str_30 Str_1_Loc;
Str_30 Str_2_Loc;
REG int Run_Index;
REG int Number_Of_Runs;
/* Initializations */
Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
Ptr_Glob->Discr = Ident_1;
Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
Ptr_Glob->variant.var_1.Int_Comp = 40;
strcpy (Ptr_Glob->variant.var_1.Str_Comp,
"DHRYSTONE PROGRAM, SOME STRING");
strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
Arr_2_Glob [8][7] = 10;
/* Was missing in published program. Without this statement, */
/* Arr_2_Glob [8][7] would have an undefined value. */
/* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
/* overflow may occur for this array element. */
printf ("\n");
printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
printf ("\n");
if (Reg)
{
printf ("Program compiled with 'register' attribute\n");
printf ("\n");
}
else
{
printf ("Program compiled without 'register' attribute\n");
printf ("\n");
}
printf ("Please give the number of runs through the benchmark: ");
{
int n;
scanf ("%d", &n);
Number_Of_Runs = n;
}
printf ("\n");
printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
/***************/
/* Start timer */
/***************/
#ifdef TIMES
times (&time_info);
Begin_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
Begin_Time = time ( (long *) 0);
Begin_Insn = insn ( (long *) 0);
#endif
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
{
Proc_5();
Proc_4();
/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
Int_1_Loc = 2;
Int_2_Loc = 3;
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
Enum_Loc = Ident_2;
Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
/* Bool_Glob == 1 */
while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
{
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
/* Int_3_Loc == 7 */
Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
/* Int_3_Loc == 7 */
Int_1_Loc += 1;
} /* while */
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
/* Int_Glob == 5 */
Proc_1 (Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
/* loop body executed twice */
{
if (Enum_Loc == Func_1 (Ch_Index, 'C'))
/* then, not executed */
{
Proc_6 (Ident_1, &Enum_Loc);
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
Int_2_Loc = Run_Index;
Int_Glob = Run_Index;
}
}
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
Proc_2 (&Int_1_Loc);
/* Int_1_Loc == 5 */
} /* loop "for Run_Index" */
/**************/
/* Stop timer */
/**************/
#ifdef TIMES
times (&time_info);
End_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
End_Time = time ( (long *) 0);
End_Insn = insn ( (long *) 0);
#endif
printf ("Execution ends\n");
printf ("\n");
printf ("Final values of the variables used in the benchmark:\n");
printf ("\n");
printf ("Int_Glob: %d\n", Int_Glob);
printf (" should be: %d\n", 5);
printf ("Bool_Glob: %d\n", Bool_Glob);
printf (" should be: %d\n", 1);
printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
printf (" should be: %c\n", 'A');
printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
printf (" should be: %c\n", 'B');
printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
printf (" should be: %d\n", 7);
printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
printf (" should be: Number_Of_Runs + 10\n");
printf ("Ptr_Glob->\n");
printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent)\n");
printf (" Discr: %d\n", Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 2);
printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 17);
printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Next_Ptr_Glob->\n");
printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent), same as above\n");
printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 1);
printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 18);
printf (" Str_Comp: %s\n",
Next_Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Int_1_Loc: %d\n", Int_1_Loc);
printf (" should be: %d\n", 5);
printf ("Int_2_Loc: %d\n", Int_2_Loc);
printf (" should be: %d\n", 13);
printf ("Int_3_Loc: %d\n", Int_3_Loc);
printf (" should be: %d\n", 7);
printf ("Enum_Loc: %d\n", Enum_Loc);
printf (" should be: %d\n", 1);
printf ("Str_1_Loc: %s\n", Str_1_Loc);
printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
printf ("Str_2_Loc: %s\n", Str_2_Loc);
printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
printf ("\n");
User_Time = End_Time - Begin_Time;
User_Insn = End_Insn - Begin_Insn;
#if 1
printf("Number_Of_Runs: %d\n", Number_Of_Runs);
printf("User_Time: %d cycles, %d insn\n", User_Time, User_Insn);
int Cycles_Per_Instruction_x1000 = (1000 * User_Time) / User_Insn;
printf("Cycles_Per_Instruction: %d.%d%d%d\n", Cycles_Per_Instruction_x1000 / 1000,
(Cycles_Per_Instruction_x1000 / 100) % 10,
(Cycles_Per_Instruction_x1000 / 10) % 10,
(Cycles_Per_Instruction_x1000 / 1) % 10);
int Dhrystones_Per_Second_Per_MHz = (Number_Of_Runs * 1000000) / User_Time;
printf("Dhrystones_Per_Second_Per_MHz: %d\n", Dhrystones_Per_Second_Per_MHz);
int DMIPS_Per_MHz_x1000 = (1000 * Dhrystones_Per_Second_Per_MHz) / 1757;
printf("DMIPS_Per_MHz: %d.%d%d%d\n", DMIPS_Per_MHz_x1000 / 1000,
(DMIPS_Per_MHz_x1000 / 100) % 10,
(DMIPS_Per_MHz_x1000 / 10) % 10,
(DMIPS_Per_MHz_x1000 / 1) % 10);
#else
if (User_Time < Too_Small_Time)
{
printf ("Measured time too small to obtain meaningful results\n");
printf ("Please increase number of runs\n");
printf ("\n");
}
else
{
#ifdef TIME
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ (float) Number_Of_Runs;
Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
#else
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ ((float) HZ * ((float) Number_Of_Runs));
Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
/ (float) User_Time;
#endif
printf ("Microseconds for one run through Dhrystone: ");
printf ("%6.1f \n", Microseconds);
printf ("Dhrystones per Second: ");
printf ("%6.1f \n", Dhrystones_Per_Second);
printf ("\n");
}
#endif
}
Proc_1 (Ptr_Val_Par)
/******************/
REG Rec_Pointer Ptr_Val_Par;
/* executed once */
{
REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
/* == Ptr_Glob_Next */
/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
/* corresponds to "rename" in Ada, "with" in Pascal */
structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
Ptr_Val_Par->variant.var_1.Int_Comp = 5;
Next_Record->variant.var_1.Int_Comp
= Ptr_Val_Par->variant.var_1.Int_Comp;
Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
Proc_3 (&Next_Record->Ptr_Comp);
/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
== Ptr_Glob->Ptr_Comp */
if (Next_Record->Discr == Ident_1)
/* then, executed */
{
Next_Record->variant.var_1.Int_Comp = 6;
Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
&Next_Record->variant.var_1.Enum_Comp);
Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
&Next_Record->variant.var_1.Int_Comp);
}
else /* not executed */
structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
} /* Proc_1 */
Proc_2 (Int_Par_Ref)
/******************/
/* executed once */
/* *Int_Par_Ref == 1, becomes 4 */
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
Enumeration Enum_Loc;
Int_Loc = *Int_Par_Ref + 10;
do /* executed once */
if (Ch_1_Glob == 'A')
/* then, executed */
{
Int_Loc -= 1;
*Int_Par_Ref = Int_Loc - Int_Glob;
Enum_Loc = Ident_1;
} /* if */
while (Enum_Loc != Ident_1); /* true */
} /* Proc_2 */
Proc_3 (Ptr_Ref_Par)
/******************/
/* executed once */
/* Ptr_Ref_Par becomes Ptr_Glob */
Rec_Pointer *Ptr_Ref_Par;
{
if (Ptr_Glob != Null)
/* then, executed */
*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
} /* Proc_3 */
Proc_4 () /* without parameters */
/*******/
/* executed once */
{
Boolean Bool_Loc;
Bool_Loc = Ch_1_Glob == 'A';
Bool_Glob = Bool_Loc | Bool_Glob;
Ch_2_Glob = 'B';
} /* Proc_4 */
Proc_5 () /* without parameters */
/*******/
/* executed once */
{
Ch_1_Glob = 'A';
Bool_Glob = false;
} /* Proc_5 */
/* Procedure for the assignment of structures, */
/* if the C compiler doesn't support this feature */
#ifdef NOSTRUCTASSIGN
memcpy (d, s, l)
register char *d;
register char *s;
register int l;
{
while (l--) *d++ = *s++;
}
#endif

192
dhrystone/dhry_2.c Normal file
View File

@ -0,0 +1,192 @@
/*
****************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_2.c (part 3 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
****************************************************************************
*/
#include "dhry.h"
#ifndef REG
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#endif
extern int Int_Glob;
extern char Ch_1_Glob;
Proc_6 (Enum_Val_Par, Enum_Ref_Par)
/*********************************/
/* executed once */
/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
Enumeration Enum_Val_Par;
Enumeration *Enum_Ref_Par;
{
*Enum_Ref_Par = Enum_Val_Par;
if (! Func_3 (Enum_Val_Par))
/* then, not executed */
*Enum_Ref_Par = Ident_4;
switch (Enum_Val_Par)
{
case Ident_1:
*Enum_Ref_Par = Ident_1;
break;
case Ident_2:
if (Int_Glob > 100)
/* then */
*Enum_Ref_Par = Ident_1;
else *Enum_Ref_Par = Ident_4;
break;
case Ident_3: /* executed */
*Enum_Ref_Par = Ident_2;
break;
case Ident_4: break;
case Ident_5:
*Enum_Ref_Par = Ident_3;
break;
} /* switch */
} /* Proc_6 */
Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
/**********************************************/
/* executed three times */
/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
/* Int_Par_Ref becomes 7 */
/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
/* Int_Par_Ref becomes 17 */
/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
/* Int_Par_Ref becomes 18 */
One_Fifty Int_1_Par_Val;
One_Fifty Int_2_Par_Val;
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
Int_Loc = Int_1_Par_Val + 2;
*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
} /* Proc_7 */
Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
/*********************************************************************/
/* executed once */
/* Int_Par_Val_1 == 3 */
/* Int_Par_Val_2 == 7 */
Arr_1_Dim Arr_1_Par_Ref;
Arr_2_Dim Arr_2_Par_Ref;
int Int_1_Par_Val;
int Int_2_Par_Val;
{
REG One_Fifty Int_Index;
REG One_Fifty Int_Loc;
Int_Loc = Int_1_Par_Val + 5;
Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
Int_Glob = 5;
} /* Proc_8 */
Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
/*************************************************/
/* executed three times */
/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
Capital_Letter Ch_1_Par_Val;
Capital_Letter Ch_2_Par_Val;
{
Capital_Letter Ch_1_Loc;
Capital_Letter Ch_2_Loc;
Ch_1_Loc = Ch_1_Par_Val;
Ch_2_Loc = Ch_1_Loc;
if (Ch_2_Loc != Ch_2_Par_Val)
/* then, executed */
return (Ident_1);
else /* not executed */
{
Ch_1_Glob = Ch_1_Loc;
return (Ident_2);
}
} /* Func_1 */
Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
/*************************************************/
/* executed once */
/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
Str_30 Str_1_Par_Ref;
Str_30 Str_2_Par_Ref;
{
REG One_Thirty Int_Loc;
Capital_Letter Ch_Loc;
Int_Loc = 2;
while (Int_Loc <= 2) /* loop body executed once */
if (Func_1 (Str_1_Par_Ref[Int_Loc],
Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
/* then, executed */
{
Ch_Loc = 'A';
Int_Loc += 1;
} /* if, while */
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
/* then, not executed */
Int_Loc = 7;
if (Ch_Loc == 'R')
/* then, not executed */
return (true);
else /* executed */
{
if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
/* then, not executed */
{
Int_Loc += 7;
Int_Glob = Int_Loc;
return (true);
}
else /* executed */
return (false);
} /* if Ch_Loc */
} /* Func_2 */
Boolean Func_3 (Enum_Par_Val)
/***************************/
/* executed once */
/* Enum_Par_Val == Ident_3 */
Enumeration Enum_Par_Val;
{
Enumeration Enum_Loc;
Enum_Loc = Enum_Par_Val;
if (Enum_Loc == Ident_3)
/* then, executed */
return (true);
else /* not executed */
return (false);
} /* Func_3 */

41
dhrystone/start.S Normal file
View File

@ -0,0 +1,41 @@
.section .text
.global start
.global main
start:
/* print "START\n" */
lui a0,0x10000000>>12
addi a1,zero,'S'
addi a2,zero,'T'
addi a3,zero,'A'
addi a4,zero,'R'
addi a5,zero,'\n'
sw a1,0(a0)
sw a2,0(a0)
sw a3,0(a0)
sw a4,0(a0)
sw a2,0(a0)
sw a5,0(a0)
/* set stack pointer */
lui sp,(64*1024)>>12
/* jump to main C code */
jal ra,main
/* print "DONE\n" */
lui a0,0x10000000>>12
addi a1,zero,'D'
addi a2,zero,'O'
addi a3,zero,'N'
addi a4,zero,'E'
addi a5,zero,'\n'
sw a1,0(a0)
sw a2,0(a0)
sw a3,0(a0)
sw a4,0(a0)
sw a5,0(a0)
/* break */
sbreak

136
dhrystone/stdlib.c Normal file
View File

@ -0,0 +1,136 @@
#include <stdarg.h>
extern long time();
extern long insn();
extern char *malloc();
extern void *memcpy(char *dest, const char *src, int n);
extern char *strcpy(char *dest, const char *src);
extern int strcmp(const char *s1, const char *s2);
extern int printf(const char *format, ...);
extern int scanf(const char *format, ...);
char heap_memory[1024];
int heap_memory_used = 0;
long time()
{
int cycles;
asm("rdcycle %0" : "=r"(cycles));
// printf("[time() -> %d]", cycles);
return cycles;
}
long insn()
{
int insns;
asm("rdinstret %0" : "=r"(insns));
// printf("[insn() -> %d]", insns);
return insns;
}
char *malloc(int size)
{
char *p = heap_memory + heap_memory_used;
// printf("[malloc(%d) -> %d (%d..%d)]", size, (int)p, heap_memory_used, heap_memory_used + size);
heap_memory_used += size;
if (heap_memory_used > 1024)
asm("sbreak");
return p;
}
void *memcpy(char *dest, const char *src, int n)
{
while (n--)
*(dest++) = *(src++);
}
char *strcpy(char *dest, const char *src)
{
char *ret = dest;
// printf("[strcpy()]");
do
*(dest++) = *src;
while (*(src++));
return ret;
}
int strcmp(const char *s1, const char *s2)
{
// printf("[strcmp()]");
while (1) {
if (*s1 == 0 && *s2 == 0)
return 0;
if (*s1 < *s2)
return -1;
if (*s1 > *s2)
return +1;
s1++, s2++;
}
}
static void printf_c(int c)
{
*((volatile int*)0x10000000) = c;
}
static void printf_s(char *p)
{
while (*p)
*((volatile int*)0x10000000) = *(p++);
}
static void printf_d(int val)
{
char buffer[32];
char *p = buffer;
if (val < 0) {
printf_c('-');
val = -val;
}
while (val || p == buffer) {
*(p++) = '0' + val % 10;
val = val / 10;
}
while (p != buffer)
printf_c(*(--p));
}
int printf(const char *format, ...)
{
int i;
va_list ap;
va_start(ap, format);
for (i = 0; format[i]; i++)
if (format[i] == '%') {
while (format[++i]) {
if (format[i] == 'c') {
printf_c(va_arg(ap,int));
break;
}
if (format[i] == 's') {
printf_s(va_arg(ap,char*));
break;
}
if (format[i] == 'd') {
printf_d(va_arg(ap,int));
break;
}
}
} else
printf_c(format[i]);
va_end(ap);
}
int scanf(const char *format, ...)
{
// printf("[scanf(\"%s\")]\n", format);
va_list ap;
va_start(ap, format);
*va_arg(ap,int*) = 100;
va_end(ap);
return 0;
}

71
dhrystone/testbench.v Normal file
View File

@ -0,0 +1,71 @@
`timescale 1 ns / 1 ps
module testbench;
reg clk = 1;
reg resetn = 0;
wire trap;
always #5 clk = ~clk;
initial begin
repeat (100) @(posedge clk);
resetn <= 1;
end
wire mem_valid;
wire mem_instr;
reg mem_ready;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
reg [31:0] mem_rdata;
picorv32 uut (
.clk (clk ),
.resetn (resetn ),
.trap (trap ),
.mem_valid(mem_valid),
.mem_instr(mem_instr),
.mem_ready(mem_ready),
.mem_addr (mem_addr ),
.mem_wdata(mem_wdata),
.mem_wstrb(mem_wstrb),
.mem_rdata(mem_rdata)
);
reg [31:0] memory [0:64*1024/4-1];
initial $readmemh("dhry.hex", memory);
always @(posedge clk) begin
mem_ready <= 0;
mem_rdata <= 'bx;
if (resetn && mem_valid && !mem_ready) begin
mem_ready <= 1;
if (mem_addr == 32'h1000_0000) begin
$write("%c", mem_wdata);
$fflush();
end else
if (mem_wstrb) begin
if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];
if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8];
if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16];
if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24];
end else begin
mem_rdata <= memory[mem_addr >> 2];
end
end
end
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
end
always @(posedge clk) begin
if (resetn && trap) begin
repeat (10) @(posedge clk);
$display("TRAP");
$finish;
end
end
endmodule

17
firmware/makehex.py Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/python3
from sys import argv
with open(argv[1], "rb") as f:
bindata = f.read()
assert len(bindata) < 60*1024
assert len(bindata) % 4 == 0
for i in range(64*1024//4):
if i < len(bindata) // 4:
w = bindata[4*i : 4*i+4]
print("%02x%02x%02x%02x" % (w[3], w[2], w[1], w[0]))
else:
print("0")

9
firmware/sections.lds Normal file
View File

@ -0,0 +1,9 @@
SECTIONS {
.memory : {
. = 0x000000;
start*(.text);
*(.text);
*(*);
end = .;
}
}

78
firmware/sieve.c Normal file
View File

@ -0,0 +1,78 @@
// A simple Sieve of Eratosthenes
#include <stdint.h>
#include <stdbool.h>
#define BITMAP_SIZE 64
#define OUTPORT 0x10000000
static uint32_t bitmap[BITMAP_SIZE/32];
static void bitmap_set(int idx)
{
bitmap[idx/32] |= 1 << (idx % 32);
}
static bool bitmap_get(int idx)
{
return (bitmap[idx/32] & (1 << (idx % 32))) != 0;
}
static void print_str(const char *p)
{
while (*p != 0)
*((volatile uint32_t*)OUTPORT) = *(p++);
}
static void print_dec(int val)
{
char buffer[10];
char *p = buffer;
while (val) {
*(p++) = val % 10;
val = val / 10;
}
while (p != buffer) {
*((volatile uint32_t*)OUTPORT) = '0' + *(--p);
}
}
static void print_prime(int idx, int val)
{
if (idx < 10)
print_str(" ");
print_dec(idx);
if (idx / 10 == 1)
goto force_th;
switch (idx % 10) {
case 1: print_str("st"); break;
case 2: print_str("nd"); break;
case 3: print_str("rd"); break;
force_th:
default: print_str("th"); break;
}
print_str(" prime is ");
print_dec(val);
print_str(".\n");
}
void sieve()
{
int i, j, k;
int idx = 1;
print_prime(idx++, 2);
for (i = 0; i < BITMAP_SIZE; i++) {
if (bitmap_get(i))
continue;
print_prime(idx++, 3+2*i);
for (j = 2*(3+2*i);; j += 3+2*i) {
if (j%2 == 0)
continue;
k = (j-3)/2;
if (k >= BITMAP_SIZE)
break;
bitmap_set(k);
}
}
}

80
firmware/start.S Normal file
View File

@ -0,0 +1,80 @@
.section .text
.global start
.global sieve
.global stats
#define TEST(n) \
.global n; .global n ## _ret; \
jal zero,n; n ## _ret:
start:
TEST(lui)
TEST(auipc)
TEST(j)
TEST(jal)
TEST(jalr)
TEST(beq)
TEST(bne)
TEST(blt)
TEST(bge)
TEST(bltu)
TEST(bgeu)
TEST(lb)
TEST(lh)
TEST(lw)
TEST(lbu)
TEST(lhu)
TEST(sb)
TEST(sh)
TEST(sw)
TEST(addi)
TEST(slti) // also tests sltiu
TEST(xori)
TEST(ori)
TEST(andi)
TEST(slli)
TEST(srli)
TEST(srai)
TEST(add)
TEST(sub)
TEST(sll)
TEST(slt) // what is with sltu ?
TEST(xor)
TEST(srl)
TEST(sra)
TEST(or)
TEST(and)
TEST(fence_i)
TEST(simple)
/* set stack pointer */
lui sp,(64*1024)>>12
/* jump to sieve C code */
jal ra,sieve
/* jump to stats C code */
jal ra,stats
/* print "DONE\n" */
lui a0,0x10000000>>12
addi a1,zero,'D'
addi a2,zero,'O'
addi a3,zero,'N'
addi a4,zero,'E'
addi a5,zero,'\n'
sw a1,0(a0)
sw a2,0(a0)
sw a3,0(a0)
sw a4,0(a0)
sw a5,0(a0)
/* break */
sbreak

43
firmware/stats.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdint.h>
#include <stdbool.h>
#define OUTPORT 0x10000000
static void print_str(const char *p)
{
while (*p != 0)
*((volatile uint32_t*)OUTPORT) = *(p++);
}
static void print_dec(int val, int digits, bool zero_pad)
{
char buffer[32];
char *p = buffer;
while (val || digits > 0) {
if (val)
*(p++) = '0' + val % 10;
else
*(p++) = zero_pad ? '0' : ' ';
val = val / 10;
digits--;
}
while (p != buffer) {
if (p[-1] == ' ' && p[-2] == ' ') p[-1] = '.';
*((volatile uint32_t*)OUTPORT) = *(--p);
}
}
void stats()
{
int num_cycles, num_instr;
asm("rdcycle %0; rdinstret %1;" : "=r"(num_cycles), "=r"(num_instr));
print_str("Cycle counter ........");
print_dec(num_cycles, 8, false);
print_str("\nInstruction counter ..");
print_dec(num_instr, 8, false);
print_str("\nCPI: ");
print_dec((num_cycles / num_instr), 0, false);
print_str(".");
print_dec(((100 * num_cycles) / num_instr) % 100, 2, true);
print_str("\n");
}

844
picorv32.v Normal file
View File

@ -0,0 +1,844 @@
/*
* PicoRV32 -- A Small RISC-V (RV32I) Processor Core
*
* Copyright (C) 2015 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`timescale 1 ns / 1 ps
// `define DEBUG
/***************************************************************
* picorv32
***************************************************************/
module picorv32 #(
parameter ENABLE_COUNTERS = 1,
parameter ENABLE_REGS_16_31 = 1
) (
input clk, resetn,
output reg trap,
output reg mem_valid,
output reg mem_instr,
input mem_ready,
output reg [31:0] mem_addr,
output reg [31:0] mem_wdata,
output reg [ 3:0] mem_wstrb,
input [31:0] mem_rdata
);
localparam integer regfile_size = ENABLE_REGS_16_31 ? 32 : 16;
localparam integer regindex_bits = ENABLE_REGS_16_31 ? 5 : 4;
reg [63:0] count_cycle, count_instr;
reg [31:0] reg_pc, reg_op1, reg_op2, reg_out;
reg [31:0] cpuregs [0:regfile_size-1];
reg [4:0] reg_sh;
wire reg_out_0 = reg_out[0];
// Memory Interface
reg [1:0] mem_state;
reg [1:0] mem_wordsize;
reg [31:0] mem_buffer;
reg mem_do_prefetch;
reg mem_do_rinst;
reg mem_do_rdata;
reg mem_do_wdata;
reg mem_done;
wire mem_busy = |{mem_do_prefetch, mem_do_rinst, mem_do_rdata, mem_do_wdata};
always @(posedge clk) begin
mem_done <= 0;
if (!resetn) begin
mem_state <= 0;
mem_valid <= 0;
end else case (mem_state)
0: begin
if (mem_do_rinst || mem_do_prefetch) begin
mem_valid <= 1;
mem_addr <= mem_do_prefetch ? reg_pc + 4 : reg_pc;
mem_instr <= 1;
mem_wstrb <= 0;
mem_state <= 1;
end
if (mem_do_rdata) begin
mem_valid <= 1;
mem_addr <= {reg_op1[31:2], 2'b00};
mem_instr <= 0;
mem_wstrb <= 0;
mem_state <= 1;
end
if (mem_do_wdata) begin
mem_valid <= 1;
mem_addr <= {reg_op1[31:2], 2'b00};
mem_instr <= 0;
(* full_case *)
case (mem_wordsize)
0: begin
mem_wdata <= reg_op2;
mem_wstrb <= 4'b1111;
end
1: begin
mem_wdata <= {2{reg_op2[15:0]}};
mem_wstrb <= reg_op1[1] ? 4'b1100 : 4'b0011;
end
2: begin
mem_wdata <= {4{reg_op2[7:0]}};
mem_wstrb <= 4'b0001 << reg_op1[1:0];
end
endcase
mem_state <= 2;
end
end
1: begin
if (mem_ready) begin
(* full_case *)
case (mem_wordsize)
0: begin
mem_buffer <= mem_rdata;
end
1: begin
case (reg_op1[1])
1'b0: mem_buffer <= mem_rdata[15: 0];
1'b1: mem_buffer <= mem_rdata[31:16];
endcase
end
2: begin
case (reg_op1[1:0])
2'b00: mem_buffer <= mem_rdata[ 7: 0];
2'b01: mem_buffer <= mem_rdata[15: 8];
2'b10: mem_buffer <= mem_rdata[23:16];
2'b11: mem_buffer <= mem_rdata[31:24];
endcase
end
endcase
mem_valid <= 0;
mem_state <= 3;
mem_done <= mem_do_rinst || mem_do_rdata;
end
end
2: begin
if (mem_ready) begin
mem_valid <= 0;
mem_state <= 3;
mem_done <= 1;
end
end
3: begin
if (mem_done)
mem_state <= 0;
else if (mem_do_rinst || mem_do_rdata)
mem_done <= 1;
end
endcase
end
// Instruction Decoder
reg instr_lui, instr_auipc, instr_jal, instr_jalr;
reg instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu;
reg instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw;
reg instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai;
reg instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and;
reg instr_fence, instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh;
wire instr_trap;
reg [regindex_bits-1:0] decoded_rd, decoded_rs1, decoded_rs2;
reg [31:0] decoded_imm;
reg decoder_trigger;
wire [31:0] decoded_imm_uj;
assign { decoded_imm_uj[31:20], decoded_imm_uj[10:1], decoded_imm_uj[11], decoded_imm_uj[19:12], decoded_imm_uj[0] } = $signed({mem_buffer[31:12], 1'b0});
reg is_lui_auipc_jal;
reg is_lb_lh_lw_lbu_lhu;
reg is_slli_srli_srai;
reg is_jalr_addi_slti_sltiu_xori_ori_andi;
reg is_sb_sh_sw;
reg is_sll_srl_sra;
reg is_lui_auipc_jal_jalr_addi_add;
reg is_slti_blt_slt;
reg is_sltiu_bltu_sltu;
reg is_beq_bne_blt_bge_bltu_bgeu;
reg is_lbu_lhu_lw;
always @(posedge clk) begin
is_lui_auipc_jal <= |{instr_lui, instr_auipc, instr_jal};
is_lb_lh_lw_lbu_lhu <= |{instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu};
is_slli_srli_srai <= |{instr_slli, instr_srli, instr_srai};
is_jalr_addi_slti_sltiu_xori_ori_andi <= |{instr_jalr, instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi};
is_sb_sh_sw <= |{instr_sb, instr_sh, instr_sw};
is_sll_srl_sra <= |{instr_sll, instr_srl, instr_sra};
is_lui_auipc_jal_jalr_addi_add <= |{instr_lui, instr_auipc, instr_jal, instr_jalr, instr_addi, instr_add};
is_slti_blt_slt <= |{instr_slti, instr_blt, instr_slt};
is_sltiu_bltu_sltu <= |{instr_sltiu, instr_bltu, instr_sltu};
is_beq_bne_blt_bge_bltu_bgeu <= |{instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu};
is_lbu_lhu_lw <= |{instr_lbu, instr_lhu, instr_lw};
end
assign instr_trap = ~|{instr_lui, instr_auipc, instr_jal, instr_jalr,
instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu,
instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu, instr_sb, instr_sh, instr_sw,
instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi, instr_slli, instr_srli, instr_srai,
instr_add, instr_sub, instr_sll, instr_slt, instr_sltu, instr_xor, instr_srl, instr_sra, instr_or, instr_and,
instr_fence, instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh};
reg [63:0] instruction;
always @* begin
instruction = 'bx;
if (instr_lui) instruction = "lui";
if (instr_auipc) instruction = "auipc";
if (instr_jal) instruction = "jal";
if (instr_jalr) instruction = "jalr";
if (instr_beq) instruction = "beq";
if (instr_bne) instruction = "bne";
if (instr_blt) instruction = "blt";
if (instr_bge) instruction = "bge";
if (instr_bltu) instruction = "bltu";
if (instr_bgeu) instruction = "bgeu";
if (instr_lb) instruction = "lb";
if (instr_lh) instruction = "lh";
if (instr_lw) instruction = "lw";
if (instr_lbu) instruction = "lbu";
if (instr_lhu) instruction = "lhu";
if (instr_sb) instruction = "sb";
if (instr_sh) instruction = "sh";
if (instr_sw) instruction = "sw";
if (instr_addi) instruction = "addi";
if (instr_slti) instruction = "slti";
if (instr_sltiu) instruction = "sltiu";
if (instr_xori) instruction = "xori";
if (instr_ori) instruction = "ori";
if (instr_andi) instruction = "andi";
if (instr_slli) instruction = "slli";
if (instr_srli) instruction = "srli";
if (instr_srai) instruction = "srai";
if (instr_add) instruction = "add";
if (instr_sub) instruction = "sub";
if (instr_sll) instruction = "sll";
if (instr_slt) instruction = "slt";
if (instr_sltu) instruction = "sltu";
if (instr_xor) instruction = "xor";
if (instr_srl) instruction = "srl";
if (instr_sra) instruction = "sra";
if (instr_or) instruction = "or";
if (instr_and) instruction = "and";
if (instr_fence) instruction = "fence";
if (instr_rdcycle) instruction = "rdcycle";
if (instr_rdcycleh) instruction = "rdcycleh";
if (instr_rdinstr) instruction = "rdinstr";
if (instr_rdinstrh) instruction = "rdinstrh";
end
always @(posedge clk) begin
decoder_trigger <= 0;
if (mem_do_rinst && mem_done) begin
instr_lui <= mem_buffer[6:0] == 7'b0110111;
instr_auipc <= mem_buffer[6:0] == 7'b0010111;
instr_jal <= mem_buffer[6:0] == 7'b1101111;
instr_jalr <= mem_buffer[6:0] == 7'b1100111;
instr_beq <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b000;
instr_bne <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b001;
instr_blt <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b100;
instr_bge <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b101;
instr_bltu <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b110;
instr_bgeu <= mem_buffer[6:0] == 7'b1100011 && mem_buffer[14:12] == 3'b111;
instr_lb <= mem_buffer[6:0] == 7'b0000011 && mem_buffer[14:12] == 3'b000;
instr_lh <= mem_buffer[6:0] == 7'b0000011 && mem_buffer[14:12] == 3'b001;
instr_lw <= mem_buffer[6:0] == 7'b0000011 && mem_buffer[14:12] == 3'b010;
instr_lbu <= mem_buffer[6:0] == 7'b0000011 && mem_buffer[14:12] == 3'b100;
instr_lhu <= mem_buffer[6:0] == 7'b0000011 && mem_buffer[14:12] == 3'b101;
instr_sb <= mem_buffer[6:0] == 7'b0100011 && mem_buffer[14:12] == 3'b000;
instr_sh <= mem_buffer[6:0] == 7'b0100011 && mem_buffer[14:12] == 3'b001;
instr_sw <= mem_buffer[6:0] == 7'b0100011 && mem_buffer[14:12] == 3'b010;
instr_addi <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b000;
instr_slti <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b010;
instr_sltiu <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b011;
instr_xori <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b100;
instr_ori <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b110;
instr_andi <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b111;
instr_slli <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b001 && mem_buffer[31:25] == 7'b0000000;
instr_srli <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b101 && mem_buffer[31:25] == 7'b0000000;
instr_srai <= mem_buffer[6:0] == 7'b0010011 && mem_buffer[14:12] == 3'b101 && mem_buffer[31:25] == 7'b0100000;
instr_add <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b000 && mem_buffer[31:25] == 7'b0000000;
instr_sub <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b000 && mem_buffer[31:25] == 7'b0100000;
instr_sll <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b001 && mem_buffer[31:25] == 7'b0000000;
instr_slt <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b010 && mem_buffer[31:25] == 7'b0000000;
instr_sltu <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b011 && mem_buffer[31:25] == 7'b0000000;
instr_xor <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b100 && mem_buffer[31:25] == 7'b0000000;
instr_srl <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b101 && mem_buffer[31:25] == 7'b0000000;
instr_sra <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b101 && mem_buffer[31:25] == 7'b0100000;
instr_or <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b110 && mem_buffer[31:25] == 7'b0000000;
instr_and <= mem_buffer[6:0] == 7'b0110011 && mem_buffer[14:12] == 3'b111 && mem_buffer[31:25] == 7'b0000000;
instr_fence <= (mem_buffer[6:0] == 7'b0001111 && mem_buffer[19:12] == 0 && mem_buffer[31:28] == 4'b0000) ||
(mem_buffer[6:0] == 7'b0001111 && mem_buffer[31:12] == 1);
instr_rdcycle <= ((mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11000000000000000010) ||
(mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11000000000100000010)) && ENABLE_COUNTERS;
instr_rdcycleh <= ((mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11001000000000000010) ||
(mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11001000000100000010)) && ENABLE_COUNTERS;
instr_rdinstr <= (mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11000000001000000010) && ENABLE_COUNTERS;
instr_rdinstrh <= (mem_buffer[6:0] == 7'b1110011 && mem_buffer[31:12] == 'b11001000001000000010) && ENABLE_COUNTERS;
decoded_rd <= mem_buffer[11:7];
decoded_rs1 <= mem_buffer[19:15];
decoded_rs2 <= mem_buffer[24:20];
decoder_trigger <= 1;
end
if (decoder_trigger) begin
(* parallel_case *)
case (1'b1)
|{instr_lui, instr_auipc}:
decoded_imm <= mem_buffer[31:12] << 12;
instr_jal:
decoded_imm <= decoded_imm_uj;
instr_jalr:
decoded_imm <= $signed(mem_buffer[31:20]);
|{instr_beq, instr_bne, instr_blt, instr_bge, instr_bltu, instr_bgeu}:
decoded_imm <= $signed({mem_buffer[31], mem_buffer[7], mem_buffer[30:25], mem_buffer[11:8], 1'b0});
|{instr_lb, instr_lh, instr_lw, instr_lbu, instr_lhu}:
decoded_imm <= $signed(mem_buffer[31:20]);
|{instr_sb, instr_sh, instr_sw}:
decoded_imm <= $signed({mem_buffer[31:25], mem_buffer[11:7]});
|{instr_addi, instr_slti, instr_sltiu, instr_xori, instr_ori, instr_andi}:
decoded_imm <= $signed(mem_buffer[31:20]);
default:
decoded_imm <= 1'bx;
endcase
end
end
// Main State Machine
localparam cpu_state_fetch = 0;
localparam cpu_state_ld_rs1 = 1;
localparam cpu_state_ld_rs2 = 2;
localparam cpu_state_exec = 3;
localparam cpu_state_shift = 4;
localparam cpu_state_store = 5;
localparam cpu_state_stmem = 6;
localparam cpu_state_ldmem = 7;
reg [2:0] cpu_state;
reg force_mem_do_rinst;
reg force_mem_do_rdata;
reg force_mem_do_wdata;
reg mask_decoder_trigger;
reg force_decoder_trigger;
reg latched_is_lu;
reg latched_is_lh;
reg latched_is_lb;
reg [regindex_bits-1:0] latched_rd;
always @(posedge clk) begin
reg_sh <= 'bx;
reg_out <= 'bx;
force_mem_do_rinst = 0;
force_mem_do_rdata = 0;
force_mem_do_wdata = 0;
mask_decoder_trigger <= 0;
force_decoder_trigger <= 0;
if (ENABLE_COUNTERS)
count_cycle <= resetn ? count_cycle + 1 : 0;
if (!resetn) begin
trap <= 0;
reg_pc <= 0;
reg_op1 <= 'bx;
reg_op2 <= 'bx;
if (ENABLE_COUNTERS)
count_instr <= 0;
latched_is_lu <= 0;
latched_is_lh <= 0;
latched_is_lb <= 0;
cpu_state <= cpu_state_fetch;
end else
(* parallel_case, full_case *)
case (cpu_state)
cpu_state_fetch: begin
mem_do_rinst <= (!decoder_trigger || mask_decoder_trigger) && !trap && !force_decoder_trigger;
mem_do_prefetch <= 0;
mem_wordsize <= 0;
if (latched_is_lu || latched_is_lh || latched_is_lb) begin
`ifdef DEBUG
$display("ST_RD: %2d 0x%08x", latched_rd, reg_out);
`endif
cpuregs[latched_rd] <= reg_out;
end
latched_is_lu <= 0;
latched_is_lh <= 0;
latched_is_lb <= 0;
if ((decoder_trigger && !mask_decoder_trigger) || force_decoder_trigger) begin
`ifdef DEBUG
$display("DECODE: 0x%08x %-s", reg_pc, instruction);
`endif
if (instr_trap) begin
trap <= 1;
end else if (instr_fence) begin
mem_do_rinst <= 1;
reg_pc <= reg_pc + 4;
cpu_state <= cpu_state_fetch;
end else if (instr_jal) begin
mem_do_rinst <= 1;
reg_out <= reg_pc + 4;
if (latched_is_lu || latched_is_lh || latched_is_lb)
reg_pc <= reg_pc + decoded_imm;
else
reg_pc <= reg_pc + decoded_imm_uj;
latched_rd <= decoded_rd;
cpu_state <= cpu_state_store;
end else if (|{instr_rdcycle, instr_rdcycleh, instr_rdinstr, instr_rdinstrh}) begin
(* parallel_case, full_case *)
case (1'b1)
instr_rdcycle:
reg_out <= count_cycle[31:0];
instr_rdcycleh:
reg_out <= count_cycle[63:32];
instr_rdinstr:
reg_out <= count_instr[31:0];
instr_rdinstrh:
reg_out <= count_instr[63:32];
endcase
latched_rd <= decoded_rd;
cpu_state <= cpu_state_store;
end else begin
mem_do_prefetch <= !instr_jalr;
cpu_state <= cpu_state_ld_rs1;
end
if (ENABLE_COUNTERS)
count_instr <= count_instr + 1;
end
end
cpu_state_ld_rs1: begin
if (is_lui_auipc_jal) begin
reg_op1 <= instr_lui ? 0 : reg_pc;
reg_op2 <= decoded_imm;
mem_do_rinst <= mem_do_prefetch;
cpu_state <= cpu_state_exec;
end else begin
`ifdef DEBUG
$display("LD_RS1: %2d 0x%08x", decoded_rs1, decoded_rs1 ? cpuregs[decoded_rs1] : 0);
`endif
reg_op1 <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
if (is_lb_lh_lw_lbu_lhu) begin
cpu_state <= cpu_state_ldmem;
mem_do_rinst <= 1;
end else if (is_slli_srli_srai) begin
reg_sh <= decoded_rs2;
cpu_state <= cpu_state_shift;
end else if (is_jalr_addi_slti_sltiu_xori_ori_andi) begin
reg_op2 <= decoded_imm;
mem_do_rinst <= mem_do_prefetch;
cpu_state <= cpu_state_exec;
end else
cpu_state <= cpu_state_ld_rs2;
end
end
cpu_state_ld_rs2: begin
`ifdef DEBUG
$display("LD_RS2: %2d 0x%08x", decoded_rs2, decoded_rs2 ? cpuregs[decoded_rs2] : 0);
`endif
reg_op2 <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
if (is_sb_sh_sw) begin
cpu_state <= cpu_state_stmem;
mem_do_rinst <= 1;
end else if (is_sll_srl_sra) begin
reg_sh <= decoded_rs2 ? cpuregs[decoded_rs2] : 0;
cpu_state <= cpu_state_shift;
end else begin
mem_do_rinst <= mem_do_prefetch;
cpu_state <= cpu_state_exec;
end
end
cpu_state_exec: begin
(* parallel_case, full_case *)
case (1'b1)
is_lui_auipc_jal_jalr_addi_add:
reg_out <= reg_op1 + reg_op2;
instr_sub:
reg_out <= reg_op1 - reg_op2;
instr_beq:
reg_out <= {31'bx, reg_op1 == reg_op2};
instr_bne:
reg_out <= {31'bx, reg_op1 != reg_op2};
instr_bge:
reg_out <= {31'bx, $signed(reg_op1) >= $signed(reg_op2)};
instr_bgeu:
reg_out <= {31'bx, reg_op1 >= reg_op2};
is_slti_blt_slt:
reg_out <= $signed(reg_op1) < $signed(reg_op2);
is_sltiu_bltu_sltu:
reg_out <= reg_op1 < reg_op2;
instr_xori || instr_xor:
reg_out <= reg_op1 ^ reg_op2;
instr_ori || instr_or:
reg_out <= reg_op1 | reg_op2;
instr_andi || instr_and:
reg_out <= reg_op1 & reg_op2;
endcase
latched_rd <= decoded_rd;
cpu_state <= cpu_state_store;
end
cpu_state_shift: begin
if (reg_sh == 0) begin
reg_out <= reg_op1;
mem_do_rinst <= mem_do_prefetch;
latched_rd <= decoded_rd;
cpu_state <= cpu_state_store;
end else if (reg_sh >= 4) begin
(* parallel_case, full_case *)
case (1'b1)
instr_slli || instr_sll: reg_op1 <= reg_op1 << 4;
instr_srli || instr_srl: reg_op1 <= reg_op1 >> 4;
instr_srai || instr_sra: reg_op1 <= $signed(reg_op1) >>> 4;
endcase
reg_sh <= reg_sh - 4;
end else begin
(* parallel_case, full_case *)
case (1'b1)
instr_slli || instr_sll: reg_op1 <= reg_op1 << 1;
instr_srli || instr_srl: reg_op1 <= reg_op1 >> 1;
instr_srai || instr_sra: reg_op1 <= $signed(reg_op1) >>> 1;
endcase
reg_sh <= reg_sh - 1;
end
end
cpu_state_store: begin
mem_do_rinst <= mem_do_prefetch || mem_do_rinst;
cpu_state <= cpu_state_fetch;
if (instr_jal) begin
`ifdef DEBUG
$display("ST_RD: %2d 0x%08x", latched_rd, reg_out);
`endif
cpuregs[latched_rd] <= reg_out;
end else if (instr_jalr) begin
`ifdef DEBUG
$display("ST_RD: %2d 0x%08x", latched_rd, reg_pc + 4);
`endif
cpuregs[latched_rd] <= reg_pc + 4;
reg_pc <= reg_out;
end else if (is_beq_bne_blt_bge_bltu_bgeu) begin
if (reg_out_0) begin
if (mem_done) begin
force_mem_do_rinst = 1;
mask_decoder_trigger <= 1;
reg_pc <= reg_pc + decoded_imm;
end else begin
/* waiting for mem_done */
cpu_state <= cpu_state_store;
reg_out[0] <= reg_out_0;
end
end else
reg_pc <= reg_pc + 4;
end else begin
`ifdef DEBUG
$display("ST_RD: %2d 0x%08x", latched_rd, reg_out);
`endif
cpuregs[latched_rd] <= reg_out;
reg_pc <= reg_pc + 4;
end
end
cpu_state_stmem: begin
if (!mem_do_prefetch || mem_done) begin
if (!mem_do_wdata) begin
(* parallel_case, full_case *)
case (1'b1)
instr_sb: mem_wordsize <= 2;
instr_sh: mem_wordsize <= 1;
instr_sw: mem_wordsize <= 0;
endcase
reg_op1 <= reg_op1 + decoded_imm;
force_mem_do_wdata = 1;
end
if (!mem_do_prefetch && mem_done) begin
reg_pc <= reg_pc + 4;
cpu_state <= cpu_state_fetch;
force_decoder_trigger <= 1;
end
end
end
cpu_state_ldmem: begin
if (!mem_do_prefetch || mem_done) begin
if (!mem_do_rdata) begin
(* parallel_case, full_case *)
case (1'b1)
instr_lb || instr_lbu: mem_wordsize <= 2;
instr_lh || instr_lhu: mem_wordsize <= 1;
instr_lw: mem_wordsize <= 0;
endcase
latched_is_lu <= is_lbu_lhu_lw;
latched_is_lh <= instr_lh;
latched_is_lb <= instr_lb;
latched_rd <= decoded_rd;
reg_op1 <= reg_op1 + decoded_imm;
force_mem_do_rdata = 1;
end
if (!mem_do_prefetch && mem_done) begin
(* parallel_case, full_case *)
case (1'b1)
latched_is_lu: reg_out <= mem_buffer;
latched_is_lh: reg_out <= $signed(mem_buffer[15:0]);
latched_is_lb: reg_out <= $signed(mem_buffer[7:0]);
endcase
reg_pc <= reg_pc + 4;
force_decoder_trigger <= 1;
cpu_state <= cpu_state_fetch;
end
end
end
endcase
if (resetn && (mem_do_rdata || mem_do_wdata)) begin
if (mem_wordsize == 0 && reg_op1[1:0] != 0) begin
`ifdef DEBUG
$display("MISALIGNED WORD: 0x%08x", reg_op1);
`endif
trap <= 1;
end
if (mem_wordsize == 1 && reg_op1[0] != 0) begin
`ifdef DEBUG
$display("MISALIGNED HALFWORD: 0x%08x", reg_op1);
`endif
trap <= 1;
end
end
if (resetn && mem_do_rinst && reg_pc[1:0] != 0) begin
`ifdef DEBUG
$display("MISALIGNED INSTRUCTION: 0x%08x", reg_pc);
`endif
trap <= 1;
end
if (!resetn || mem_done) begin
mem_do_prefetch <= 0;
mem_do_rinst <= 0;
mem_do_rdata <= 0;
mem_do_wdata <= 0;
end
if (force_mem_do_rinst)
mem_do_rinst <= 1;
if (force_mem_do_rdata)
mem_do_rdata <= 1;
if (force_mem_do_wdata)
mem_do_wdata <= 1;
// optimize for 32bit instr alignment
reg_pc[1:0] <= 0;
end
endmodule
/***************************************************************
* picorv32_axi
***************************************************************/
module picorv32_axi #(
parameter ENABLE_COUNTERS = 1,
parameter ENABLE_REGS_16_31 = 1
) (
input clk, resetn,
output trap,
// AXI4-lite master memory interface
output mem_axi_awvalid,
input mem_axi_awready,
output [31:0] mem_axi_awaddr,
output [ 2:0] mem_axi_awprot,
output mem_axi_wvalid,
input mem_axi_wready,
output [31:0] mem_axi_wdata,
output [ 3:0] mem_axi_wstrb,
input mem_axi_bvalid,
output mem_axi_bready,
output mem_axi_arvalid,
input mem_axi_arready,
output [31:0] mem_axi_araddr,
output [ 2:0] mem_axi_arprot,
input mem_axi_rvalid,
output mem_axi_rready,
input [31:0] mem_axi_rdata
);
wire mem_valid;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [ 3:0] mem_wstrb;
wire mem_instr;
wire mem_ready;
wire [31:0] mem_rdata;
picorv32_axi_adapter axi_adapter (
.clk (clk ),
.resetn (resetn ),
.mem_axi_awvalid(mem_axi_awvalid),
.mem_axi_awready(mem_axi_awready),
.mem_axi_awaddr (mem_axi_awaddr ),
.mem_axi_awprot (mem_axi_awprot ),
.mem_axi_wvalid (mem_axi_wvalid ),
.mem_axi_wready (mem_axi_wready ),
.mem_axi_wdata (mem_axi_wdata ),
.mem_axi_wstrb (mem_axi_wstrb ),
.mem_axi_bvalid (mem_axi_bvalid ),
.mem_axi_bready (mem_axi_bready ),
.mem_axi_arvalid(mem_axi_arvalid),
.mem_axi_arready(mem_axi_arready),
.mem_axi_araddr (mem_axi_araddr ),
.mem_axi_arprot (mem_axi_arprot ),
.mem_axi_rvalid (mem_axi_rvalid ),
.mem_axi_rready (mem_axi_rready ),
.mem_axi_rdata (mem_axi_rdata ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata )
);
picorv32 #(
.ENABLE_COUNTERS (ENABLE_COUNTERS ),
.ENABLE_REGS_16_31(ENABLE_REGS_16_31)
) picorv32_core (
.clk (clk ),
.resetn (resetn ),
.trap (trap ),
.mem_valid(mem_valid),
.mem_addr (mem_addr ),
.mem_wdata(mem_wdata),
.mem_wstrb(mem_wstrb),
.mem_instr(mem_instr),
.mem_ready(mem_ready),
.mem_rdata(mem_rdata)
);
endmodule
/***************************************************************
* picorv32_axi_adapter
***************************************************************/
module picorv32_axi_adapter (
input clk, resetn,
// AXI4-lite master memory interface
output mem_axi_awvalid,
input mem_axi_awready,
output [31:0] mem_axi_awaddr,
output [ 2:0] mem_axi_awprot,
output mem_axi_wvalid,
input mem_axi_wready,
output [31:0] mem_axi_wdata,
output [ 3:0] mem_axi_wstrb,
input mem_axi_bvalid,
output mem_axi_bready,
output mem_axi_arvalid,
input mem_axi_arready,
output [31:0] mem_axi_araddr,
output [ 2:0] mem_axi_arprot,
input mem_axi_rvalid,
output mem_axi_rready,
input [31:0] mem_axi_rdata,
// Native PicoRV32 memory interface
input mem_valid,
input mem_instr,
output mem_ready,
input [31:0] mem_addr,
input [31:0] mem_wdata,
input [ 3:0] mem_wstrb,
output [31:0] mem_rdata
);
reg ack_awvalid;
reg ack_arvalid;
reg ack_wvalid;
assign mem_axi_awvalid = mem_valid && |mem_wstrb && !ack_awvalid;
assign mem_axi_awaddr = mem_addr;
assign mem_axi_awprot = 0;
assign mem_axi_arvalid = mem_valid && ~|mem_wstrb && !ack_arvalid;
assign mem_axi_araddr = mem_addr;
assign mem_axi_arprot = mem_instr ? 3'b100 : 3'b000;
assign mem_axi_wvalid = mem_valid && |mem_wstrb && !ack_wvalid;
assign mem_axi_wdata = mem_wdata;
assign mem_axi_wstrb = mem_wstrb;
assign mem_ready = mem_axi_bvalid || mem_axi_rvalid;
assign mem_axi_bready = mem_valid;
assign mem_axi_rready = mem_valid;
assign mem_rdata = mem_axi_rdata;
always @(posedge clk) begin
if (!resetn) begin
ack_awvalid <= 0;
end else begin
if (mem_axi_awready && mem_axi_awvalid)
ack_awvalid <= 1;
if (mem_axi_arready && mem_axi_arvalid)
ack_arvalid <= 1;
if (mem_axi_wready && mem_axi_wvalid)
ack_wvalid <= 1;
if (!mem_valid) begin
ack_awvalid <= 0;
ack_arvalid <= 0;
ack_wvalid <= 0;
end
end
end
endmodule

16
synth_vivado.tcl Normal file
View File

@ -0,0 +1,16 @@
# vivado -nojournal -log synth_vivado.log -mode batch -source synth_vivado.tcl
read_verilog picorv32.v
read_xdc synth_vivado.xdc
synth_design -part xc7a15t-csg324 -top picorv32_axi
opt_design
place_design
route_design
report_utilization
report_timing
write_verilog -force synth_vivado.v

1
synth_vivado.xdc Normal file
View File

@ -0,0 +1 @@
create_clock -period 4.00 [get_ports clk]

148
testbench.v Normal file
View File

@ -0,0 +1,148 @@
`timescale 1 ns / 1 ps
// `define VERBOSE
// `define RANDOM_AXI_DELAYS
module testbench;
reg clk = 1;
reg resetn = 0;
wire trap;
always #5 clk = ~clk;
initial begin
repeat (100) @(posedge clk);
resetn <= 1;
end
wire mem_axi_awvalid;
reg mem_axi_awready = 0;
wire [31:0] mem_axi_awaddr;
wire [ 2:0] mem_axi_awprot;
wire mem_axi_wvalid;
reg mem_axi_wready = 0;
wire [31:0] mem_axi_wdata;
wire [ 3:0] mem_axi_wstrb;
reg mem_axi_bvalid = 0;
wire mem_axi_bready;
wire mem_axi_arvalid;
reg mem_axi_arready = 0;
wire [31:0] mem_axi_araddr;
wire [ 2:0] mem_axi_arprot;
reg mem_axi_rvalid = 0;
wire mem_axi_rready;
reg [31:0] mem_axi_rdata;
picorv32_axi uut (
.clk (clk ),
.resetn (resetn ),
.trap (trap ),
.mem_axi_awvalid(mem_axi_awvalid),
.mem_axi_awready(mem_axi_awready),
.mem_axi_awaddr (mem_axi_awaddr ),
.mem_axi_awprot (mem_axi_awprot ),
.mem_axi_wvalid (mem_axi_wvalid ),
.mem_axi_wready (mem_axi_wready ),
.mem_axi_wdata (mem_axi_wdata ),
.mem_axi_wstrb (mem_axi_wstrb ),
.mem_axi_bvalid (mem_axi_bvalid ),
.mem_axi_bready (mem_axi_bready ),
.mem_axi_arvalid(mem_axi_arvalid),
.mem_axi_arready(mem_axi_arready),
.mem_axi_araddr (mem_axi_araddr ),
.mem_axi_arprot (mem_axi_arprot ),
.mem_axi_rvalid (mem_axi_rvalid ),
.mem_axi_rready (mem_axi_rready ),
.mem_axi_rdata (mem_axi_rdata )
);
reg [31:0] memory [0:64*1024/4-1];
initial $readmemh("firmware/firmware.hex", memory);
reg [63:0] xorshift64_state = 64'd88172645463325252;
task xorshift64_next;
begin
// see page 4 of Marsaglia, George (July 2003). "Xorshift RNGs". Journal of Statistical Software 8 (14).
xorshift64_state = xorshift64_state ^ (xorshift64_state << 13);
xorshift64_state = xorshift64_state ^ (xorshift64_state >> 7);
xorshift64_state = xorshift64_state ^ (xorshift64_state << 17);
end
endtask
reg delay_axi_transaction = 0;
`ifdef RANDOM_AXI_DELAYS
always @(posedge clk) begin
xorshift64_next;
delay_axi_transaction <= xorshift64_state[0];
end
`endif
always @(posedge clk) begin
mem_axi_awready <= 0;
mem_axi_wready <= 0;
mem_axi_arready <= 0;
if (!mem_axi_bvalid || mem_axi_bready) begin
mem_axi_bvalid <= 0;
if (mem_axi_awvalid && mem_axi_wvalid && !mem_axi_awready && !mem_axi_wready && !delay_axi_transaction) begin
`ifdef VERBOSE
$display("WR: ADDR=%08x DATA=%08x STRB=%04b", mem_axi_awaddr, mem_axi_wdata, mem_axi_wstrb);
`endif
if (mem_axi_awaddr < 64*1024) begin
if (mem_axi_wstrb[0]) memory[mem_axi_awaddr >> 2][ 7: 0] <= mem_axi_wdata[ 7: 0];
if (mem_axi_wstrb[1]) memory[mem_axi_awaddr >> 2][15: 8] <= mem_axi_wdata[15: 8];
if (mem_axi_wstrb[2]) memory[mem_axi_awaddr >> 2][23:16] <= mem_axi_wdata[23:16];
if (mem_axi_wstrb[3]) memory[mem_axi_awaddr >> 2][31:24] <= mem_axi_wdata[31:24];
end
if (mem_axi_awaddr == 32'h1000_0000) begin
`ifdef VERBOSE
if (32 <= mem_axi_wdata && mem_axi_wdata < 128)
$display("OUT: '%c'", mem_axi_wdata);
else
$display("OUT: %3d", mem_axi_wdata);
`else
$write("%c", mem_axi_wdata);
$fflush();
`endif
end
mem_axi_awready <= 1;
mem_axi_wready <= 1;
mem_axi_bvalid <= 1;
end
end
if (!mem_axi_rvalid || mem_axi_rready) begin
mem_axi_rvalid <= 0;
if (mem_axi_arvalid && !mem_axi_arready && !delay_axi_transaction) begin
`ifdef VERBOSE
$display("RD: ADDR=%08x DATA=%08x", mem_axi_araddr, memory[mem_axi_araddr >> 2]);
`endif
mem_axi_arready <= 1;
mem_axi_rdata <= memory[mem_axi_araddr >> 2];
mem_axi_rvalid <= 1;
end
end
end
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
repeat (1000000) @(posedge clk);
$display("TIMEOUT");
$finish;
end
always @(posedge clk) begin
if (resetn && trap) begin
repeat (10) @(posedge clk);
$display("TRAP");
$finish;
end
end
endmodule

24
tests/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.

85
tests/add.S Normal file
View File

@ -0,0 +1,85 @@
# See LICENSE for license details.
#*****************************************************************************
# add.S
#-----------------------------------------------------------------------------
#
# Test add instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, add, 0x00000000, 0x00000000, 0x00000000 );
TEST_RR_OP( 3, add, 0x00000002, 0x00000001, 0x00000001 );
TEST_RR_OP( 4, add, 0x0000000a, 0x00000003, 0x00000007 );
TEST_RR_OP( 5, add, 0xffff8000, 0x00000000, 0xffff8000 );
TEST_RR_OP( 6, add, 0x80000000, 0x80000000, 0x00000000 );
TEST_RR_OP( 7, add, 0x7fff8000, 0x80000000, 0xffff8000 );
TEST_RR_OP( 8, add, 0x00007fff, 0x00000000, 0x00007fff );
TEST_RR_OP( 9, add, 0x7fffffff, 0x7fffffff, 0x00000000 );
TEST_RR_OP( 10, add, 0x80007ffe, 0x7fffffff, 0x00007fff );
TEST_RR_OP( 11, add, 0x80007fff, 0x80000000, 0x00007fff );
TEST_RR_OP( 12, add, 0x7fff7fff, 0x7fffffff, 0xffff8000 );
TEST_RR_OP( 13, add, 0xffffffff, 0x00000000, 0xffffffff );
TEST_RR_OP( 14, add, 0x00000000, 0xffffffff, 0x00000001 );
TEST_RR_OP( 15, add, 0xfffffffe, 0xffffffff, 0xffffffff );
TEST_RR_OP( 16, add, 0x80000000, 0x00000001, 0x7fffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 17, add, 24, 13, 11 );
TEST_RR_SRC2_EQ_DEST( 18, add, 25, 14, 11 );
TEST_RR_SRC12_EQ_DEST( 19, add, 26, 13 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 20, 0, add, 24, 13, 11 );
TEST_RR_DEST_BYPASS( 21, 1, add, 25, 14, 11 );
TEST_RR_DEST_BYPASS( 22, 2, add, 26, 15, 11 );
TEST_RR_SRC12_BYPASS( 23, 0, 0, add, 24, 13, 11 );
TEST_RR_SRC12_BYPASS( 24, 0, 1, add, 25, 14, 11 );
TEST_RR_SRC12_BYPASS( 25, 0, 2, add, 26, 15, 11 );
TEST_RR_SRC12_BYPASS( 26, 1, 0, add, 24, 13, 11 );
TEST_RR_SRC12_BYPASS( 27, 1, 1, add, 25, 14, 11 );
TEST_RR_SRC12_BYPASS( 28, 2, 0, add, 26, 15, 11 );
TEST_RR_SRC21_BYPASS( 29, 0, 0, add, 24, 13, 11 );
TEST_RR_SRC21_BYPASS( 30, 0, 1, add, 25, 14, 11 );
TEST_RR_SRC21_BYPASS( 31, 0, 2, add, 26, 15, 11 );
TEST_RR_SRC21_BYPASS( 32, 1, 0, add, 24, 13, 11 );
TEST_RR_SRC21_BYPASS( 33, 1, 1, add, 25, 14, 11 );
TEST_RR_SRC21_BYPASS( 34, 2, 0, add, 26, 15, 11 );
TEST_RR_ZEROSRC1( 35, add, 15, 15 );
TEST_RR_ZEROSRC2( 36, add, 32, 32 );
TEST_RR_ZEROSRC12( 37, add, 0 );
TEST_RR_ZERODEST( 38, add, 16, 30 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

71
tests/addi.S Normal file
View File

@ -0,0 +1,71 @@
# See LICENSE for license details.
#*****************************************************************************
# addi.S
#-----------------------------------------------------------------------------
#
# Test addi instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, addi, 0x00000000, 0x00000000, 0x000 );
TEST_IMM_OP( 3, addi, 0x00000002, 0x00000001, 0x001 );
TEST_IMM_OP( 4, addi, 0x0000000a, 0x00000003, 0x007 );
TEST_IMM_OP( 5, addi, 0xfffff800, 0x00000000, 0x800 );
TEST_IMM_OP( 6, addi, 0x80000000, 0x80000000, 0x000 );
TEST_IMM_OP( 7, addi, 0x7ffff800, 0x80000000, 0x800 );
TEST_IMM_OP( 8, addi, 0x000007ff, 0x00000000, 0x7ff );
TEST_IMM_OP( 9, addi, 0x7fffffff, 0x7fffffff, 0x000 );
TEST_IMM_OP( 10, addi, 0x800007fe, 0x7fffffff, 0x7ff );
TEST_IMM_OP( 11, addi, 0x800007ff, 0x80000000, 0x7ff );
TEST_IMM_OP( 12, addi, 0x7ffff7ff, 0x7fffffff, 0x800 );
TEST_IMM_OP( 13, addi, 0xffffffff, 0x00000000, 0xfff );
TEST_IMM_OP( 14, addi, 0x00000000, 0xffffffff, 0x001 );
TEST_IMM_OP( 15, addi, 0xfffffffe, 0xffffffff, 0xfff );
TEST_IMM_OP( 16, addi, 0x80000000, 0x7fffffff, 0x001 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 17, addi, 24, 13, 11 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 18, 0, addi, 24, 13, 11 );
TEST_IMM_DEST_BYPASS( 19, 1, addi, 23, 13, 10 );
TEST_IMM_DEST_BYPASS( 20, 2, addi, 22, 13, 9 );
TEST_IMM_SRC1_BYPASS( 21, 0, addi, 24, 13, 11 );
TEST_IMM_SRC1_BYPASS( 22, 1, addi, 23, 13, 10 );
TEST_IMM_SRC1_BYPASS( 23, 2, addi, 22, 13, 9 );
TEST_IMM_ZEROSRC1( 24, addi, 32, 32 );
TEST_IMM_ZERODEST( 25, addi, 33, 50 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

69
tests/and.S Normal file
View File

@ -0,0 +1,69 @@
# See LICENSE for license details.
#*****************************************************************************
# and.S
#-----------------------------------------------------------------------------
#
# Test and instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_RR_OP( 2, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_OP( 3, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_OP( 4, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_OP( 5, and, 0xf000f000, 0xf00ff00f, 0xf0f0f0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 6, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC2_EQ_DEST( 7, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_EQ_DEST( 8, and, 0xff00ff00, 0xff00ff00 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 9, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_DEST_BYPASS( 10, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_DEST_BYPASS( 11, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 12, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 13, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 14, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 15, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 16, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 17, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 18, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 19, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 20, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 21, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 22, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 23, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_ZEROSRC1( 24, and, 0, 0xff00ff00 );
TEST_RR_ZEROSRC2( 25, and, 0, 0x00ff00ff );
TEST_RR_ZEROSRC12( 26, and, 0 );
TEST_RR_ZERODEST( 27, and, 0x11111111, 0x22222222 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

55
tests/andi.S Normal file
View File

@ -0,0 +1,55 @@
# See LICENSE for license details.
#*****************************************************************************
# andi.S
#-----------------------------------------------------------------------------
#
# Test andi instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, andi, 0xff00ff00, 0xff00ff00, 0xf0f );
TEST_IMM_OP( 3, andi, 0x000000f0, 0x0ff00ff0, 0x0f0 );
TEST_IMM_OP( 4, andi, 0x0000000f, 0x00ff00ff, 0x70f );
TEST_IMM_OP( 5, andi, 0x00000000, 0xf00ff00f, 0x0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 6, andi, 0x00000000, 0xff00ff00, 0x0f0 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 7, 0, andi, 0x00000700, 0x0ff00ff0, 0x70f );
TEST_IMM_DEST_BYPASS( 8, 1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 );
TEST_IMM_DEST_BYPASS( 9, 2, andi, 0xf00ff00f, 0xf00ff00f, 0xf0f );
TEST_IMM_SRC1_BYPASS( 10, 0, andi, 0x00000700, 0x0ff00ff0, 0x70f );
TEST_IMM_SRC1_BYPASS( 11, 1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 );
TEST_IMM_SRC1_BYPASS( 12, 2, andi, 0x0000000f, 0xf00ff00f, 0x70f );
TEST_IMM_ZEROSRC1( 13, andi, 0, 0x0f0 );
TEST_IMM_ZERODEST( 14, andi, 0x00ff00ff, 0x70f );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

39
tests/auipc.S Normal file
View File

@ -0,0 +1,39 @@
# See LICENSE for license details.
#*****************************************************************************
# auipc.S
#-----------------------------------------------------------------------------
#
# Test auipc instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
TEST_CASE(2, a0, 10000, \
.align 3; \
lla a0, 1f + 10000; \
jal a1, 1f; \
1: sub a0, a0, a1; \
)
TEST_CASE(3, a0, -10000, \
.align 3; \
lla a0, 1f - 10000; \
jal a1, 1f; \
1: sub a0, a0, a1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

73
tests/beq.S Normal file
View File

@ -0,0 +1,73 @@
# See LICENSE for license details.
#*****************************************************************************
# beq.S
#-----------------------------------------------------------------------------
#
# Test beq instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, beq, 0, 0 );
TEST_BR2_OP_TAKEN( 3, beq, 1, 1 );
TEST_BR2_OP_TAKEN( 4, beq, -1, -1 );
TEST_BR2_OP_NOTTAKEN( 5, beq, 0, 1 );
TEST_BR2_OP_NOTTAKEN( 6, beq, 1, 0 );
TEST_BR2_OP_NOTTAKEN( 7, beq, -1, 1 );
TEST_BR2_OP_NOTTAKEN( 8, beq, 1, -1 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 9, 0, 0, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 10, 0, 1, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 11, 0, 2, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 12, 1, 0, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 13, 1, 1, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 14, 2, 0, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 15, 0, 0, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 16, 0, 1, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 17, 0, 2, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 18, 1, 0, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 19, 1, 1, beq, 0, -1 );
TEST_BR2_SRC12_BYPASS( 20, 2, 0, beq, 0, -1 );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 21, x1, 3, \
li x1, 1; \
beq x0, x0, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

76
tests/bge.S Normal file
View File

@ -0,0 +1,76 @@
# See LICENSE for license details.
#*****************************************************************************
# bge.S
#-----------------------------------------------------------------------------
#
# Test bge instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, bge, 0, 0 );
TEST_BR2_OP_TAKEN( 3, bge, 1, 1 );
TEST_BR2_OP_TAKEN( 4, bge, -1, -1 );
TEST_BR2_OP_TAKEN( 5, bge, 1, 0 );
TEST_BR2_OP_TAKEN( 6, bge, 1, -1 );
TEST_BR2_OP_TAKEN( 7, bge, -1, -2 );
TEST_BR2_OP_NOTTAKEN( 8, bge, 0, 1 );
TEST_BR2_OP_NOTTAKEN( 9, bge, -1, 1 );
TEST_BR2_OP_NOTTAKEN( 10, bge, -2, -1 );
TEST_BR2_OP_NOTTAKEN( 11, bge, -2, 1 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 12, 0, 0, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 13, 0, 1, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 14, 0, 2, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 15, 1, 0, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 16, 1, 1, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 17, 2, 0, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 18, 0, 0, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 19, 0, 1, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 20, 0, 2, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 21, 1, 0, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 22, 1, 1, bge, -1, 0 );
TEST_BR2_SRC12_BYPASS( 23, 2, 0, bge, -1, 0 );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 24, x1, 3, \
li x1, 1; \
bge x1, x0, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

76
tests/bgeu.S Normal file
View File

@ -0,0 +1,76 @@
# See LICENSE for license details.
#*****************************************************************************
# bgeu.S
#-----------------------------------------------------------------------------
#
# Test bgeu instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, bgeu, 0x00000000, 0x00000000 );
TEST_BR2_OP_TAKEN( 3, bgeu, 0x00000001, 0x00000001 );
TEST_BR2_OP_TAKEN( 4, bgeu, 0xffffffff, 0xffffffff );
TEST_BR2_OP_TAKEN( 5, bgeu, 0x00000001, 0x00000000 );
TEST_BR2_OP_TAKEN( 6, bgeu, 0xffffffff, 0xfffffffe );
TEST_BR2_OP_TAKEN( 7, bgeu, 0xffffffff, 0x00000000 );
TEST_BR2_OP_NOTTAKEN( 8, bgeu, 0x00000000, 0x00000001 );
TEST_BR2_OP_NOTTAKEN( 9, bgeu, 0xfffffffe, 0xffffffff );
TEST_BR2_OP_NOTTAKEN( 10, bgeu, 0x00000000, 0xffffffff );
TEST_BR2_OP_NOTTAKEN( 11, bgeu, 0x7fffffff, 0x80000000 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 12, 0, 0, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 13, 0, 1, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 14, 0, 2, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 15, 1, 0, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 16, 1, 1, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 17, 2, 0, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 18, 0, 0, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 19, 0, 1, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 20, 0, 2, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 21, 1, 0, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 22, 1, 1, bgeu, 0xefffffff, 0xf0000000 );
TEST_BR2_SRC12_BYPASS( 23, 2, 0, bgeu, 0xefffffff, 0xf0000000 );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 24, x1, 3, \
li x1, 1; \
bgeu x1, x0, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

73
tests/blt.S Normal file
View File

@ -0,0 +1,73 @@
# See LICENSE for license details.
#*****************************************************************************
# blt.S
#-----------------------------------------------------------------------------
#
# Test blt instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, blt, 0, 1 );
TEST_BR2_OP_TAKEN( 3, blt, -1, 1 );
TEST_BR2_OP_TAKEN( 4, blt, -2, -1 );
TEST_BR2_OP_NOTTAKEN( 5, blt, 1, 0 );
TEST_BR2_OP_NOTTAKEN( 6, blt, 1, -1 );
TEST_BR2_OP_NOTTAKEN( 7, blt, -1, -2 );
TEST_BR2_OP_NOTTAKEN( 8, blt, 1, -2 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 9, 0, 0, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 10, 0, 1, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 11, 0, 2, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 12, 1, 0, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 13, 1, 1, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 14, 2, 0, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 15, 0, 0, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 16, 0, 1, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 17, 0, 2, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 18, 1, 0, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 19, 1, 1, blt, 0, -1 );
TEST_BR2_SRC12_BYPASS( 20, 2, 0, blt, 0, -1 );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 21, x1, 3, \
li x1, 1; \
blt x0, x1, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

73
tests/bltu.S Normal file
View File

@ -0,0 +1,73 @@
# See LICENSE for license details.
#*****************************************************************************
# bltu.S
#-----------------------------------------------------------------------------
#
# Test bltu instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, bltu, 0x00000000, 0x00000001 );
TEST_BR2_OP_TAKEN( 3, bltu, 0xfffffffe, 0xffffffff );
TEST_BR2_OP_TAKEN( 4, bltu, 0x00000000, 0xffffffff );
TEST_BR2_OP_NOTTAKEN( 5, bltu, 0x00000001, 0x00000000 );
TEST_BR2_OP_NOTTAKEN( 6, bltu, 0xffffffff, 0xfffffffe );
TEST_BR2_OP_NOTTAKEN( 7, bltu, 0xffffffff, 0x00000000 );
TEST_BR2_OP_NOTTAKEN( 8, bltu, 0x80000000, 0x7fffffff );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 9, 0, 0, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 10, 0, 1, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 11, 0, 2, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 12, 1, 0, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 13, 1, 1, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 14, 2, 0, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 15, 0, 0, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 16, 0, 1, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 17, 0, 2, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 18, 1, 0, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 19, 1, 1, bltu, 0xf0000000, 0xefffffff );
TEST_BR2_SRC12_BYPASS( 20, 2, 0, bltu, 0xf0000000, 0xefffffff );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 21, x1, 3, \
li x1, 1; \
bltu x0, x1, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

73
tests/bne.S Normal file
View File

@ -0,0 +1,73 @@
# See LICENSE for license details.
#*****************************************************************************
# bne.S
#-----------------------------------------------------------------------------
#
# Test bne instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Branch tests
#-------------------------------------------------------------
# Each test checks both forward and backward branches
TEST_BR2_OP_TAKEN( 2, bne, 0, 1 );
TEST_BR2_OP_TAKEN( 3, bne, 1, 0 );
TEST_BR2_OP_TAKEN( 4, bne, -1, 1 );
TEST_BR2_OP_TAKEN( 5, bne, 1, -1 );
TEST_BR2_OP_NOTTAKEN( 6, bne, 0, 0 );
TEST_BR2_OP_NOTTAKEN( 7, bne, 1, 1 );
TEST_BR2_OP_NOTTAKEN( 8, bne, -1, -1 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_BR2_SRC12_BYPASS( 9, 0, 0, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 10, 0, 1, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 11, 0, 2, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 12, 1, 0, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 13, 1, 1, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 14, 2, 0, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 15, 0, 0, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 16, 0, 1, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 17, 0, 2, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 18, 1, 0, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 19, 1, 1, bne, 0, 0 );
TEST_BR2_SRC12_BYPASS( 20, 2, 0, bne, 0, 0 );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 21, x1, 3, \
li x1, 1; \
bne x1, x0, 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

53
tests/fence_i.S Normal file
View File

@ -0,0 +1,53 @@
# See LICENSE for license details.
#*****************************************************************************
# fence_i.S
#-----------------------------------------------------------------------------
#
# Test self-modifying code and the fence.i instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
li a3, 111
la a0, 3f
la a1, 1f
la a2, 2f
lw a0, 0(a0)
# test I$ hit
.align 6
sw a0, 0(a1)
fence.i
1: addi a3, a3, 222
TEST_CASE( 2, a3, 444, nop )
# test prefetcher hit
li a4, 100
1: addi a4, a4, -1
bnez a4, 1b
sw a0, 0(a2)
fence.i
.align 6
2: addi a3, a3, 555
TEST_CASE( 3, a3, 777, nop )
3: addi a3, a3, 333
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

49
tests/j.S Normal file
View File

@ -0,0 +1,49 @@
# See LICENSE for license details.
#*****************************************************************************
# j.S
#-----------------------------------------------------------------------------
#
# Test j instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Test basic
#-------------------------------------------------------------
li TESTNUM, 2;
j test_2;
j fail;
test_2:
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 3, x1, 3, \
li x1, 1; \
j 1f; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

60
tests/jal.S Normal file
View File

@ -0,0 +1,60 @@
# See LICENSE for license details.
#*****************************************************************************
# jal.S
#-----------------------------------------------------------------------------
#
# Test jal instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Test 2: Basic test
#-------------------------------------------------------------
test_2:
li TESTNUM, 2
li ra, 0
linkaddr_2:
jal target_2
nop
nop
j fail
target_2:
la x2, linkaddr_2
addi x2, x2, 4
bne x2, ra, fail
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 3, x2, 3, \
li x2, 1; \
jal 1f; \
addi x2, x2, 1; \
addi x2, x2, 1; \
addi x2, x2, 1; \
addi x2, x2, 1; \
1: addi x2, x2, 1; \
addi x2, x2, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

88
tests/jalr.S Normal file
View File

@ -0,0 +1,88 @@
# See LICENSE for license details.
#*****************************************************************************
# jalr.S
#-----------------------------------------------------------------------------
#
# Test jalr instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Test 2: Basic test
#-------------------------------------------------------------
test_2:
li TESTNUM, 2
li x31, 0
la x2, target_2
linkaddr_2:
jalr x19, x2, 0
nop
nop
j fail
target_2:
la x1, linkaddr_2
addi x1, x1, 4
bne x1, x19, fail
#-------------------------------------------------------------
# Test 3: Check r0 target and that r31 is not modified
#-------------------------------------------------------------
test_3:
li TESTNUM, 3
li x31, 0
la x3, target_3
linkaddr_3:
jalr x0, x3, 0
nop
j fail
target_3:
bne x31, x0, fail
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_JALR_SRC1_BYPASS( 4, 0, jalr );
TEST_JALR_SRC1_BYPASS( 5, 1, jalr );
TEST_JALR_SRC1_BYPASS( 6, 2, jalr );
#-------------------------------------------------------------
# Test delay slot instructions not executed nor bypassed
#-------------------------------------------------------------
TEST_CASE( 7, x1, 4, \
li x1, 1; \
la x2, 1f;
jalr x19, x2, -4; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
addi x1, x1, 1; \
1: addi x1, x1, 1; \
addi x1, x1, 1; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

92
tests/lb.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# lb.S
#-----------------------------------------------------------------------------
#
# Test lb instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_LD_OP( 2, lb, 0xffffffff, 0, tdat );
TEST_LD_OP( 3, lb, 0x00000000, 1, tdat );
TEST_LD_OP( 4, lb, 0xfffffff0, 2, tdat );
TEST_LD_OP( 5, lb, 0x0000000f, 3, tdat );
# Test with negative offset
TEST_LD_OP( 6, lb, 0xffffffff, -3, tdat4 );
TEST_LD_OP( 7, lb, 0x00000000, -2, tdat4 );
TEST_LD_OP( 8, lb, 0xfffffff0, -1, tdat4 );
TEST_LD_OP( 9, lb, 0x0000000f, 0, tdat4 );
# Test with a negative base
TEST_CASE( 10, x3, 0xffffffff, \
la x1, tdat; \
addi x1, x1, -32; \
lb x3, 32(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0x00000000, \
la x1, tdat; \
addi x1, x1, -6; \
lb x3, 7(x1); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_LD_DEST_BYPASS( 12, 0, lb, 0xfffffff0, 1, tdat2 );
TEST_LD_DEST_BYPASS( 13, 1, lb, 0x0000000f, 1, tdat3 );
TEST_LD_DEST_BYPASS( 14, 2, lb, 0x00000000, 1, tdat1 );
TEST_LD_SRC1_BYPASS( 15, 0, lb, 0xfffffff0, 1, tdat2 );
TEST_LD_SRC1_BYPASS( 16, 1, lb, 0x0000000f, 1, tdat3 );
TEST_LD_SRC1_BYPASS( 17, 2, lb, 0x00000000, 1, tdat1 );
#-------------------------------------------------------------
# Test write-after-write hazard
#-------------------------------------------------------------
TEST_CASE( 18, x2, 2, \
la x3, tdat; \
lb x2, 0(x3); \
li x2, 2; \
)
TEST_CASE( 19, x2, 2, \
la x3, tdat; \
lb x2, 0(x3); \
nop; \
li x2, 2; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .byte 0xff
tdat2: .byte 0x00
tdat3: .byte 0xf0
tdat4: .byte 0x0f
RVTEST_DATA_END

92
tests/lbu.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# lbu.S
#-----------------------------------------------------------------------------
#
# Test lbu instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_LD_OP( 2, lbu, 0x000000ff, 0, tdat );
TEST_LD_OP( 3, lbu, 0x00000000, 1, tdat );
TEST_LD_OP( 4, lbu, 0x000000f0, 2, tdat );
TEST_LD_OP( 5, lbu, 0x0000000f, 3, tdat );
# Test with negative offset
TEST_LD_OP( 6, lbu, 0x000000ff, -3, tdat4 );
TEST_LD_OP( 7, lbu, 0x00000000, -2, tdat4 );
TEST_LD_OP( 8, lbu, 0x000000f0, -1, tdat4 );
TEST_LD_OP( 9, lbu, 0x0000000f, 0, tdat4 );
# Test with a negative base
TEST_CASE( 10, x3, 0x000000ff, \
la x1, tdat; \
addi x1, x1, -32; \
lbu x3, 32(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0x00000000, \
la x1, tdat; \
addi x1, x1, -6; \
lbu x3, 7(x1); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_LD_DEST_BYPASS( 12, 0, lbu, 0x000000f0, 1, tdat2 );
TEST_LD_DEST_BYPASS( 13, 1, lbu, 0x0000000f, 1, tdat3 );
TEST_LD_DEST_BYPASS( 14, 2, lbu, 0x00000000, 1, tdat1 );
TEST_LD_SRC1_BYPASS( 15, 0, lbu, 0x000000f0, 1, tdat2 );
TEST_LD_SRC1_BYPASS( 16, 1, lbu, 0x0000000f, 1, tdat3 );
TEST_LD_SRC1_BYPASS( 17, 2, lbu, 0x00000000, 1, tdat1 );
#-------------------------------------------------------------
# Test write-after-write hazard
#-------------------------------------------------------------
TEST_CASE( 18, x2, 2, \
la x3, tdat; \
lbu x2, 0(x3); \
li x2, 2; \
)
TEST_CASE( 19, x2, 2, \
la x3, tdat; \
lbu x2, 0(x3); \
nop; \
li x2, 2; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .byte 0xff
tdat2: .byte 0x00
tdat3: .byte 0xf0
tdat4: .byte 0x0f
RVTEST_DATA_END

92
tests/lh.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# lh.S
#-----------------------------------------------------------------------------
#
# Test lh instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_LD_OP( 2, lh, 0x000000ff, 0, tdat );
TEST_LD_OP( 3, lh, 0xffffff00, 2, tdat );
TEST_LD_OP( 4, lh, 0x00000ff0, 4, tdat );
TEST_LD_OP( 5, lh, 0xfffff00f, 6, tdat );
# Test with negative offset
TEST_LD_OP( 6, lh, 0x000000ff, -6, tdat4 );
TEST_LD_OP( 7, lh, 0xffffff00, -4, tdat4 );
TEST_LD_OP( 8, lh, 0x00000ff0, -2, tdat4 );
TEST_LD_OP( 9, lh, 0xfffff00f, 0, tdat4 );
# Test with a negative base
TEST_CASE( 10, x3, 0x000000ff, \
la x1, tdat; \
addi x1, x1, -32; \
lh x3, 32(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0xffffff00, \
la x1, tdat; \
addi x1, x1, -5; \
lh x3, 7(x1); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_LD_DEST_BYPASS( 12, 0, lh, 0x00000ff0, 2, tdat2 );
TEST_LD_DEST_BYPASS( 13, 1, lh, 0xfffff00f, 2, tdat3 );
TEST_LD_DEST_BYPASS( 14, 2, lh, 0xffffff00, 2, tdat1 );
TEST_LD_SRC1_BYPASS( 15, 0, lh, 0x00000ff0, 2, tdat2 );
TEST_LD_SRC1_BYPASS( 16, 1, lh, 0xfffff00f, 2, tdat3 );
TEST_LD_SRC1_BYPASS( 17, 2, lh, 0xffffff00, 2, tdat1 );
#-------------------------------------------------------------
# Test write-after-write hazard
#-------------------------------------------------------------
TEST_CASE( 18, x2, 2, \
la x3, tdat; \
lh x2, 0(x3); \
li x2, 2; \
)
TEST_CASE( 19, x2, 2, \
la x3, tdat; \
lh x2, 0(x3); \
nop; \
li x2, 2; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .half 0x00ff
tdat2: .half 0xff00
tdat3: .half 0x0ff0
tdat4: .half 0xf00f
RVTEST_DATA_END

92
tests/lhu.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# lhu.S
#-----------------------------------------------------------------------------
#
# Test lhu instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_LD_OP( 2, lhu, 0x000000ff, 0, tdat );
TEST_LD_OP( 3, lhu, 0x0000ff00, 2, tdat );
TEST_LD_OP( 4, lhu, 0x00000ff0, 4, tdat );
TEST_LD_OP( 5, lhu, 0x0000f00f, 6, tdat );
# Test with negative offset
TEST_LD_OP( 6, lhu, 0x000000ff, -6, tdat4 );
TEST_LD_OP( 7, lhu, 0x0000ff00, -4, tdat4 );
TEST_LD_OP( 8, lhu, 0x00000ff0, -2, tdat4 );
TEST_LD_OP( 9, lhu, 0x0000f00f, 0, tdat4 );
# Test with a negative base
TEST_CASE( 10, x3, 0x000000ff, \
la x1, tdat; \
addi x1, x1, -32; \
lhu x3, 32(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0x0000ff00, \
la x1, tdat; \
addi x1, x1, -5; \
lhu x3, 7(x1); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_LD_DEST_BYPASS( 12, 0, lhu, 0x00000ff0, 2, tdat2 );
TEST_LD_DEST_BYPASS( 13, 1, lhu, 0x0000f00f, 2, tdat3 );
TEST_LD_DEST_BYPASS( 14, 2, lhu, 0x0000ff00, 2, tdat1 );
TEST_LD_SRC1_BYPASS( 15, 0, lhu, 0x00000ff0, 2, tdat2 );
TEST_LD_SRC1_BYPASS( 16, 1, lhu, 0x0000f00f, 2, tdat3 );
TEST_LD_SRC1_BYPASS( 17, 2, lhu, 0x0000ff00, 2, tdat1 );
#-------------------------------------------------------------
# Test write-after-write hazard
#-------------------------------------------------------------
TEST_CASE( 18, x2, 2, \
la x3, tdat; \
lhu x2, 0(x3); \
li x2, 2; \
)
TEST_CASE( 19, x2, 2, \
la x3, tdat; \
lhu x2, 0(x3); \
nop; \
li x2, 2; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .half 0x00ff
tdat2: .half 0xff00
tdat3: .half 0x0ff0
tdat4: .half 0xf00f
RVTEST_DATA_END

36
tests/lui.S Normal file
View File

@ -0,0 +1,36 @@
# See LICENSE for license details.
#*****************************************************************************
# lui.S
#-----------------------------------------------------------------------------
#
# Test lui instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_CASE( 2, x1, 0x00000000, lui x1, 0x00000 );
TEST_CASE( 3, x1, 0xfffff800, lui x1, 0xfffff;sra x1,x1,1);
TEST_CASE( 4, x1, 0x000007ff, lui x1, 0x7ffff;sra x1,x1,20);
TEST_CASE( 5, x1, 0xfffff800, lui x1, 0x80000;sra x1,x1,20);
TEST_CASE( 6, x0, 0, lui x0, 0x80000 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

92
tests/lw.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# lw.S
#-----------------------------------------------------------------------------
#
# Test lw instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_LD_OP( 2, lw, 0x00ff00ff, 0, tdat );
TEST_LD_OP( 3, lw, 0xff00ff00, 4, tdat );
TEST_LD_OP( 4, lw, 0x0ff00ff0, 8, tdat );
TEST_LD_OP( 5, lw, 0xf00ff00f, 12, tdat );
# Test with negative offset
TEST_LD_OP( 6, lw, 0x00ff00ff, -12, tdat4 );
TEST_LD_OP( 7, lw, 0xff00ff00, -8, tdat4 );
TEST_LD_OP( 8, lw, 0x0ff00ff0, -4, tdat4 );
TEST_LD_OP( 9, lw, 0xf00ff00f, 0, tdat4 );
# Test with a negative base
TEST_CASE( 10, x3, 0x00ff00ff, \
la x1, tdat; \
addi x1, x1, -32; \
lw x3, 32(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0xff00ff00, \
la x1, tdat; \
addi x1, x1, -3; \
lw x3, 7(x1); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_LD_DEST_BYPASS( 12, 0, lw, 0x0ff00ff0, 4, tdat2 );
TEST_LD_DEST_BYPASS( 13, 1, lw, 0xf00ff00f, 4, tdat3 );
TEST_LD_DEST_BYPASS( 14, 2, lw, 0xff00ff00, 4, tdat1 );
TEST_LD_SRC1_BYPASS( 15, 0, lw, 0x0ff00ff0, 4, tdat2 );
TEST_LD_SRC1_BYPASS( 16, 1, lw, 0xf00ff00f, 4, tdat3 );
TEST_LD_SRC1_BYPASS( 17, 2, lw, 0xff00ff00, 4, tdat1 );
#-------------------------------------------------------------
# Test write-after-write hazard
#-------------------------------------------------------------
TEST_CASE( 18, x2, 2, \
la x3, tdat; \
lw x2, 0(x3); \
li x2, 2; \
)
TEST_CASE( 19, x2, 2, \
la x3, tdat; \
lw x2, 0(x3); \
nop; \
li x2, 2; \
)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .word 0x00ff00ff
tdat2: .word 0xff00ff00
tdat3: .word 0x0ff00ff0
tdat4: .word 0xf00ff00f
RVTEST_DATA_END

69
tests/or.S Normal file
View File

@ -0,0 +1,69 @@
# See LICENSE for license details.
#*****************************************************************************
# or.S
#-----------------------------------------------------------------------------
#
# Test or instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_RR_OP( 2, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_OP( 3, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_OP( 4, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_OP( 5, or, 0xf0fff0ff, 0xf00ff00f, 0xf0f0f0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 6, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC2_EQ_DEST( 7, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_EQ_DEST( 8, or, 0xff00ff00, 0xff00ff00 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 9, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_DEST_BYPASS( 10, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_DEST_BYPASS( 11, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 12, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 13, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 14, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 15, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 16, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 17, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 18, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 19, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 20, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 21, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 22, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 23, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_ZEROSRC1( 24, or, 0xff00ff00, 0xff00ff00 );
TEST_RR_ZEROSRC2( 25, or, 0x00ff00ff, 0x00ff00ff );
TEST_RR_ZEROSRC12( 26, or, 0 );
TEST_RR_ZERODEST( 27, or, 0x11111111, 0x22222222 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

55
tests/ori.S Normal file
View File

@ -0,0 +1,55 @@
# See LICENSE for license details.
#*****************************************************************************
# ori.S
#-----------------------------------------------------------------------------
#
# Test ori instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, ori, 0xffffff0f, 0xff00ff00, 0xf0f );
TEST_IMM_OP( 3, ori, 0x0ff00ff0, 0x0ff00ff0, 0x0f0 );
TEST_IMM_OP( 4, ori, 0x00ff07ff, 0x00ff00ff, 0x70f );
TEST_IMM_OP( 5, ori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 6, ori, 0xff00fff0, 0xff00ff00, 0x0f0 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 7, 0, ori, 0x0ff00ff0, 0x0ff00ff0, 0x0f0 );
TEST_IMM_DEST_BYPASS( 8, 1, ori, 0x00ff07ff, 0x00ff00ff, 0x70f );
TEST_IMM_DEST_BYPASS( 9, 2, ori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
TEST_IMM_SRC1_BYPASS( 10, 0, ori, 0x0ff00ff0, 0x0ff00ff0, 0x0f0 );
TEST_IMM_SRC1_BYPASS( 11, 1, ori, 0xffffffff, 0x00ff00ff, 0xf0f );
TEST_IMM_SRC1_BYPASS( 12, 2, ori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
TEST_IMM_ZEROSRC1( 13, ori, 0x0f0, 0x0f0 );
TEST_IMM_ZERODEST( 14, ori, 0x00ff00ff, 0x70f );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

64
tests/riscv_test.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef _ENV_PICORV32_TEST_H
#define _ENV_PICORV32_TEST_H
#ifndef TEST_FUNC_NAME
# define TEST_FUNC_NAME mytest
# define TEST_FUNC_TXT "mytest"
# define TEST_FUNC_RET mytest_ret
#endif
#define RVTEST_RV32U
#define TESTNUM x28
#define RVTEST_CODE_BEGIN \
.text; \
.global TEST_FUNC_NAME; \
.global TEST_FUNC_RET; \
TEST_FUNC_NAME: \
lui a0,%hi(.test_name); \
addi a0,a0,%lo(.test_name); \
lui a2,0x10000000>>12; \
.prname_next: \
lb a1,0(a0); \
beq a1,zero,.prname_done; \
sw a1,0(a2); \
addi a0,a0,1; \
jal zero,.prname_next; \
.test_name: \
.ascii TEST_FUNC_TXT; \
.byte 0x00; \
.balign 4; \
.prname_done: \
addi a1,zero,'.'; \
sw a1,0(a2); \
sw a1,0(a2);
#define RVTEST_PASS \
lui a0,0x10000000>>12; \
addi a1,zero,'O'; \
addi a2,zero,'K'; \
addi a3,zero,'\n'; \
sw a1,0(a0); \
sw a2,0(a0); \
sw a3,0(a0); \
jal zero,TEST_FUNC_RET;
#define RVTEST_FAIL \
lui a0,0x10000000>>12; \
addi a1,zero,'E'; \
addi a2,zero,'R'; \
addi a3,zero,'O'; \
addi a4,zero,'\n'; \
sw a1,0(a0); \
sw a2,0(a0); \
sw a2,0(a0); \
sw a3,0(a0); \
sw a2,0(a0); \
sw a4,0(a0); \
sbreak;
#define RVTEST_CODE_END
#define RVTEST_DATA_BEGIN .balign 4;
#define RVTEST_DATA_END
#endif

102
tests/sb.S Normal file
View File

@ -0,0 +1,102 @@
# See LICENSE for license details.
#*****************************************************************************
# sb.S
#-----------------------------------------------------------------------------
#
# Test sb instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_ST_OP( 2, lb, sb, 0xffffffaa, 0, tdat );
TEST_ST_OP( 3, lb, sb, 0x00000000, 1, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lh, sb, 0xffffefa0, 2, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lh, sb, 0xffffa0ef, 2, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lb, sb, 0x0000000a, 3, tdat );
# Test with negative offset
TEST_ST_OP( 6, lb, sb, 0xffffffaa, -3, tdat8 );
TEST_ST_OP( 7, lb, sb, 0x00000000, -2, tdat8 );
TEST_ST_OP( 8, lb, sb, 0xffffffa0, -1, tdat8 );
TEST_ST_OP( 9, lb, sb, 0x0000000a, 0, tdat8 );
# Test with a negative base
TEST_CASE( 10, x3, 0x78, \
la x1, tdat9; \
li x2, 0x12345678; \
addi x4, x1, -32; \
sb x2, 32(x4); \
lb x3, 0(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0xffffff98, \
la x1, tdat9; \
li x2, 0x00003098; \
addi x1, x1, -6; \
sb x2, 7(x1); \
la x4, tdat10; \
lb x3, 0(x4); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_ST_SRC12_BYPASS( 12, 0, 0, lb, sb, 0xffffffdd, 0, tdat );
TEST_ST_SRC12_BYPASS( 13, 0, 1, lb, sb, 0xffffffcd, 1, tdat );
TEST_ST_SRC12_BYPASS( 14, 0, 2, lb, sb, 0xffffffcc, 2, tdat );
TEST_ST_SRC12_BYPASS( 15, 1, 0, lb, sb, 0xffffffbc, 3, tdat );
TEST_ST_SRC12_BYPASS( 16, 1, 1, lb, sb, 0xffffffbb, 4, tdat );
TEST_ST_SRC12_BYPASS( 17, 2, 0, lb, sb, 0xffffffab, 5, tdat );
TEST_ST_SRC21_BYPASS( 18, 0, 0, lb, sb, 0x33, 0, tdat );
TEST_ST_SRC21_BYPASS( 19, 0, 1, lb, sb, 0x23, 1, tdat );
TEST_ST_SRC21_BYPASS( 20, 0, 2, lb, sb, 0x22, 2, tdat );
TEST_ST_SRC21_BYPASS( 21, 1, 0, lb, sb, 0x12, 3, tdat );
TEST_ST_SRC21_BYPASS( 22, 1, 1, lb, sb, 0x11, 4, tdat );
TEST_ST_SRC21_BYPASS( 23, 2, 0, lb, sb, 0x01, 5, tdat );
li a0, 0xef
la a1, tdat
sb a0, 3(a1)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .byte 0xef
tdat2: .byte 0xef
tdat3: .byte 0xef
tdat4: .byte 0xef
tdat5: .byte 0xef
tdat6: .byte 0xef
tdat7: .byte 0xef
tdat8: .byte 0xef
tdat9: .byte 0xef
tdat10: .byte 0xef
RVTEST_DATA_END

102
tests/sh.S Normal file
View File

@ -0,0 +1,102 @@
# See LICENSE for license details.
#*****************************************************************************
# sh.S
#-----------------------------------------------------------------------------
#
# Test sh instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_ST_OP( 2, lh, sh, 0x000000aa, 0, tdat );
TEST_ST_OP( 3, lh, sh, 0xffffaa00, 2, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lw, sh, 0xbeef0aa0, 4, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lw, sh, 0x0aa0beef, 4, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lh, sh, 0xffffa00a, 6, tdat );
# Test with negative offset
TEST_ST_OP( 6, lh, sh, 0x000000aa, -6, tdat8 );
TEST_ST_OP( 7, lh, sh, 0xffffaa00, -4, tdat8 );
TEST_ST_OP( 8, lh, sh, 0x00000aa0, -2, tdat8 );
TEST_ST_OP( 9, lh, sh, 0xffffa00a, 0, tdat8 );
# Test with a negative base
TEST_CASE( 10, x3, 0x5678, \
la x1, tdat9; \
li x2, 0x12345678; \
addi x4, x1, -32; \
sh x2, 32(x4); \
lh x3, 0(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0x3098, \
la x1, tdat9; \
li x2, 0x00003098; \
addi x1, x1, -5; \
sh x2, 7(x1); \
la x4, tdat10; \
lh x3, 0(x4); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_ST_SRC12_BYPASS( 12, 0, 0, lh, sh, 0xffffccdd, 0, tdat );
TEST_ST_SRC12_BYPASS( 13, 0, 1, lh, sh, 0xffffbccd, 2, tdat );
TEST_ST_SRC12_BYPASS( 14, 0, 2, lh, sh, 0xffffbbcc, 4, tdat );
TEST_ST_SRC12_BYPASS( 15, 1, 0, lh, sh, 0xffffabbc, 6, tdat );
TEST_ST_SRC12_BYPASS( 16, 1, 1, lh, sh, 0xffffaabb, 8, tdat );
TEST_ST_SRC12_BYPASS( 17, 2, 0, lh, sh, 0xffffdaab, 10, tdat );
TEST_ST_SRC21_BYPASS( 18, 0, 0, lh, sh, 0x2233, 0, tdat );
TEST_ST_SRC21_BYPASS( 19, 0, 1, lh, sh, 0x1223, 2, tdat );
TEST_ST_SRC21_BYPASS( 20, 0, 2, lh, sh, 0x1122, 4, tdat );
TEST_ST_SRC21_BYPASS( 21, 1, 0, lh, sh, 0x0112, 6, tdat );
TEST_ST_SRC21_BYPASS( 22, 1, 1, lh, sh, 0x0011, 8, tdat );
TEST_ST_SRC21_BYPASS( 23, 2, 0, lh, sh, 0x3001, 10, tdat );
li a0, 0xbeef
la a1, tdat
sh a0, 6(a1)
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .half 0xbeef
tdat2: .half 0xbeef
tdat3: .half 0xbeef
tdat4: .half 0xbeef
tdat5: .half 0xbeef
tdat6: .half 0xbeef
tdat7: .half 0xbeef
tdat8: .half 0xbeef
tdat9: .half 0xbeef
tdat10: .half 0xbeef
RVTEST_DATA_END

27
tests/simple.S Normal file
View File

@ -0,0 +1,27 @@
# See LICENSE for license details.
#*****************************************************************************
# simple.S
#-----------------------------------------------------------------------------
#
# This is the most basic self checking test. If your simulator does not
# pass thiss then there is little chance that it will pass any of the
# more complicated self checking tests.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
RVTEST_PASS
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

90
tests/sll.S Normal file
View File

@ -0,0 +1,90 @@
# See LICENSE for license details.
#*****************************************************************************
# sll.S
#-----------------------------------------------------------------------------
#
# Test sll instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, sll, 0x00000001, 0x00000001, 0 );
TEST_RR_OP( 3, sll, 0x00000002, 0x00000001, 1 );
TEST_RR_OP( 4, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_OP( 5, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_OP( 6, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_OP( 7, sll, 0xffffffff, 0xffffffff, 0 );
TEST_RR_OP( 8, sll, 0xfffffffe, 0xffffffff, 1 );
TEST_RR_OP( 9, sll, 0xffffff80, 0xffffffff, 7 );
TEST_RR_OP( 10, sll, 0xffffc000, 0xffffffff, 14 );
TEST_RR_OP( 11, sll, 0x80000000, 0xffffffff, 31 );
TEST_RR_OP( 12, sll, 0x21212121, 0x21212121, 0 );
TEST_RR_OP( 13, sll, 0x42424242, 0x21212121, 1 );
TEST_RR_OP( 14, sll, 0x90909080, 0x21212121, 7 );
TEST_RR_OP( 15, sll, 0x48484000, 0x21212121, 14 );
TEST_RR_OP( 16, sll, 0x80000000, 0x21212121, 31 );
# Verify that shifts only use bottom five bits
TEST_RR_OP( 17, sll, 0x21212121, 0x21212121, 0xffffffe0 );
TEST_RR_OP( 18, sll, 0x42424242, 0x21212121, 0xffffffe1 );
TEST_RR_OP( 19, sll, 0x90909080, 0x21212121, 0xffffffe7 );
TEST_RR_OP( 20, sll, 0x48484000, 0x21212121, 0xffffffee );
TEST_RR_OP( 21, sll, 0x00000000, 0x21212120, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 22, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_SRC2_EQ_DEST( 23, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_SRC12_EQ_DEST( 24, sll, 24, 3 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 25, 0, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_DEST_BYPASS( 26, 1, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_DEST_BYPASS( 27, 2, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_SRC12_BYPASS( 28, 0, 0, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_SRC12_BYPASS( 29, 0, 1, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_SRC12_BYPASS( 30, 0, 2, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_SRC12_BYPASS( 31, 1, 0, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_SRC12_BYPASS( 32, 1, 1, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_SRC12_BYPASS( 33, 2, 0, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_SRC21_BYPASS( 34, 0, 0, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_SRC21_BYPASS( 35, 0, 1, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_SRC21_BYPASS( 36, 0, 2, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_SRC21_BYPASS( 37, 1, 0, sll, 0x00000080, 0x00000001, 7 );
TEST_RR_SRC21_BYPASS( 38, 1, 1, sll, 0x00004000, 0x00000001, 14 );
TEST_RR_SRC21_BYPASS( 39, 2, 0, sll, 0x80000000, 0x00000001, 31 );
TEST_RR_ZEROSRC1( 40, sll, 0, 15 );
TEST_RR_ZEROSRC2( 41, sll, 32, 32 );
TEST_RR_ZEROSRC12( 42, sll, 0 );
TEST_RR_ZERODEST( 43, sll, 1024, 2048 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

68
tests/slli.S Normal file
View File

@ -0,0 +1,68 @@
# See LICENSE for license details.
#*****************************************************************************
# slli.S
#-----------------------------------------------------------------------------
#
# Test slli instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, slli, 0x00000001, 0x00000001, 0 );
TEST_IMM_OP( 3, slli, 0x00000002, 0x00000001, 1 );
TEST_IMM_OP( 4, slli, 0x00000080, 0x00000001, 7 );
TEST_IMM_OP( 5, slli, 0x00004000, 0x00000001, 14 );
TEST_IMM_OP( 6, slli, 0x80000000, 0x00000001, 31 );
TEST_IMM_OP( 7, slli, 0xffffffff, 0xffffffff, 0 );
TEST_IMM_OP( 8, slli, 0xfffffffe, 0xffffffff, 1 );
TEST_IMM_OP( 9, slli, 0xffffff80, 0xffffffff, 7 );
TEST_IMM_OP( 10, slli, 0xffffc000, 0xffffffff, 14 );
TEST_IMM_OP( 11, slli, 0x80000000, 0xffffffff, 31 );
TEST_IMM_OP( 12, slli, 0x21212121, 0x21212121, 0 );
TEST_IMM_OP( 13, slli, 0x42424242, 0x21212121, 1 );
TEST_IMM_OP( 14, slli, 0x90909080, 0x21212121, 7 );
TEST_IMM_OP( 15, slli, 0x48484000, 0x21212121, 14 );
TEST_IMM_OP( 16, slli, 0x80000000, 0x21212121, 31 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 17, slli, 0x00000080, 0x00000001, 7 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 18, 0, slli, 0x00000080, 0x00000001, 7 );
TEST_IMM_DEST_BYPASS( 19, 1, slli, 0x00004000, 0x00000001, 14 );
TEST_IMM_DEST_BYPASS( 20, 2, slli, 0x80000000, 0x00000001, 31 );
TEST_IMM_SRC1_BYPASS( 21, 0, slli, 0x00000080, 0x00000001, 7 );
TEST_IMM_SRC1_BYPASS( 22, 1, slli, 0x00004000, 0x00000001, 14 );
TEST_IMM_SRC1_BYPASS( 23, 2, slli, 0x80000000, 0x00000001, 31 );
TEST_IMM_ZEROSRC1( 24, slli, 0, 31 );
TEST_IMM_ZERODEST( 25, slli, 33, 20 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

84
tests/slt.S Normal file
View File

@ -0,0 +1,84 @@
# See LICENSE for license details.
#*****************************************************************************
# slt.S
#-----------------------------------------------------------------------------
#
# Test slt instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, slt, 0, 0x00000000, 0x00000000 );
TEST_RR_OP( 3, slt, 0, 0x00000001, 0x00000001 );
TEST_RR_OP( 4, slt, 1, 0x00000003, 0x00000007 );
TEST_RR_OP( 5, slt, 0, 0x00000007, 0x00000003 );
TEST_RR_OP( 6, slt, 0, 0x00000000, 0xffff8000 );
TEST_RR_OP( 7, slt, 1, 0x80000000, 0x00000000 );
TEST_RR_OP( 8, slt, 1, 0x80000000, 0xffff8000 );
TEST_RR_OP( 9, slt, 1, 0x00000000, 0x00007fff );
TEST_RR_OP( 10, slt, 0, 0x7fffffff, 0x00000000 );
TEST_RR_OP( 11, slt, 0, 0x7fffffff, 0x00007fff );
TEST_RR_OP( 12, slt, 1, 0x80000000, 0x00007fff );
TEST_RR_OP( 13, slt, 0, 0x7fffffff, 0xffff8000 );
TEST_RR_OP( 14, slt, 0, 0x00000000, 0xffffffff );
TEST_RR_OP( 15, slt, 1, 0xffffffff, 0x00000001 );
TEST_RR_OP( 16, slt, 0, 0xffffffff, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 17, slt, 0, 14, 13 );
TEST_RR_SRC2_EQ_DEST( 18, slt, 1, 11, 13 );
TEST_RR_SRC12_EQ_DEST( 19, slt, 0, 13 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 20, 0, slt, 1, 11, 13 );
TEST_RR_DEST_BYPASS( 21, 1, slt, 0, 14, 13 );
TEST_RR_DEST_BYPASS( 22, 2, slt, 1, 12, 13 );
TEST_RR_SRC12_BYPASS( 23, 0, 0, slt, 0, 14, 13 );
TEST_RR_SRC12_BYPASS( 24, 0, 1, slt, 1, 11, 13 );
TEST_RR_SRC12_BYPASS( 25, 0, 2, slt, 0, 15, 13 );
TEST_RR_SRC12_BYPASS( 26, 1, 0, slt, 1, 10, 13 );
TEST_RR_SRC12_BYPASS( 27, 1, 1, slt, 0, 16, 13 );
TEST_RR_SRC12_BYPASS( 28, 2, 0, slt, 1, 9, 13 );
TEST_RR_SRC21_BYPASS( 29, 0, 0, slt, 0, 17, 13 );
TEST_RR_SRC21_BYPASS( 30, 0, 1, slt, 1, 8, 13 );
TEST_RR_SRC21_BYPASS( 31, 0, 2, slt, 0, 18, 13 );
TEST_RR_SRC21_BYPASS( 32, 1, 0, slt, 1, 7, 13 );
TEST_RR_SRC21_BYPASS( 33, 1, 1, slt, 0, 19, 13 );
TEST_RR_SRC21_BYPASS( 34, 2, 0, slt, 1, 6, 13 );
TEST_RR_ZEROSRC1( 35, slt, 0, -1 );
TEST_RR_ZEROSRC2( 36, slt, 1, -1 );
TEST_RR_ZEROSRC12( 37, slt, 0 );
TEST_RR_ZERODEST( 38, slt, 16, 30 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

70
tests/slti.S Normal file
View File

@ -0,0 +1,70 @@
# See LICENSE for license details.
#*****************************************************************************
# slti.S
#-----------------------------------------------------------------------------
#
# Test slti instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, slti, 0, 0x00000000, 0x000 );
TEST_IMM_OP( 3, slti, 0, 0x00000001, 0x001 );
TEST_IMM_OP( 4, slti, 1, 0x00000003, 0x007 );
TEST_IMM_OP( 5, slti, 0, 0x00000007, 0x003 );
TEST_IMM_OP( 6, slti, 0, 0x00000000, 0x800 );
TEST_IMM_OP( 7, slti, 1, 0x80000000, 0x000 );
TEST_IMM_OP( 8, slti, 1, 0x80000000, 0x800 );
TEST_IMM_OP( 9, slti, 1, 0x00000000, 0x7ff );
TEST_IMM_OP( 10, slti, 0, 0x7fffffff, 0x000 );
TEST_IMM_OP( 11, slti, 0, 0x7fffffff, 0x7ff );
TEST_IMM_OP( 12, slti, 1, 0x80000000, 0x7ff );
TEST_IMM_OP( 13, slti, 0, 0x7fffffff, 0x800 );
TEST_IMM_OP( 14, slti, 0, 0x00000000, 0xfff );
TEST_IMM_OP( 15, slti, 1, 0xffffffff, 0x001 );
TEST_IMM_OP( 16, slti, 0, 0xffffffff, 0xfff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 17, sltiu, 1, 11, 13 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 18, 0, slti, 0, 15, 10 );
TEST_IMM_DEST_BYPASS( 19, 1, slti, 1, 10, 16 );
TEST_IMM_DEST_BYPASS( 20, 2, slti, 0, 16, 9 );
TEST_IMM_SRC1_BYPASS( 21, 0, slti, 1, 11, 15 );
TEST_IMM_SRC1_BYPASS( 22, 1, slti, 0, 17, 8 );
TEST_IMM_SRC1_BYPASS( 23, 2, slti, 1, 12, 14 );
TEST_IMM_ZEROSRC1( 24, slti, 0, 0xfff );
TEST_IMM_ZERODEST( 25, slti, 0x00ff00ff, 0xfff );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

90
tests/sra.S Normal file
View File

@ -0,0 +1,90 @@
# See LICENSE for license details.
#*****************************************************************************
# sra.S
#-----------------------------------------------------------------------------
#
# Test sra instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, sra, 0x80000000, 0x80000000, 0 );
TEST_RR_OP( 3, sra, 0xc0000000, 0x80000000, 1 );
TEST_RR_OP( 4, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_OP( 5, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_OP( 6, sra, 0xffffffff, 0x80000001, 31 );
TEST_RR_OP( 7, sra, 0x7fffffff, 0x7fffffff, 0 );
TEST_RR_OP( 8, sra, 0x3fffffff, 0x7fffffff, 1 );
TEST_RR_OP( 9, sra, 0x00ffffff, 0x7fffffff, 7 );
TEST_RR_OP( 10, sra, 0x0001ffff, 0x7fffffff, 14 );
TEST_RR_OP( 11, sra, 0x00000000, 0x7fffffff, 31 );
TEST_RR_OP( 12, sra, 0x81818181, 0x81818181, 0 );
TEST_RR_OP( 13, sra, 0xc0c0c0c0, 0x81818181, 1 );
TEST_RR_OP( 14, sra, 0xff030303, 0x81818181, 7 );
TEST_RR_OP( 15, sra, 0xfffe0606, 0x81818181, 14 );
TEST_RR_OP( 16, sra, 0xffffffff, 0x81818181, 31 );
# Verify that shifts only use bottom five bits
TEST_RR_OP( 17, sra, 0x81818181, 0x81818181, 0xffffffc0 );
TEST_RR_OP( 18, sra, 0xc0c0c0c0, 0x81818181, 0xffffffc1 );
TEST_RR_OP( 19, sra, 0xff030303, 0x81818181, 0xffffffc7 );
TEST_RR_OP( 20, sra, 0xfffe0606, 0x81818181, 0xffffffce );
TEST_RR_OP( 21, sra, 0xffffffff, 0x81818181, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 22, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_SRC2_EQ_DEST( 23, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_SRC12_EQ_DEST( 24, sra, 0, 7 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 25, 0, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_DEST_BYPASS( 26, 1, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_DEST_BYPASS( 27, 2, sra, 0xffffffff, 0x80000000, 31 );
TEST_RR_SRC12_BYPASS( 28, 0, 0, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_SRC12_BYPASS( 29, 0, 1, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_SRC12_BYPASS( 30, 0, 2, sra, 0xffffffff, 0x80000000, 31 );
TEST_RR_SRC12_BYPASS( 31, 1, 0, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_SRC12_BYPASS( 32, 1, 1, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_SRC12_BYPASS( 33, 2, 0, sra, 0xffffffff, 0x80000000, 31 );
TEST_RR_SRC21_BYPASS( 34, 0, 0, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_SRC21_BYPASS( 35, 0, 1, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_SRC21_BYPASS( 36, 0, 2, sra, 0xffffffff, 0x80000000, 31 );
TEST_RR_SRC21_BYPASS( 37, 1, 0, sra, 0xff000000, 0x80000000, 7 );
TEST_RR_SRC21_BYPASS( 38, 1, 1, sra, 0xfffe0000, 0x80000000, 14 );
TEST_RR_SRC21_BYPASS( 39, 2, 0, sra, 0xffffffff, 0x80000000, 31 );
TEST_RR_ZEROSRC1( 40, sra, 0, 15 );
TEST_RR_ZEROSRC2( 41, sra, 32, 32 );
TEST_RR_ZEROSRC12( 42, sra, 0 );
TEST_RR_ZERODEST( 43, sra, 1024, 2048 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

68
tests/srai.S Normal file
View File

@ -0,0 +1,68 @@
# See LICENSE for license details.
#*****************************************************************************
# srai.S
#-----------------------------------------------------------------------------
#
# Test srai instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, srai, 0x00000000, 0x00000000, 0 );
TEST_IMM_OP( 3, srai, 0xc0000000, 0x80000000, 1 );
TEST_IMM_OP( 4, srai, 0xff000000, 0x80000000, 7 );
TEST_IMM_OP( 5, srai, 0xfffe0000, 0x80000000, 14 );
TEST_IMM_OP( 6, srai, 0xffffffff, 0x80000001, 31 );
TEST_IMM_OP( 7, srai, 0x7fffffff, 0x7fffffff, 0 );
TEST_IMM_OP( 8, srai, 0x3fffffff, 0x7fffffff, 1 );
TEST_IMM_OP( 9, srai, 0x00ffffff, 0x7fffffff, 7 );
TEST_IMM_OP( 10, srai, 0x0001ffff, 0x7fffffff, 14 );
TEST_IMM_OP( 11, srai, 0x00000000, 0x7fffffff, 31 );
TEST_IMM_OP( 12, srai, 0x81818181, 0x81818181, 0 );
TEST_IMM_OP( 13, srai, 0xc0c0c0c0, 0x81818181, 1 );
TEST_IMM_OP( 14, srai, 0xff030303, 0x81818181, 7 );
TEST_IMM_OP( 15, srai, 0xfffe0606, 0x81818181, 14 );
TEST_IMM_OP( 16, srai, 0xffffffff, 0x81818181, 31 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 17, srai, 0xff000000, 0x80000000, 7 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 18, 0, srai, 0xff000000, 0x80000000, 7 );
TEST_IMM_DEST_BYPASS( 19, 1, srai, 0xfffe0000, 0x80000000, 14 );
TEST_IMM_DEST_BYPASS( 20, 2, srai, 0xffffffff, 0x80000001, 31 );
TEST_IMM_SRC1_BYPASS( 21, 0, srai, 0xff000000, 0x80000000, 7 );
TEST_IMM_SRC1_BYPASS( 22, 1, srai, 0xfffe0000, 0x80000000, 14 );
TEST_IMM_SRC1_BYPASS( 23, 2, srai, 0xffffffff, 0x80000001, 31 );
TEST_IMM_ZEROSRC1( 24, srai, 0, 31 );
TEST_IMM_ZERODEST( 25, srai, 33, 20 );
#
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

90
tests/srl.S Normal file
View File

@ -0,0 +1,90 @@
# See LICENSE for license details.
#*****************************************************************************
# srl.S
#-----------------------------------------------------------------------------
#
# Test srl instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, srl, 0xffff8000, 0xffff8000, 0 );
TEST_RR_OP( 3, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_OP( 4, srl, 0x01ffff00, 0xffff8000, 7 );
TEST_RR_OP( 5, srl, 0x0003fffe, 0xffff8000, 14 );
TEST_RR_OP( 6, srl, 0x0001ffff, 0xffff8001, 15 );
TEST_RR_OP( 7, srl, 0xffffffff, 0xffffffff, 0 );
TEST_RR_OP( 8, srl, 0x7fffffff, 0xffffffff, 1 );
TEST_RR_OP( 9, srl, 0x01ffffff, 0xffffffff, 7 );
TEST_RR_OP( 10, srl, 0x0003ffff, 0xffffffff, 14 );
TEST_RR_OP( 11, srl, 0x00000001, 0xffffffff, 31 );
TEST_RR_OP( 12, srl, 0x21212121, 0x21212121, 0 );
TEST_RR_OP( 13, srl, 0x10909090, 0x21212121, 1 );
TEST_RR_OP( 14, srl, 0x00424242, 0x21212121, 7 );
TEST_RR_OP( 15, srl, 0x00008484, 0x21212121, 14 );
TEST_RR_OP( 16, srl, 0x00000000, 0x21212121, 31 );
# Verify that shifts only use bottom five bits
TEST_RR_OP( 17, srl, 0x21212121, 0x21212121, 0xffffffe0 );
TEST_RR_OP( 18, srl, 0x10909090, 0x21212121, 0xffffffe1 );
TEST_RR_OP( 19, srl, 0x00424242, 0x21212121, 0xffffffe7 );
TEST_RR_OP( 20, srl, 0x00008484, 0x21212121, 0xffffffee );
TEST_RR_OP( 21, srl, 0x00000000, 0x21212121, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 22, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_SRC2_EQ_DEST( 23, srl, 0x0003fffe, 0xffff8000, 14 );
TEST_RR_SRC12_EQ_DEST( 24, srl, 0, 7 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 25, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_DEST_BYPASS( 26, 1, srl, 0x0003fffe, 0xffff8000, 14 );
TEST_RR_DEST_BYPASS( 27, 2, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_RR_SRC12_BYPASS( 28, 0, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_SRC12_BYPASS( 29, 0, 1, srl, 0x01ffff00, 0xffff8000, 7 );
TEST_RR_SRC12_BYPASS( 30, 0, 2, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_RR_SRC12_BYPASS( 31, 1, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_SRC12_BYPASS( 32, 1, 1, srl, 0x01ffff00, 0xffff8000, 7 );
TEST_RR_SRC12_BYPASS( 33, 2, 0, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_RR_SRC21_BYPASS( 34, 0, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_SRC21_BYPASS( 35, 0, 1, srl, 0x01ffff00, 0xffff8000, 7 );
TEST_RR_SRC21_BYPASS( 36, 0, 2, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_RR_SRC21_BYPASS( 37, 1, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_RR_SRC21_BYPASS( 38, 1, 1, srl, 0x01ffff00, 0xffff8000, 7 );
TEST_RR_SRC21_BYPASS( 39, 2, 0, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_RR_ZEROSRC1( 40, srl, 0, 15 );
TEST_RR_ZEROSRC2( 41, srl, 32, 32 );
TEST_RR_ZEROSRC12( 42, srl, 0 );
TEST_RR_ZERODEST( 43, srl, 1024, 2048 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

69
tests/srli.S Normal file
View File

@ -0,0 +1,69 @@
# See LICENSE for license details.
#*****************************************************************************
# srli.S
#-----------------------------------------------------------------------------
#
# Test srli instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, srli, 0xffff8000, 0xffff8000, 0 );
TEST_IMM_OP( 3, srli, 0x7fffc000, 0xffff8000, 1 );
TEST_IMM_OP( 4, srli, 0x01ffff00, 0xffff8000, 7 );
TEST_IMM_OP( 5, srli, 0x0003fffe, 0xffff8000, 14 );
TEST_IMM_OP( 6, srli, 0x0001ffff, 0xffff8001, 15 );
TEST_IMM_OP( 7, srli, 0xffffffff, 0xffffffff, 0 );
TEST_IMM_OP( 8, srli, 0x7fffffff, 0xffffffff, 1 );
TEST_IMM_OP( 9, srli, 0x01ffffff, 0xffffffff, 7 );
TEST_IMM_OP( 10, srli, 0x0003ffff, 0xffffffff, 14 );
TEST_IMM_OP( 11, srli, 0x00000001, 0xffffffff, 31 );
TEST_IMM_OP( 12, srli, 0x21212121, 0x21212121, 0 );
TEST_IMM_OP( 13, srli, 0x10909090, 0x21212121, 1 );
TEST_IMM_OP( 14, srli, 0x00424242, 0x21212121, 7 );
TEST_IMM_OP( 15, srli, 0x00008484, 0x21212121, 14 );
TEST_IMM_OP( 16, srli, 0x00000000, 0x21212121, 31 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 21, srli, 0x7fffc000, 0xffff8000, 1 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 22, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_IMM_DEST_BYPASS( 23, 1, srl, 0x0003fffe, 0xffff8000, 14 );
TEST_IMM_DEST_BYPASS( 24, 2, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_IMM_SRC1_BYPASS( 25, 0, srl, 0x7fffc000, 0xffff8000, 1 );
TEST_IMM_SRC1_BYPASS( 26, 1, srl, 0x0003fffe, 0xffff8000, 14 );
TEST_IMM_SRC1_BYPASS( 27, 2, srl, 0x0001ffff, 0xffff8000, 15 );
TEST_IMM_ZEROSRC1( 28, srli, 0, 31 );
TEST_IMM_ZERODEST( 29, srli, 33, 20 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

83
tests/sub.S Normal file
View File

@ -0,0 +1,83 @@
# See LICENSE for license details.
#*****************************************************************************
# sub.S
#-----------------------------------------------------------------------------
#
# Test sub instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Arithmetic tests
#-------------------------------------------------------------
TEST_RR_OP( 2, sub, 0x00000000, 0x00000000, 0x00000000 );
TEST_RR_OP( 3, sub, 0x00000000, 0x00000001, 0x00000001 );
TEST_RR_OP( 4, sub, 0xfffffffc, 0x00000003, 0x00000007 );
TEST_RR_OP( 5, sub, 0x00008000, 0x00000000, 0xffff8000 );
TEST_RR_OP( 6, sub, 0x80000000, 0x80000000, 0x00000000 );
TEST_RR_OP( 7, sub, 0x80008000, 0x80000000, 0xffff8000 );
TEST_RR_OP( 8, sub, 0xffff8001, 0x00000000, 0x00007fff );
TEST_RR_OP( 9, sub, 0x7fffffff, 0x7fffffff, 0x00000000 );
TEST_RR_OP( 10, sub, 0x7fff8000, 0x7fffffff, 0x00007fff );
TEST_RR_OP( 11, sub, 0x7fff8001, 0x80000000, 0x00007fff );
TEST_RR_OP( 12, sub, 0x80007fff, 0x7fffffff, 0xffff8000 );
TEST_RR_OP( 13, sub, 0x00000001, 0x00000000, 0xffffffff );
TEST_RR_OP( 14, sub, 0xfffffffe, 0xffffffff, 0x00000001 );
TEST_RR_OP( 15, sub, 0x00000000, 0xffffffff, 0xffffffff );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 16, sub, 2, 13, 11 );
TEST_RR_SRC2_EQ_DEST( 17, sub, 3, 14, 11 );
TEST_RR_SRC12_EQ_DEST( 18, sub, 0, 13 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 19, 0, sub, 2, 13, 11 );
TEST_RR_DEST_BYPASS( 20, 1, sub, 3, 14, 11 );
TEST_RR_DEST_BYPASS( 21, 2, sub, 4, 15, 11 );
TEST_RR_SRC12_BYPASS( 22, 0, 0, sub, 2, 13, 11 );
TEST_RR_SRC12_BYPASS( 23, 0, 1, sub, 3, 14, 11 );
TEST_RR_SRC12_BYPASS( 24, 0, 2, sub, 4, 15, 11 );
TEST_RR_SRC12_BYPASS( 25, 1, 0, sub, 2, 13, 11 );
TEST_RR_SRC12_BYPASS( 26, 1, 1, sub, 3, 14, 11 );
TEST_RR_SRC12_BYPASS( 27, 2, 0, sub, 4, 15, 11 );
TEST_RR_SRC21_BYPASS( 28, 0, 0, sub, 2, 13, 11 );
TEST_RR_SRC21_BYPASS( 29, 0, 1, sub, 3, 14, 11 );
TEST_RR_SRC21_BYPASS( 30, 0, 2, sub, 4, 15, 11 );
TEST_RR_SRC21_BYPASS( 31, 1, 0, sub, 2, 13, 11 );
TEST_RR_SRC21_BYPASS( 32, 1, 1, sub, 3, 14, 11 );
TEST_RR_SRC21_BYPASS( 33, 2, 0, sub, 4, 15, 11 );
TEST_RR_ZEROSRC1( 34, sub, 15, -15 );
TEST_RR_ZEROSRC2( 35, sub, 32, 32 );
TEST_RR_ZEROSRC12( 36, sub, 0 );
TEST_RR_ZERODEST( 37, sub, 16, 30 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

92
tests/sw.S Normal file
View File

@ -0,0 +1,92 @@
# See LICENSE for license details.
#*****************************************************************************
# sw.S
#-----------------------------------------------------------------------------
#
# Test sw instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Basic tests
#-------------------------------------------------------------
TEST_ST_OP( 2, lw, sw, 0x00aa00aa, 0, tdat );
TEST_ST_OP( 3, lw, sw, 0xaa00aa00, 4, tdat );
TEST_ST_OP( 4, lw, sw, 0x0aa00aa0, 8, tdat );
TEST_ST_OP( 5, lw, sw, 0xa00aa00a, 12, tdat );
# Test with negative offset
TEST_ST_OP( 6, lw, sw, 0x00aa00aa, -12, tdat8 );
TEST_ST_OP( 7, lw, sw, 0xaa00aa00, -8, tdat8 );
TEST_ST_OP( 8, lw, sw, 0x0aa00aa0, -4, tdat8 );
TEST_ST_OP( 9, lw, sw, 0xa00aa00a, 0, tdat8 );
# Test with a negative base
TEST_CASE( 10, x3, 0x12345678, \
la x1, tdat9; \
li x2, 0x12345678; \
addi x4, x1, -32; \
sw x2, 32(x4); \
lw x3, 0(x1); \
)
# Test with unaligned base
TEST_CASE( 11, x3, 0x58213098, \
la x1, tdat9; \
li x2, 0x58213098; \
addi x1, x1, -3; \
sw x2, 7(x1); \
la x4, tdat10; \
lw x3, 0(x4); \
)
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_ST_SRC12_BYPASS( 12, 0, 0, lw, sw, 0xaabbccdd, 0, tdat );
TEST_ST_SRC12_BYPASS( 13, 0, 1, lw, sw, 0xdaabbccd, 4, tdat );
TEST_ST_SRC12_BYPASS( 14, 0, 2, lw, sw, 0xddaabbcc, 8, tdat );
TEST_ST_SRC12_BYPASS( 15, 1, 0, lw, sw, 0xcddaabbc, 12, tdat );
TEST_ST_SRC12_BYPASS( 16, 1, 1, lw, sw, 0xccddaabb, 16, tdat );
TEST_ST_SRC12_BYPASS( 17, 2, 0, lw, sw, 0xbccddaab, 20, tdat );
TEST_ST_SRC21_BYPASS( 18, 0, 0, lw, sw, 0x00112233, 0, tdat );
TEST_ST_SRC21_BYPASS( 19, 0, 1, lw, sw, 0x30011223, 4, tdat );
TEST_ST_SRC21_BYPASS( 20, 0, 2, lw, sw, 0x33001122, 8, tdat );
TEST_ST_SRC21_BYPASS( 21, 1, 0, lw, sw, 0x23300112, 12, tdat );
TEST_ST_SRC21_BYPASS( 22, 1, 1, lw, sw, 0x22330011, 16, tdat );
TEST_ST_SRC21_BYPASS( 23, 2, 0, lw, sw, 0x12233001, 20, tdat );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
tdat:
tdat1: .word 0xdeadbeef
tdat2: .word 0xdeadbeef
tdat3: .word 0xdeadbeef
tdat4: .word 0xdeadbeef
tdat5: .word 0xdeadbeef
tdat6: .word 0xdeadbeef
tdat7: .word 0xdeadbeef
tdat8: .word 0xdeadbeef
tdat9: .word 0xdeadbeef
tdat10: .word 0xdeadbeef
RVTEST_DATA_END

708
tests/test_macros.h Normal file
View File

@ -0,0 +1,708 @@
// See LICENSE for license details.
#ifndef __TEST_MACROS_SCALAR_H
#define __TEST_MACROS_SCALAR_H
#-----------------------------------------------------------------------
# Helper macros
#-----------------------------------------------------------------------
#define TEST_CASE( testnum, testreg, correctval, code... ) \
test_ ## testnum: \
code; \
li x29, 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, val1; \
inst x3, x1, SEXT_IMM(imm); \
)
#define TEST_IMM_SRC1_EQ_DEST( testnum, inst, result, val1, imm ) \
TEST_CASE( testnum, x1, result, \
li x1, 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, 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, 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, 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, val1; \
li x2, val2; \
inst x3, x1, x2; \
)
#define TEST_RR_SRC1_EQ_DEST( testnum, inst, result, val1, val2 ) \
TEST_CASE( testnum, x1, result, \
li x1, val1; \
li x2, val2; \
inst x1, x1, x2; \
)
#define TEST_RR_SRC2_EQ_DEST( testnum, inst, result, val1, val2 ) \
TEST_CASE( testnum, x2, result, \
li x1, val1; \
li x2, val2; \
inst x2, x1, x2; \
)
#define TEST_RR_SRC12_EQ_DEST( testnum, inst, result, val1 ) \
TEST_CASE( testnum, x1, result, \
li x1, 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, val1; \
li x2, 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, val1; \
TEST_INSERT_NOPS_ ## src1_nops \
li x2, 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, val2; \
TEST_INSERT_NOPS_ ## src1_nops \
li x1, 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, val; \
inst x2, x0, x1; \
)
#define TEST_RR_ZEROSRC2( testnum, inst, result, val ) \
TEST_CASE( testnum, x2, result, \
li x1, 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, val1; \
li x2, 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: la 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 \
la 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 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; \
.align 2; \
.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; \
.align 3; \
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_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, result, val1, val2 ) \
TEST_FP_OP_S_INTERNAL( testnum, 0, word result, val1, val2, 0.0, \
inst a0, f0, f1)
#define TEST_FP_CMP_OP_D( testnum, inst, result, val1, val2 ) \
TEST_FP_OP_D_INTERNAL( testnum, 0, dword result, val1, val2, 0.0, \
inst a0, f0, f1)
#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; \
.align 2; \
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; \
.align 3; \
test_ ## testnum ## _data: \
.double result; \
1:
#-----------------------------------------------------------------------
# RV64SV MACROS
#-----------------------------------------------------------------------
#define TEST_ILLEGAL_TVEC_REGID( testnum, nxreg, nfreg, inst, reg1, reg2) \
la a0, handler ## testnum; \
csrw stvec, a0; \
vsetcfg nxreg, nfreg; \
li a0, 4; \
vsetvl a0, a0; \
la a0, src1; \
la a1, src2; \
vld vx2, a0; \
vld vx3, a1; \
lui a0,%hi(vtcode1 ## testnum); \
vf %lo(vtcode1 ## testnum)(a0); \
la reg2, dest; \
illegal ## testnum: \
inst reg1, reg2; \
la a3, dest; \
vsd vx2, a3; \
fence; \
vtcode1 ## testnum: \
add x2, x2, x3; \
stop; \
vtcode2 ## testnum: \
add x2, x2, x3; \
stop; \
handler ## testnum: \
vxcptkill; \
li TESTNUM,2; \
csrr a0, scause; \
li a1,HWACHA_CAUSE_TVEC_ILLEGAL_REGID; \
bne a0,a1,fail; \
csrr a0, sbadaddr; \
la a1, illegal ## testnum; \
lw a2, 0(a1); \
bne a0, a2, fail; \
vsetcfg 32,0; \
li a0,4; \
vsetvl a0,a0; \
la a0,src1; \
la a1,src2; \
vld vx2,a0; \
vld vx3,a1; \
lui a0,%hi(vtcode2 ## testnum); \
vf %lo(vtcode2 ## testnum)(a0); \
la a3,dest; \
vsd vx2,a3; \
fence; \
ld a1,0(a3); \
li a2,5; \
li TESTNUM,2; \
bne a1,a2,fail; \
ld a1,8(a3); \
li TESTNUM,3; \
bne a1,a2,fail; \
ld a1,16(a3); \
li TESTNUM,4; \
bne a1,a2,fail; \
ld a1,24(a3); \
li TESTNUM,5; \
bne a1,a2,fail; \
#define TEST_ILLEGAL_VT_REGID( testnum, nxreg, nfreg, inst, reg1, reg2, reg3) \
la a0, handler ## testnum; \
csrw stvec, a0; \
vsetcfg nxreg, nfreg; \
li a0, 4; \
vsetvl a0, a0; \
la a0, src1; \
la a1, src2; \
vld vx2, a0; \
vld vx3, a1; \
lui a0,%hi(vtcode1 ## testnum); \
vf %lo(vtcode1 ## testnum)(a0); \
la a3, dest; \
vsd vx2, a3; \
fence; \
vtcode1 ## testnum: \
add x2, x2, x3; \
illegal ## testnum: \
inst reg1, reg2, reg3; \
stop; \
vtcode2 ## testnum: \
add x2, x2, x3; \
stop; \
handler ## testnum: \
vxcptkill; \
li TESTNUM,2; \
csrr a0, scause; \
li a1,HWACHA_CAUSE_VF_ILLEGAL_REGID; \
bne a0,a1,fail; \
csrr a0, sbadaddr; \
la a1,illegal ## testnum; \
bne a0,a1,fail; \
vsetcfg 32,0; \
li a0,4; \
vsetvl a0,a0; \
la a0,src1; \
la a1,src2; \
vld vx2,a0; \
vld vx3,a1; \
lui a0,%hi(vtcode2 ## testnum); \
vf %lo(vtcode2 ## testnum)(a0); \
la a3,dest; \
vsd vx2,a3; \
fence; \
ld a1,0(a3); \
li a2,5; \
li TESTNUM,2; \
bne a1,a2,fail; \
ld a1,8(a3); \
li TESTNUM,3; \
bne a1,a2,fail; \
ld a1,16(a3); \
li TESTNUM,4; \
bne a1,a2,fail; \
ld a1,24(a3); \
li TESTNUM,5; \
bne a1,a2,fail; \
#-----------------------------------------------------------------------
# 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

69
tests/xor.S Normal file
View File

@ -0,0 +1,69 @@
# See LICENSE for license details.
#*****************************************************************************
# xor.S
#-----------------------------------------------------------------------------
#
# Test xor instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_RR_OP( 2, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_OP( 3, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_OP( 4, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_OP( 5, xor, 0x00ff00ff, 0xf00ff00f, 0xf0f0f0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_RR_SRC1_EQ_DEST( 6, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC2_EQ_DEST( 7, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_EQ_DEST( 8, xor, 0x00000000, 0xff00ff00 );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_RR_DEST_BYPASS( 9, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_DEST_BYPASS( 10, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_DEST_BYPASS( 11, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 12, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 13, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 14, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 15, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC12_BYPASS( 16, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC12_BYPASS( 17, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 18, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 19, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 20, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 21, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f );
TEST_RR_SRC21_BYPASS( 22, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 );
TEST_RR_SRC21_BYPASS( 23, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f );
TEST_RR_ZEROSRC1( 24, xor, 0xff00ff00, 0xff00ff00 );
TEST_RR_ZEROSRC2( 25, xor, 0x00ff00ff, 0x00ff00ff );
TEST_RR_ZEROSRC12( 26, xor, 0 );
TEST_RR_ZERODEST( 27, xor, 0x11111111, 0x22222222 );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END

55
tests/xori.S Normal file
View File

@ -0,0 +1,55 @@
# See LICENSE for license details.
#*****************************************************************************
# xori.S
#-----------------------------------------------------------------------------
#
# Test xori instruction.
#
#include "riscv_test.h"
#include "test_macros.h"
RVTEST_RV32U
RVTEST_CODE_BEGIN
#-------------------------------------------------------------
# Logical tests
#-------------------------------------------------------------
TEST_IMM_OP( 2, xori, 0xff00f00f, 0x00ff0f00, 0xf0f );
TEST_IMM_OP( 3, xori, 0x0ff00f00, 0x0ff00ff0, 0x0f0 );
TEST_IMM_OP( 4, xori, 0x00ff0ff0, 0x00ff08ff, 0x70f );
TEST_IMM_OP( 5, xori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
#-------------------------------------------------------------
# Source/Destination tests
#-------------------------------------------------------------
TEST_IMM_SRC1_EQ_DEST( 6, xori, 0xff00f00f, 0xff00f700, 0x70f );
#-------------------------------------------------------------
# Bypassing tests
#-------------------------------------------------------------
TEST_IMM_DEST_BYPASS( 7, 0, xori, 0x0ff00f00, 0x0ff00ff0, 0x0f0 );
TEST_IMM_DEST_BYPASS( 8, 1, xori, 0x00ff0ff0, 0x00ff08ff, 0x70f );
TEST_IMM_DEST_BYPASS( 9, 2, xori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
TEST_IMM_SRC1_BYPASS( 10, 0, xori, 0x0ff00f00, 0x0ff00ff0, 0x0f0 );
TEST_IMM_SRC1_BYPASS( 11, 1, xori, 0x00ff0ff0, 0x00ff0fff, 0x00f );
TEST_IMM_SRC1_BYPASS( 12, 2, xori, 0xf00ff0ff, 0xf00ff00f, 0x0f0 );
TEST_IMM_ZEROSRC1( 13, xori, 0x0f0, 0x0f0 );
TEST_IMM_ZERODEST( 14, xori, 0x00ff00ff, 0x70f );
TEST_PASSFAIL
RVTEST_CODE_END
.data
RVTEST_DATA_BEGIN
TEST_DATA
RVTEST_DATA_END