mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-23 21:39:10 -04:00
Merged RV64IMFD extensions to master branch
This commit is contained in:
parent
3324b32a29
commit
885bb58ca9
10 changed files with 237 additions and 225 deletions
48
miscs/docker/vortex/Dockerfile
Normal file
48
miscs/docker/vortex/Dockerfile
Normal file
|
@ -0,0 +1,48 @@
|
|||
# Dockerfile for setting up the vortex development environment
|
||||
|
||||
FROM ubuntu:18.04
|
||||
|
||||
# Install dependencies
|
||||
RUN apt update && apt install -y \
|
||||
git build-essential g++ libfl2 \
|
||||
libfl-dev zlibc zlib1g zlib1g-dev \
|
||||
ccache libgoogle-perftools-dev numactl perl-doc \
|
||||
python3 device-tree-compiler gdb
|
||||
|
||||
# Download vortex-toolchain-prebuilt
|
||||
RUN git clone https://github.com/SantoshSrivatsan24/vortex-toolchain-prebuilt.git /tmp/vortex-toolchain-prebuilt
|
||||
|
||||
# Copy riscv-gnu-toolchain
|
||||
RUN cd /tmp/vortex-toolchain-prebuilt/riscv-gnu-toolchain/ubuntu/bionic; \
|
||||
cat riscv-gnu-toolchain.tar.bz2.part* > riscv-gnu-toolchain.tar.bz2; \
|
||||
tar -xf riscv-gnu-toolchain.tar.bz2 -C /opt/;
|
||||
|
||||
# Copy riscv64-gnu-toolchain
|
||||
RUN cd /tmp/vortex-toolchain-prebuilt/riscv64-gnu-toolchain/ubuntu/bionic; \
|
||||
cat riscv64-gnu-toolchain.tar.bz2.part* > riscv64-gnu-toolchain.tar.bz2; \
|
||||
tar -xf riscv64-gnu-toolchain.tar.bz2 -C /opt/;
|
||||
|
||||
# Copy llvm-riscv
|
||||
RUN cd /tmp/vortex-toolchain-prebuilt/llvm-riscv/ubuntu/bionic; \
|
||||
cat llvm-riscv.tar.bz2.part* > llvm-riscv.tar.bz2; \
|
||||
tar -xf llvm-riscv.tar.bz2 -C /opt/;
|
||||
|
||||
# Copy pocl
|
||||
RUN cd /tmp/vortex-toolchain-prebuilt/pocl/ubuntu/bionic; \
|
||||
tar -xf pocl.tar.bz2 -C /opt/;
|
||||
|
||||
# Copy verilator
|
||||
RUN cd /tmp/vortex-toolchain-prebuilt/verilator/ubuntu/bionic; \
|
||||
tar -xf verilator.tar.bz2 -C /opt/;
|
||||
|
||||
# Set environment variables
|
||||
ENV RISCV_TOOLCHAIN_PATH=/opt/riscv-gnu-toolchain
|
||||
ENV RISCV64_TOOLCHAIN_PATH=/opt/riscv64-gnu-toolchain
|
||||
ENV VERILATOR_ROOT=/opt/verilator
|
||||
ENV PATH=$PATH:/${RISCV_TOOLCHAIN_PATH}/bin:${RISCV64_TOOLCHAIN_PATH}/bin:${RISCV64_TOOLCHAIN_PATH}/riscv64-unknown-elf/bin:${VERILATOR_ROOT}/bin
|
||||
|
||||
# Cleanup
|
||||
RUN rm -rf /tmp/vortex-toolchain-prebuilt
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /home/vortex
|
|
@ -78,16 +78,18 @@ inline uint32_t sext32(uint32_t word, uint32_t width) {
|
|||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
||||
|
||||
inline uint32_t sext64(uint64_t word, uint32_t width) {
|
||||
inline uint64_t sext64(uint64_t word, uint64_t width) {
|
||||
assert(width > 1);
|
||||
assert(width <= 64);
|
||||
uint64_t mask = (1 << width) - 1;
|
||||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
uint64_t unity = 1;
|
||||
uint64_t mask = (unity << width) - 0x1;
|
||||
return ((word >> (width - 0x1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
||||
|
||||
inline uint32_t sext128(__uint128_t word, uint32_t width) {
|
||||
inline __uint128_t sext128(__uint128_t word, uint32_t width) {
|
||||
assert(width > 1);
|
||||
assert(width <= 128);
|
||||
uint128_t mask = (1 << width) - 1;
|
||||
__uint128_t unity = 1;
|
||||
__uint128_t mask = (unity << width) - 1;
|
||||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
RTL_DIR = ../hw/rtl
|
||||
|
||||
CXXFLAGS += -std=c++11 -Wall -Wextra -Wfatal-errors -Werror -g
|
||||
CXXFLAGS += -fPIC -Wno-maybe-uninitialized
|
||||
CXXFLAGS += -I. -I../common -I../../hw
|
||||
CXXFLAGS += -I../common/softfloat/source/include
|
||||
CXXFLAGS += $(CONFIGS)
|
||||
|
||||
LDFLAGS += ../common/softfloat/build/Linux-x86_64-GCC/softfloat.a
|
||||
|
||||
TOP = vx_cache_sim
|
||||
|
||||
SRCS = ../common/util.cpp ../common/mem.cpp ../common/rvfloats.cpp
|
||||
SRCS += args.cpp pipeline.cpp warp.cpp core.cpp decode.cpp execute.cpp main.cpp
|
||||
|
||||
OBJS := $(patsubst %.cpp, obj_dir/%.o, $(notdir $(SRCS)))
|
||||
VPATH := $(sort $(dir $(SRCS)))
|
||||
|
||||
#$(info OBJS is $(OBJS))
|
||||
#$(info VPATH is $(VPATH))
|
||||
|
||||
# Debugigng
|
||||
ifdef DEBUG
|
||||
CXXFLAGS += -g -O0 -DDEBUG_LEVEL=$(DEBUG)
|
||||
else
|
||||
CXXFLAGS += -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
PROJECT = simX
|
||||
|
||||
all: $(PROJECT)
|
||||
|
||||
$(PROJECT): $(SRCS)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
obj_dir/%.o: %.cpp
|
||||
mkdir -p obj_dir
|
||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
static: $(OBJS)
|
||||
$(AR) rcs lib$(PROJECT).a $(OBJS) ../common/softfloat/build/Linux-x86_64-GCC/*.o
|
||||
|
||||
.depend: $(SRCS)
|
||||
$(CXX) $(CXXFLAGS) -MM $^ > .depend;
|
||||
|
||||
clean-static:
|
||||
rm -rf lib$(PROJECT).a obj_dir .depend
|
||||
|
||||
clean: clean-static
|
||||
rm -rf $(PROJECT)
|
|
@ -28,7 +28,7 @@ public:
|
|||
: num_cores_(num_cores)
|
||||
, num_warps_(num_warps)
|
||||
, num_threads_(num_threads)
|
||||
, wsize_(8)
|
||||
, wsize_(4)
|
||||
, vsize_(16)
|
||||
, num_regs_(32)
|
||||
, num_csrs_(4096)
|
||||
|
@ -66,4 +66,6 @@ public:
|
|||
uint16_t num_cores() const {
|
||||
return num_cores_;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
|
@ -406,8 +406,8 @@ Word Core::icache_read(Addr addr, Size size) {
|
|||
return data;
|
||||
}
|
||||
|
||||
Word Core::dcache_read(Addr addr, Size size) {
|
||||
Word data;
|
||||
DoubleWord Core::dcache_read(Addr addr, Size size) {
|
||||
DoubleWord data;
|
||||
auto type = get_addr_type(addr, size);
|
||||
if (type == AddrType::Shared) {
|
||||
smem_.read(&data, addr & (SMEM_SIZE-1), size);
|
||||
|
@ -417,7 +417,7 @@ Word Core::dcache_read(Addr addr, Size size) {
|
|||
return data;
|
||||
}
|
||||
|
||||
void Core::dcache_write(Addr addr, Word data, Size size) {
|
||||
void Core::dcache_write(Addr addr, DoubleWord data, Size size) {
|
||||
if (addr >= IO_COUT_ADDR
|
||||
&& addr <= (IO_COUT_ADDR + IO_COUT_SIZE - 1)) {
|
||||
this->writeToStdOut(addr, data);
|
||||
|
|
|
@ -109,9 +109,9 @@ public:
|
|||
|
||||
Word icache_read(Addr, Size);
|
||||
|
||||
Word dcache_read(Addr, Size);
|
||||
DoubleWord dcache_read(Addr, Size);
|
||||
|
||||
void dcache_write(Addr, Word, Size);
|
||||
void dcache_write(Addr, DoubleWord, Size);
|
||||
|
||||
Word tex_read(uint32_t unit, Word lod, Word u, Word v, std::vector<mem_addr_size_t>* mem_addrs);
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ static const std::unordered_map<int, struct InstTableEntry_t> sc_instTable = {
|
|||
{Opcode::VSET, {false, InstType::V_TYPE}},
|
||||
{Opcode::GPGPU, {false, InstType::R_TYPE}},
|
||||
{Opcode::GPU, {false, InstType::R4_TYPE}},
|
||||
{Opcode::R_INST_64, {false, InstType::R_TYPE}},
|
||||
{Opcode::I_INST_64, {false, InstType::I_TYPE}},
|
||||
};
|
||||
|
||||
static const char* op_string(const Instr &instr) {
|
||||
|
@ -494,17 +496,25 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
break;
|
||||
case Opcode::I_INST:
|
||||
if (func3 == 0x1 || func3 == 0x5) {
|
||||
// simx64
|
||||
// int6
|
||||
instr->setImm(sext32(rs2, 6));
|
||||
// int5
|
||||
instr->setImm(sext64(rs2, 5));
|
||||
} else {
|
||||
// int12
|
||||
instr->setImm(sext32(code >> shift_rs2_, 12));
|
||||
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||
}
|
||||
break;
|
||||
case Opcode::I_INST_64:
|
||||
if (func3 == 0x1 || func3 == 0x5) {
|
||||
// int4
|
||||
instr->setImm(sext64(rs2, 4));
|
||||
} else {
|
||||
// int12
|
||||
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// int12
|
||||
instr->setImm(sext32(code >> shift_rs2_, 12));
|
||||
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
@ -516,9 +526,8 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
instr->setSrcReg(rs2);
|
||||
}
|
||||
instr->setFunc3(func3);
|
||||
// simx64
|
||||
DoubleWord imm = (func7 << reg_s_) | rd;
|
||||
instr->setImm(sext32(imm, 12));
|
||||
instr->setImm(sext64(imm, 12));
|
||||
} break;
|
||||
|
||||
case InstType::B_TYPE: {
|
||||
|
@ -529,14 +538,13 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
Word bits_4_1 = rd >> 1;
|
||||
Word bit_10_5 = func7 & 0x3f;
|
||||
Word bit_12 = func7 >> 6;
|
||||
// simx64
|
||||
DoubleWord imm = (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
|
||||
instr->setImm(sext32(imm, 13));
|
||||
instr->setImm(sext64(imm, 13));
|
||||
} break;
|
||||
|
||||
case InstType::U_TYPE:
|
||||
instr->setDestReg(rd);
|
||||
instr->setImm(sext32(code >> shift_func3_, 20));
|
||||
instr->setImm(sext64(code >> shift_func3_, 20));
|
||||
break;
|
||||
|
||||
case InstType::J_TYPE: {
|
||||
|
@ -546,7 +554,6 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
Word bit_11 = (unordered >> 8) & 0x1;
|
||||
Word bits_10_1 = (unordered >> 9) & 0x3ff;
|
||||
Word bit_20 = (unordered >> 19) & 0x1;
|
||||
// simx64
|
||||
DoubleWord imm = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
|
||||
if (bit_20) {
|
||||
imm |= ~j_imm_mask_;
|
||||
|
@ -616,8 +623,6 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
}
|
||||
instr->setFunc2(func2);
|
||||
instr->setFunc3(func3);
|
||||
// simx64
|
||||
instr->setFunc2(func2);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
|
|
|
@ -52,7 +52,7 @@ inline void update_fcrs(uint32_t fflags, Core* core, uint32_t tid, uint32_t wid)
|
|||
void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
||||
assert(tmask_.any());
|
||||
|
||||
DoubleWord nextPC = PC_ + 4;
|
||||
DoubleWord nextPC = PC_ + core_->arch().wsize();
|
||||
|
||||
Word func2 = instr.getFunc2();
|
||||
Word func3 = instr.getFunc3();
|
||||
|
@ -134,7 +134,6 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
// simx64
|
||||
rddata[t] = ((immsrc << 12) & 0xfffffffffffff000) + PC_;
|
||||
}
|
||||
rd_write = true;
|
||||
|
@ -334,6 +333,133 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
case R_INST_64:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::ARITH;
|
||||
trace->used_iregs.set(rsrc0);
|
||||
trace->used_iregs.set(rsrc1);
|
||||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
if (func7 & 0x1){
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// RV64M: MULW
|
||||
rddata[t] = sext64((WordI)rsdata[t][0] * (WordI)rsdata[t][1], 32);
|
||||
break;
|
||||
case 4: {
|
||||
// RV64M: DIVW
|
||||
int32_t dividen = (WordI) rsdata[t][0];
|
||||
int32_t divisor = (WordI) rsdata[t][1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = -1;
|
||||
} else if (dividen == WordI(0x80000000) && divisor == WordI(0xFFFFFFFF)) {
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 5: {
|
||||
// RV64M: DIVUW
|
||||
uint32_t dividen = (Word) rsdata[t][0];
|
||||
uint32_t divisor = (Word) rsdata[t][1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = -1;
|
||||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 6: {
|
||||
// RV64M: REMW
|
||||
int32_t dividen = (WordI) rsdata[t][0];
|
||||
int32_t divisor = (WordI) rsdata[t][1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else if (dividen == WordI(0x80000000) && divisor == WordI(0xFFFFFFFF)) {
|
||||
rddata[t] = 0;
|
||||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 7: {
|
||||
// RV64M: REMUW
|
||||
uint32_t dividen = (Word) rsdata[t][0];
|
||||
uint32_t divisor = (Word) rsdata[t][1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
} else {
|
||||
switch (func3) {
|
||||
case 0:
|
||||
if (func7){
|
||||
// RV64I: SUBW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] - (Word)rsdata[t][1], 32);
|
||||
}
|
||||
else{
|
||||
// RV64I: ADDW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] + (Word)rsdata[t][1], 32);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// RV64I: SLLW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] << (Word)rsdata[t][1], 32);
|
||||
break;
|
||||
case 5:
|
||||
if (func7) {
|
||||
// RV64I: SRAW
|
||||
rddata[t] = sext64((WordI)rsdata[t][0] >> (WordI)rsdata[t][1], 32);
|
||||
} else {
|
||||
// RV64I: SRLW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] >> (Word)rsdata[t][1], 32);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
case I_INST_64:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::ARITH;
|
||||
trace->used_iregs.set(rsrc0);
|
||||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
switch (func3) {
|
||||
case 0: {
|
||||
// RV64I: ADDIW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] + (Word)immsrc, 32);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
// RV64I: SLLIW
|
||||
rddata[t] = sext64((Word)rsdata[t][0] << (Word)immsrc, 32);
|
||||
break;
|
||||
case 5:
|
||||
if (func7) {
|
||||
// RV64I: SRAIW
|
||||
DoubleWord result = sext64((WordI)rsdata[t][0] >> (WordI)immsrc, 32);
|
||||
rddata[t] = result;
|
||||
} else {
|
||||
// RV64I: SRLIW
|
||||
DoubleWord result = sext64((Word)rsdata[t][0] >> (Word)immsrc, 32);
|
||||
rddata[t] = result;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
case B_INST:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::BRANCH;
|
||||
|
@ -423,28 +549,28 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
DoubleWord mem_addr = ((rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFF8); // word aligned
|
||||
Word shift_by = ((rsdata[t][0] + immsrc) & 0x00000007) * 8;
|
||||
// simx64
|
||||
DoubleWord mem_addr = ((rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFF8); // double word aligned
|
||||
DoubleWord shift_by = ((rsdata[t][0] + immsrc) & 0x00000007) * 8;
|
||||
DoubleWord data_read = core_->dcache_read(mem_addr, 8);
|
||||
trace->mem_addrs.at(t).push_back({mem_addr, 4});
|
||||
trace->mem_addrs.at(t).push_back({mem_addr, 8});
|
||||
DP(4, "LOAD MEM: ADDRESS=0x" << std::hex << mem_addr << ", DATA=0x" << data_read);
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// RV32I: LBI
|
||||
rddata[t] = sext32((data_read >> shift_by) & 0xFF, 8);
|
||||
rddata[t] = sext64((data_read >> shift_by) & 0xFF, 8);
|
||||
break;
|
||||
case 1:
|
||||
// RV32I: LHI
|
||||
rddata[t] = sext32((data_read >> shift_by) & 0xFFFF, 16);
|
||||
rddata[t] = sext64((data_read >> shift_by) & 0xFFFF, 16);
|
||||
break;
|
||||
case 2:
|
||||
// RV32I: LW
|
||||
rddata[t] = sext32((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
||||
rddata[t] = sext64((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
||||
break;
|
||||
case 3:
|
||||
// RV64I: LD
|
||||
rddata[t] = data_read;
|
||||
break;
|
||||
case 4:
|
||||
// RV32I: LBU
|
||||
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFF);
|
||||
|
@ -456,6 +582,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
case 6:
|
||||
// RV64I: LWU
|
||||
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
|
@ -514,6 +641,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
case 3:
|
||||
// RV64I: SD
|
||||
core_->dcache_write(mem_addr, rsdata[t][1], 8);
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
|
@ -535,120 +663,6 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
// simx64
|
||||
case R_INST_64: {
|
||||
if (func7 & 0x1){
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// RV64M: MULW
|
||||
rddata[t] = sext64((WordI)rsdata[t][0] * (WordI)rsdata[t][1], 32);
|
||||
break;
|
||||
case 4: {
|
||||
// RV64M: DIVW
|
||||
int32_t dividen = (WordI) rsdata[t][0];
|
||||
int32_t divisor = (WordI) rsdata[t][1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = -1;
|
||||
} else if (dividen == WordI(0x80000000) && divisor == WordI(0xFFFFFFFF)) {
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 5: {
|
||||
// RV64M: DIVUW
|
||||
uint32_t dividen = (Word) rsdata[0];
|
||||
uint32_t divisor = (Word) rsdata[1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = -1;
|
||||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 6: {
|
||||
// RV64M: REMW
|
||||
int32_t dividen = (WordI) rsdata[0];
|
||||
int32_t divisor = (WordI) rsdata[1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else if (dividen == WordI(0x80000000) && divisor == WordI(0xFFFFFFFF)) {
|
||||
rddata[t] = 0;
|
||||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
} break;
|
||||
case 7: {
|
||||
// RV64M: REMUW
|
||||
uint32_t dividen = (Word) rsdata[0];
|
||||
uint32_t divisor = (Word) rsdata[1];
|
||||
if (divisor == 0){
|
||||
rddata[t] = sext64(dividen, 32);
|
||||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
} else {
|
||||
switch (func3) {
|
||||
case 0:
|
||||
if (func7){
|
||||
// RV64I: SUBW
|
||||
rddata[t] = sext64((Word)rsdata[0] - (Word)rsdata[1], 32);
|
||||
}
|
||||
else{
|
||||
// RV64I: ADDW
|
||||
rddata[t] = sext64((Word)rsdata[0] + (Word)rsdata[1], 32);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// RV64I: SLLW
|
||||
rddata[t] = sext64((Word)rsdata[0] << (Word)rsdata[1], 32);
|
||||
break;
|
||||
case 5:
|
||||
if (func7) {
|
||||
// RV64I: SRAW
|
||||
rddata[t] = sext64((WordI)rsdata[0] >> (WordI)rsdata[1], 32);
|
||||
} else {
|
||||
// RV64I: SRLW
|
||||
rddata[t] = sext64((Word)rsdata[0] >> (Word)rsdata[1], 32);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
rd_write = true;
|
||||
} break;
|
||||
|
||||
// simx64
|
||||
case I_INST_64: {
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// RV64I: ADDIW
|
||||
rddata[t] = sext64((Word)rsdata[0] + (Word)immsrc, 32);
|
||||
break;
|
||||
case 1:
|
||||
// RV64I: SLLIW
|
||||
rddata[t] = sext64((Word)rsdata[0] << (Word)immsrc, 32);
|
||||
break;
|
||||
case 5:
|
||||
if (func7) {
|
||||
// RV64I: SRAIW
|
||||
DoubleWord result = sext64((WordI)rsdata[0] >> (WordI)immsrc, 32);
|
||||
rddata[t] = result;
|
||||
} else {
|
||||
// RV64I: SRLIW
|
||||
DoubleWord result = sext64((Word)rsdata[0] >> (Word)immsrc, 32);
|
||||
rddata[t] = result;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::abort();
|
||||
}
|
||||
rd_write = true;
|
||||
} break;
|
||||
case SYS_INST:
|
||||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
|
@ -776,7 +790,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
trace->used_fregs.set(rsrc0);
|
||||
trace->used_fregs.set(rsrc1);
|
||||
break;
|
||||
case 0x0c: // RV32F: FDIV.D
|
||||
case 0x0d: // RV32F: FDIV.D
|
||||
rddata[t] = rv_fdiv_d(rsdata[t][0], rsdata[t][1], frm, &fflags);
|
||||
trace->fpu.type = FpuType::FDIV;
|
||||
trace->used_fregs.set(rsrc0);
|
||||
|
@ -848,19 +862,19 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
switch(rsrc1) {
|
||||
case 0:
|
||||
// RV32F: FCVT.W.S
|
||||
rddata[t] = sext64(rv_ftoi(rsdata[0], frm, &fflags), 32);
|
||||
rddata[t] = sext64(rv_ftoi(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 1:
|
||||
// RV32F: FCVT.WU.S
|
||||
rddata[t] = sext64(rv_ftou(rsdata[0], frm, &fflags), 32);
|
||||
rddata[t] = sext64(rv_ftou(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 2:
|
||||
// RV64F: FCVT.L.S
|
||||
rddata[t] = rv_ftol(rsdata[0], frm, &fflags);
|
||||
rddata[t] = rv_ftol(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
case 3:
|
||||
// RV64F: FCVT.LU.S
|
||||
rddata[t] = rv_ftolu(rsdata[0], frm, &fflags);
|
||||
rddata[t] = rv_ftolu(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
}
|
||||
trace->fpu.type = FpuType::FCVT;
|
||||
|
@ -870,19 +884,19 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
switch(rsrc1) {
|
||||
case 0:
|
||||
// RV32F: FCVT.W.D
|
||||
rddata[t] = sext64(rv_ftoi_d(rsdata[0], frm, &fflags), 32);
|
||||
rddata[t] = sext64(rv_ftoi_d(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 1:
|
||||
// RV32F: FCVT.WU.D
|
||||
rddata[t] = sext64(rv_ftou_d(rsdata[0], frm, &fflags), 32);
|
||||
rddata[t] = sext64(rv_ftou_d(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 2:
|
||||
// RV64F: FCVT.L.D
|
||||
rddata[t] = rv_ftol_d(rsdata[0], frm, &fflags);
|
||||
rddata[t] = rv_ftol_d(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
case 3:
|
||||
// RV64F: FCVT.LU.D
|
||||
rddata[t] = rv_ftolu_d(rsdata[0], frm, &fflags);
|
||||
rddata[t] = rv_ftolu_d(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
}
|
||||
trace->fpu.type = FpuType::FCVT;
|
||||
|
@ -2123,9 +2137,9 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
}
|
||||
|
||||
PC_ += 4;
|
||||
PC_ += core_->arch().wsize();
|
||||
if (PC_ != nextPC) {
|
||||
DP(3, "*** Next PC: " << std::hex << nextPC << std::dec);
|
||||
PC_ = nextPC;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "constants.h"
|
||||
#include <util.h>
|
||||
#include "args.h"
|
||||
#include "core.h"
|
||||
|
||||
using namespace vortex;
|
||||
|
||||
|
@ -79,7 +80,8 @@ int main(int argc, char **argv) {
|
|||
processor.attach_ram(&ram);
|
||||
|
||||
// run simulation
|
||||
processor.run();
|
||||
exitcode = processor.run();
|
||||
|
||||
}
|
||||
|
||||
if (riscv_test) {
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
# ALL_TESTS := $(wildcard *.hex)
|
||||
|
||||
# D_TESTS := $(wildcard *ud-p-*.hex)
|
||||
# V_TESTS := $(wildcard *-v-*.hex)
|
||||
# M_TESTS := $(wildcard *um-*.hex)
|
||||
# A_TESTS := $(wildcard *ua-*.hex)
|
||||
|
||||
# EXCLUDED_TESTS := $(V_TESTS) $(D_TESTS) $(M_TESTS) $(A_TESTS) rv32si-p-scall.hex rv32si-p-sbreak.hex rv32mi-p-breakpoint.hex rv32ua-p-amomax_w.hex rv32ua-p-amoxor_w.hex rv32ua-p-amoor_w.hex rv32mi-p-ma_addr.hex rv32mi-p-mcsr.hex rv32ua-p-amoswap_w.hex rv32mi-p-ma_fetch.hex rv32mi-p-csr.hex rv32ua-p-amoadd_w.hex rv32si-p-dirty.hex rv32ui-p-fence_i.hex rv32si-p-csr.hex rv32mi-p-shamt.hex rv32ua-p-amomin_w.hex rv32ua-p-lrsc.hex rv32si-p-wfi.hex rv32ua-p-amomaxu_w.hex rv32si-p-ma_fetch.hex rv32mi-p-illegal.hex rv32uc-p-rvc.hex rv32mi-p-sbreak.hex rv32ua-p-amominu_w.hex rv32ua-p-amoand_w.hex
|
||||
|
||||
# TESTS := $(filter-out $(EXCLUDED_TESTS), $(ALL_TESTS))
|
||||
|
||||
ALL_TESTS := $(wildcard *.hex)
|
||||
|
||||
EXCLUDED_TESTS := rv64ud-p-move.hex
|
||||
|
@ -23,19 +12,19 @@ TESTS := $(I_TESTS) $(M_TESTS) $(F_TESTS) $(D_TESTS)
|
|||
all:
|
||||
|
||||
run-simx-i:
|
||||
$(foreach test, $(I_TESTS), ../../../sim/simX/simX -r -a rv64i -c 1 -i $(test) || exit;)
|
||||
$(foreach test, $(I_TESTS), ../../../sim/simx/simx -r -a rv64i -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-m:
|
||||
$(foreach test, $(M_TESTS), ../../../sim/simX/simX -r -a rv64im -c 1 -i $(test) || exit;)
|
||||
$(foreach test, $(M_TESTS), ../../../sim/simx/simx -r -a rv64im -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-f:
|
||||
$(foreach test, $(F_TESTS), ../../../sim/simX/simX -r -a rv64imf -c 1 -i $(test) || exit;)
|
||||
$(foreach test, $(F_TESTS), ../../../sim/simx/simx -r -a rv64imf -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-d:
|
||||
$(foreach test, $(D_TESTS), ../../../sim/simX/simX -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
$(foreach test, $(D_TESTS), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx:
|
||||
$(foreach test, $(TESTS), ../../../sim/simX/simX -r -a rv64i -c 1 -i $(test) || exit;)
|
||||
$(foreach test, $(TESTS), ../../../sim/simx/simx -r -a rv64i -c 1 -i $(test) || exit;)
|
||||
|
||||
run-rtlsim:
|
||||
$(foreach test, $(TESTS), ../../../sim/rtlsim/rtlsim -r $(test) || exit;)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue