Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sim/simx/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ instr_trace_t* Emulator::execute(const Instr &instr, uint32_t wid) {
continue;
rd_data[t].i = next_pc;
}
next_pc = rs1_data[thread_last].i + offset;
next_pc = (rs1_data[thread_last].u + offset) & ~Word(1);
trace->fetch_stall = true;
rd_write = true;
} break;
Expand Down Expand Up @@ -1562,4 +1562,4 @@ instr_trace_t* Emulator::execute(const Instr &instr, uint32_t wid) {
}

return trace;
}
}
4 changes: 4 additions & 0 deletions tests/regression/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NP ?= 4

all:
$(MAKE) -C basic
$(MAKE) -C jalr
$(MAKE) -C demo
$(MAKE) -C dogfood
$(MAKE) -C dropout
Expand Down Expand Up @@ -36,6 +37,7 @@ all-mpi:

run-simx:
$(MAKE) -C basic run-simx
$(MAKE) -C jalr run-simx
$(MAKE) -C demo run-simx
$(MAKE) -C dogfood run-simx
$(MAKE) -C dropout run-simx
Expand Down Expand Up @@ -67,6 +69,7 @@ run-simx-mpi:

run-rtlsim:
$(MAKE) -C basic run-rtlsim
$(MAKE) -C jalr run-rtlsim
$(MAKE) -C demo run-rtlsim
$(MAKE) -C dogfood run-rtlsim
$(MAKE) -C dropout run-rtlsim
Expand All @@ -88,6 +91,7 @@ run-rtlsim:

clean:
$(MAKE) -C basic clean
$(MAKE) -C jalr clean
$(MAKE) -C demo clean
$(MAKE) -C dogfood clean
$(MAKE) -C dropout clean
Expand Down
21 changes: 21 additions & 0 deletions tests/regression/jalr/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ROOT_DIR := $(realpath ../../..)
include $(ROOT_DIR)/config.mk

PROJECT := jalr

SRC_DIR := $(VORTEX_HOME)/tests/regression/$(PROJECT)

SRCS := $(SRC_DIR)/main.cpp

VX_SRCS := $(SRC_DIR)/kernel.cpp $(VORTEX_HOME)/kernel/src/vx_perf.c $(SRC_DIR)/start.S

OPTS ?=

include ../common.mk

VX_LDFLAGS = -Wl,-Bstatic,--gc-sections,-T,$(VORTEX_HOME)/kernel/scripts/link$(XLEN).ld,--defsym=STARTUP_ADDR=$(STARTUP_ADDR)

VX_CC = $(RISCV_TOOLCHAIN_PATH)/bin/$(RISCV_PREFIX)-gcc
VX_CXX = $(RISCV_TOOLCHAIN_PATH)/bin/$(RISCV_PREFIX)-g++
VX_DP = $(RISCV_TOOLCHAIN_PATH)/bin/$(RISCV_PREFIX)-objdump
VX_CP = $(RISCV_TOOLCHAIN_PATH)/bin/$(RISCV_PREFIX)-objcopy
8 changes: 8 additions & 0 deletions tests/regression/jalr/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _COMMON_H_
#define _COMMON_H_

typedef struct {
uint64_t dst_addr;
} kernel_arg_t;

#endif
52 changes: 52 additions & 0 deletions tests/regression/jalr/kernel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <vx_intrinsics.h>
#include "common.h"

int main() {
kernel_arg_t* __UNIFORM__ arg = (kernel_arg_t*)csr_read(VX_CSR_MSCRATCH);

if (vx_warp_id() != 0 || vx_thread_id() != 0)
return 0;

uint32_t value = 0;
asm volatile(
// x1 is prepared so that the misaligned decode path can immediately
// execute a valid JALR to label 3 and produce a deterministic failure
// value instead of aborting in the decoder.
"la x1, 3f\n"
// 1744 is chosen to match the immediate embedded in the overlapped
// misaligned instruction below: jalr x0, -1744(x1).
"addi x1, x1, 1744\n"
"la t0, 1f\n"
// Add 1 on purpose. A correct JALR implementation must clear bit 0 and
// land at 1f. An incorrect implementation enters at 1f + 1 instead.
"addi t0, t0, 1\n"
"jalr x0, t0, 0\n"
".balign 4\n"
"1:\n"
// 0x00806713 is a hand-picked overlapped instruction word:
// - from the aligned entry at 1f it decodes as: ori x14, x0, 8
// - from the misaligned entry at 1f + 1 it decodes as:
// jalr x0, -1744(x1)
//
// That lets both fixed and unfixed builds decode valid instructions while
// still producing different results.
".4byte 0x00806713\n"
// This is the next aligned instruction after the pass-path overlap word.
".4byte 0x00000093\n"
"j 4f\n"
"3:\n"
// Fail signature used when JALR does not clear bit 0.
"li %[value], 0x2468ace0\n"
"j 5f\n"
"4:\n"
// Pass signature used when JALR correctly clears bit 0.
"li %[value], 0x13579bdf\n"
"5:\n"
: [value] "=r" (value)
:
: "x1", "t0", "x14");

uint32_t* dst_ptr = (uint32_t*)arg->dst_addr;
dst_ptr[vx_core_id()] = value;
return 0;
}
87 changes: 87 additions & 0 deletions tests/regression/jalr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <vector>
#include <vortex.h>
#include "common.h"

#define RT_CHECK(_expr) \
do { \
int _ret = _expr; \
if (0 == _ret) \
break; \
printf("Error: '%s' returned %d!\n", #_expr, (int)_ret); \
cleanup(); \
exit(-1); \
} while (false)

static constexpr uint32_t kPassValue = 0x13579bdf;

const char* kernel_file = "kernel.vxbin";

vx_device_h device = nullptr;
vx_buffer_h dst_buffer = nullptr;
vx_buffer_h krnl_buffer = nullptr;
vx_buffer_h args_buffer = nullptr;
kernel_arg_t kernel_arg = {};

void cleanup() {
if (device) {
vx_mem_free(dst_buffer);
vx_mem_free(krnl_buffer);
vx_mem_free(args_buffer);
vx_dev_close(device);
}
}

int main() {
std::cout << "open device connection" << std::endl;
RT_CHECK(vx_dev_open(&device));

uint64_t num_cores = 0;
RT_CHECK(vx_dev_caps(device, VX_CAPS_NUM_CORES, &num_cores));

uint32_t buf_size = num_cores * sizeof(uint32_t);
std::vector<uint32_t> h_dst(num_cores, 0);

std::cout << "allocate device memory" << std::endl;
RT_CHECK(vx_mem_alloc(device, buf_size, VX_MEM_WRITE, &dst_buffer));
RT_CHECK(vx_mem_address(dst_buffer, &kernel_arg.dst_addr));
RT_CHECK(vx_copy_to_dev(dst_buffer, h_dst.data(), 0, buf_size));

std::cout << "upload kernel binary" << std::endl;
RT_CHECK(vx_upload_kernel_file(device, kernel_file, &krnl_buffer));

std::cout << "upload kernel argument" << std::endl;
RT_CHECK(vx_upload_bytes(device, &kernel_arg, sizeof(kernel_arg_t), &args_buffer));

std::cout << "start device" << std::endl;
RT_CHECK(vx_start(device, krnl_buffer, args_buffer));
RT_CHECK(vx_ready_wait(device, VX_MAX_TIMEOUT));

std::cout << "download destination buffer" << std::endl;
RT_CHECK(vx_copy_from_dev(h_dst.data(), dst_buffer, 0, buf_size));

int errors = 0;
for (uint64_t i = 0; i < num_cores; ++i) {
if (h_dst[i] != kPassValue) {
std::cout << "error at core " << std::dec << i
<< ": actual=0x" << std::hex << h_dst[i]
<< ", expected=0x" << kPassValue << std::endl;
++errors;
}
}

std::cout << "cleanup" << std::endl;
cleanup();

if (errors != 0) {
std::cout << "FAILED!" << std::endl;
return errors;
}

std::cout << "PASSED!" << std::endl;
return 0;
}
24 changes: 24 additions & 0 deletions tests/regression/jalr/start.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright © 2019-2023
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <VX_config.h>
#include <VX_types.h>

.section .init, "ax"
.global _start
.type _start, @function
_start:
call main
call vx_perf_dump
.insn r 0x0b, 0, 0, x0, x0, x0
.size _start, .-_start
Loading