rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

rtests.c (4978B)


      1 #include <stdint.h>
      2 #include <inttypes.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <stdint.h>
      7 
      8 #include "exec.h"
      9 #include "mem.h"
     10 #include "disasm.h"
     11 #include "test.h"
     12 
     13 /**** TESTS ****/
     14 
     15 test_t tests[] = {
     16 	{
     17 		.name = "upper immediate instructions",
     18 		.program = {
     19 			0xaaaaa3b7,	// lui x7, 0xaaaaa	-> rd:aaaaa000
     20 			0x00001397,	// auipc x7 0x1 	-> rd 1004
     21 			0x00000013,	// nop
     22 			0x0ff0000f,	// fence
     23 			0x00100073,	// ebreak
     24 		},
     25 		.program_len = 5,
     26 		.exp = {
     27 			.x[7] = 0x1004,
     28 			.x_check_mask = (UINT32_C(1) << 7),
     29 			.pc = 16,
     30 
     31 		},
     32 	},
     33 	{
     34 		.name = "negative I-type immediates",
     35 		.program = {
     36 			0xfff00093,  // addi  x1, x0, -1
     37 			0xfff04113,  // xori  x2, x0, -1
     38 			0xfff06193,  // ori   x3, x0, -1
     39 			0xfff17213,  // andi  x4, x2, -1
     40 			0xfff02293,  // slti  x5, x0, -1
     41 			0xfff03313,  // sltiu x6, x0, -1
     42 			0x00100073,  // ebreak
     43 		},
     44 		.program_len = 7,
     45 		.exp = {
     46 			.x = {
     47 				[1] = 0xffffffff,
     48 				[2] = 0xffffffff,
     49 				[3] = 0xffffffff,
     50 				[4] = 0xffffffff,
     51 				[5] = 0x0,
     52 				[6] = 0x1,
     53 			},
     54 			.x_check_mask = (UINT32_C(1) << 6) |
     55 					(UINT32_C(1) << 5) |
     56 					(UINT32_C(1) << 4) |
     57 					(UINT32_C(1) << 3) |
     58 					(UINT32_C(1) << 2) |
     59 					(UINT32_C(1) << 1),
     60 			.pc = 0x18
     61 		}
     62 	},
     63 	{
     64 		.name = "I-type immediates",
     65 		.program = {
     66       			0x00700513,  // addi x10, x0, 7
     67       			0x00451513,  // slli x10, x10, 4
     68       			0x00d50513,  // addi x10, x10, 13
     69       			0x05554513,  // xori x10, x10, 0x55
     70       			0xff750513,  // addi x10, x10, -9
     71       			0x00100073   // ebreak
     72 		},
     73 		.program_len = 6,
     74 		.exp = {
     75 			.x[10] = 0x0000001f,
     76 			.x_check_mask = (UINT32_C(1) << 10),
     77 			.pc = 0x14,
     78 		}
     79 	},
     80 	{
     81 		.name = "basic loads and stores",
     82 		.program = {
     83 			0x00a00093,	//li      ra,10
     84 			0x00000113,	//li      sp,0
     85 			0x00100193,	//li      gp,1
     86 			0x00310133,	//add     sp,sp,gp
     87 			0x00118193,	//addi    gp,gp,1
     88 			0xfff08093,	//addi    ra,ra,-1
     89 			0xfe009ae3,	//bnez    ra,c <loop>
     90 			0x10000513,	//li      a0,256
     91 			0x00252023,	//sw      sp,0(a0)
     92 			0x00350223,	//sb      gp,4(a0)
     93 			0x00052203,	//lw      tp,0(a0)
     94 			0x00450283,	//lb      t0,4(a0)
     95 			0x00121313,	//slli    t1,tp,0x1
     96 			0x004343b3,	//xor     t2,t1,tp
     97 			0x03822413,	//slti    s0,tp,56
     98 			0xfff23493,	//sltiu   s1,tp,-1
     99 			0x00c005ef,	//jal     a1,4c <subroutine>
    100 			0x00c52423,	//sw      a2,8(a0)
    101 			0x00100073,	//ebreak
    102 			0x00720613,	//addi    a2,tp,7 # 7 <_start+0x7>
    103 			0x00058067	//jr      a1
    104 		},
    105 		.program_len = 21,
    106 		.exp = {
    107 			.x = {
    108 				[0] = 0x00000000,
    109 				[1] = 0x00000000,
    110 				[2] = 0x00000037,
    111 				[3] = 0x0000000b,
    112 				[4] = 0x00000037,
    113 				[5] = 0x0000000b,
    114 				[6] = 0x0000006e,
    115 				[7] = 0x00000059,
    116 				[8] = 0x00000001,
    117 				[9] = 0x00000001,
    118 				[10] = 0x00000100,
    119 				[11] = 0x00000044,
    120 				[12] = 0x0000003e,
    121 
    122 			},
    123 			.x_check_mask = ((UINT32_C(1) << 12) |
    124 					(UINT32_C(1) << 11) |
    125 					(UINT32_C(1) << 10) |
    126 					(UINT32_C(1) << 9) |
    127 					(UINT32_C(1) << 8) |
    128 					(UINT32_C(1) << 7) |
    129 					(UINT32_C(1) << 6) |
    130 					(UINT32_C(1) << 5) |
    131 					(UINT32_C(1) << 4) |
    132 					(UINT32_C(1) << 3) |
    133 					(UINT32_C(1) << 2) |
    134 					(UINT32_C(1) << 1) |
    135 					(UINT32_C(1))),
    136 			.pc = 0x48
    137 		}
    138 	},
    139 };
    140 
    141 static void
    142 load_program(uint8_t *mem, uint32_t arr[], size_t len)
    143 {
    144 	int b = 0; /*byte*/
    145 	for (size_t i=0; i<len; i++) {
    146 		
    147 		mem[b+0] = (uint8_t)(arr[i] >> 0);
    148 		mem[b+1] = (uint8_t)(arr[i] >> 8);
    149 		mem[b+2] = (uint8_t)(arr[i] >> 16);
    150 		mem[b+3] = (uint8_t)(arr[i] >> 24);
    151 
    152 		b+=4;
    153 	}
    154 }
    155 
    156 static void
    157 print_trap(cpu_state_t *cpu)
    158 {
    159 	if (cpu->status == CPU_TRAPPED) {
    160 		switch(cpu->trap.cause) {
    161 		case TRAP_EBREAK:
    162 			printf("Code reached breakpoint\n");
    163 			break;
    164 		case TRAP_ECALL:
    165 			printf("Code ECALL\n");
    166 			break;
    167 		case TRAP_ILLEGAL_INSTRUCTION:
    168 			printf("Illegal instruction\n");
    169 			break;
    170 		case TRAP_INSTRUCTION_MISALIGNED: 
    171 			printf("Instruction misaligned\n");
    172 			break;
    173 		case TRAP_INSTRUCTION_ACCESS_FAULT: 
    174 			printf("Instruction access fault\n");
    175 			break;
    176 		case TRAP_NONE:
    177 			printf("No trap cause\n");
    178 			break;
    179 		}
    180 	}
    181 }
    182 
    183 int
    184 main()
    185 {
    186 	size_t n = sizeof(tests) / sizeof(test_t);
    187 
    188 	int n_p = 0;
    189 	int n_f = 0;
    190 	for (size_t i=0; i<n; i++) {
    191 
    192 		cpu_state_t cpu = {0};
    193 		uint8_t mem[MEMSIZE] = {0};
    194 		
    195 		load_program(mem, tests[i].program, tests[i].program_len);
    196 		
    197 		/* fetch & run */
    198 		while (1) {
    199 			cpu_step(&cpu, mem);
    200 			if (cpu.status == CPU_TRAPPED) {
    201 				break;
    202 			}
    203 		}
    204 
    205 		for (int j=0; j<32; j++) {
    206 			if ((UINT32_C(1) << j) == tests[i].exp.x_check_mask) {
    207 				if (cpu.x[j] != tests[i].exp.x[j]) {
    208 					tests[i].result = TEST_FAILURE;
    209 					printf( "bad register %d. Expected %x, got %x\n",
    210 						j, tests[i].exp.x[j], cpu.x[j]);
    211 				}
    212 			}
    213 
    214 			if (cpu.pc != tests[i].exp.pc) {
    215 				tests[i].result = TEST_FAILURE;
    216 				puts("bad pc\n");
    217 			}
    218 		}
    219 		if (tests[i].result != TEST_FAILURE) {
    220 			printf("ok - %s (%zu)\n", tests[i].name, i);
    221 			n_p++;
    222 		} else {
    223 			printf("not ok - %s (%zu)\n   ", tests[i].name, i);
    224 			print_trap(&cpu);
    225 			n_f++;
    226 		}
    227 
    228 	}
    229 	printf("\n%d passed, %d failed\n", n_p, n_f);
    230 
    231 	return 0;
    232 }