Merged RV64IMFD extensions to master branch
This commit is contained in:
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;
|
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 > 1);
|
||||||
assert(width <= 64);
|
assert(width <= 64);
|
||||||
uint64_t mask = (1 << width) - 1;
|
uint64_t unity = 1;
|
||||||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
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 > 1);
|
||||||
assert(width <= 128);
|
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;
|
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_cores_(num_cores)
|
||||||
, num_warps_(num_warps)
|
, num_warps_(num_warps)
|
||||||
, num_threads_(num_threads)
|
, num_threads_(num_threads)
|
||||||
, wsize_(8)
|
, wsize_(4)
|
||||||
, vsize_(16)
|
, vsize_(16)
|
||||||
, num_regs_(32)
|
, num_regs_(32)
|
||||||
, num_csrs_(4096)
|
, num_csrs_(4096)
|
||||||
@@ -66,4 +66,6 @@ public:
|
|||||||
uint16_t num_cores() const {
|
uint16_t num_cores() const {
|
||||||
return num_cores_;
|
return num_cores_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -406,8 +406,8 @@ Word Core::icache_read(Addr addr, Size size) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Word Core::dcache_read(Addr addr, Size size) {
|
DoubleWord Core::dcache_read(Addr addr, Size size) {
|
||||||
Word data;
|
DoubleWord data;
|
||||||
auto type = get_addr_type(addr, size);
|
auto type = get_addr_type(addr, size);
|
||||||
if (type == AddrType::Shared) {
|
if (type == AddrType::Shared) {
|
||||||
smem_.read(&data, addr & (SMEM_SIZE-1), size);
|
smem_.read(&data, addr & (SMEM_SIZE-1), size);
|
||||||
@@ -417,7 +417,7 @@ Word Core::dcache_read(Addr addr, Size size) {
|
|||||||
return data;
|
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
|
if (addr >= IO_COUT_ADDR
|
||||||
&& addr <= (IO_COUT_ADDR + IO_COUT_SIZE - 1)) {
|
&& addr <= (IO_COUT_ADDR + IO_COUT_SIZE - 1)) {
|
||||||
this->writeToStdOut(addr, data);
|
this->writeToStdOut(addr, data);
|
||||||
|
|||||||
@@ -109,9 +109,9 @@ public:
|
|||||||
|
|
||||||
Word icache_read(Addr, Size);
|
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);
|
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::VSET, {false, InstType::V_TYPE}},
|
||||||
{Opcode::GPGPU, {false, InstType::R_TYPE}},
|
{Opcode::GPGPU, {false, InstType::R_TYPE}},
|
||||||
{Opcode::GPU, {false, InstType::R4_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) {
|
static const char* op_string(const Instr &instr) {
|
||||||
@@ -494,17 +496,25 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||||||
break;
|
break;
|
||||||
case Opcode::I_INST:
|
case Opcode::I_INST:
|
||||||
if (func3 == 0x1 || func3 == 0x5) {
|
if (func3 == 0x1 || func3 == 0x5) {
|
||||||
// simx64
|
// int5
|
||||||
// int6
|
instr->setImm(sext64(rs2, 5));
|
||||||
instr->setImm(sext32(rs2, 6));
|
|
||||||
} else {
|
} else {
|
||||||
// int12
|
// 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;
|
break;
|
||||||
default:
|
default:
|
||||||
// int12
|
// int12
|
||||||
instr->setImm(sext32(code >> shift_rs2_, 12));
|
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -516,9 +526,8 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||||||
instr->setSrcReg(rs2);
|
instr->setSrcReg(rs2);
|
||||||
}
|
}
|
||||||
instr->setFunc3(func3);
|
instr->setFunc3(func3);
|
||||||
// simx64
|
|
||||||
DoubleWord imm = (func7 << reg_s_) | rd;
|
DoubleWord imm = (func7 << reg_s_) | rd;
|
||||||
instr->setImm(sext32(imm, 12));
|
instr->setImm(sext64(imm, 12));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case InstType::B_TYPE: {
|
case InstType::B_TYPE: {
|
||||||
@@ -529,14 +538,13 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||||||
Word bits_4_1 = rd >> 1;
|
Word bits_4_1 = rd >> 1;
|
||||||
Word bit_10_5 = func7 & 0x3f;
|
Word bit_10_5 = func7 & 0x3f;
|
||||||
Word bit_12 = func7 >> 6;
|
Word bit_12 = func7 >> 6;
|
||||||
// simx64
|
|
||||||
DoubleWord imm = (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
|
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;
|
} break;
|
||||||
|
|
||||||
case InstType::U_TYPE:
|
case InstType::U_TYPE:
|
||||||
instr->setDestReg(rd);
|
instr->setDestReg(rd);
|
||||||
instr->setImm(sext32(code >> shift_func3_, 20));
|
instr->setImm(sext64(code >> shift_func3_, 20));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstType::J_TYPE: {
|
case InstType::J_TYPE: {
|
||||||
@@ -546,7 +554,6 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||||||
Word bit_11 = (unordered >> 8) & 0x1;
|
Word bit_11 = (unordered >> 8) & 0x1;
|
||||||
Word bits_10_1 = (unordered >> 9) & 0x3ff;
|
Word bits_10_1 = (unordered >> 9) & 0x3ff;
|
||||||
Word bit_20 = (unordered >> 19) & 0x1;
|
Word bit_20 = (unordered >> 19) & 0x1;
|
||||||
// simx64
|
|
||||||
DoubleWord imm = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
|
DoubleWord imm = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
|
||||||
if (bit_20) {
|
if (bit_20) {
|
||||||
imm |= ~j_imm_mask_;
|
imm |= ~j_imm_mask_;
|
||||||
@@ -616,8 +623,6 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||||||
}
|
}
|
||||||
instr->setFunc2(func2);
|
instr->setFunc2(func2);
|
||||||
instr->setFunc3(func3);
|
instr->setFunc3(func3);
|
||||||
// simx64
|
|
||||||
instr->setFunc2(func2);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::abort();
|
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) {
|
void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
||||||
assert(tmask_.any());
|
assert(tmask_.any());
|
||||||
|
|
||||||
DoubleWord nextPC = PC_ + 4;
|
DoubleWord nextPC = PC_ + core_->arch().wsize();
|
||||||
|
|
||||||
Word func2 = instr.getFunc2();
|
Word func2 = instr.getFunc2();
|
||||||
Word func3 = instr.getFunc3();
|
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) {
|
for (int t = 0; t < num_threads; ++t) {
|
||||||
if (!tmask_.test(t))
|
if (!tmask_.test(t))
|
||||||
continue;
|
continue;
|
||||||
// simx64
|
|
||||||
rddata[t] = ((immsrc << 12) & 0xfffffffffffff000) + PC_;
|
rddata[t] = ((immsrc << 12) & 0xfffffffffffff000) + PC_;
|
||||||
}
|
}
|
||||||
rd_write = true;
|
rd_write = true;
|
||||||
@@ -334,6 +333,133 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
}
|
}
|
||||||
rd_write = true;
|
rd_write = true;
|
||||||
break;
|
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:
|
case B_INST:
|
||||||
trace->exe_type = ExeType::ALU;
|
trace->exe_type = ExeType::ALU;
|
||||||
trace->alu.type = AluType::BRANCH;
|
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) {
|
for (int t = 0; t < num_threads; ++t) {
|
||||||
if (!tmask_.test(t))
|
if (!tmask_.test(t))
|
||||||
continue;
|
continue;
|
||||||
DoubleWord mem_addr = ((rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFF8); // word aligned
|
DoubleWord mem_addr = ((rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFF8); // double word aligned
|
||||||
Word shift_by = ((rsdata[t][0] + immsrc) & 0x00000007) * 8;
|
DoubleWord shift_by = ((rsdata[t][0] + immsrc) & 0x00000007) * 8;
|
||||||
// simx64
|
|
||||||
DoubleWord data_read = core_->dcache_read(mem_addr, 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);
|
DP(4, "LOAD MEM: ADDRESS=0x" << std::hex << mem_addr << ", DATA=0x" << data_read);
|
||||||
switch (func3) {
|
switch (func3) {
|
||||||
case 0:
|
case 0:
|
||||||
// RV32I: LBI
|
// RV32I: LBI
|
||||||
rddata[t] = sext32((data_read >> shift_by) & 0xFF, 8);
|
rddata[t] = sext64((data_read >> shift_by) & 0xFF, 8);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// RV32I: LHI
|
// RV32I: LHI
|
||||||
rddata[t] = sext32((data_read >> shift_by) & 0xFFFF, 16);
|
rddata[t] = sext64((data_read >> shift_by) & 0xFFFF, 16);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// RV32I: LW
|
// RV32I: LW
|
||||||
rddata[t] = sext32((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
rddata[t] = sext64((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// RV64I: LD
|
// RV64I: LD
|
||||||
rddata[t] = data_read;
|
rddata[t] = data_read;
|
||||||
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
// RV32I: LBU
|
// RV32I: LBU
|
||||||
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFF);
|
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFF);
|
||||||
@@ -456,6 +582,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
case 6:
|
case 6:
|
||||||
// RV64I: LWU
|
// RV64I: LWU
|
||||||
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFFFFFFFF);
|
rddata[t] = DoubleWord((data_read >> shift_by) & 0xFFFFFFFF);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
@@ -514,6 +641,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
case 3:
|
case 3:
|
||||||
// RV64I: SD
|
// RV64I: SD
|
||||||
core_->dcache_write(mem_addr, rsdata[t][1], 8);
|
core_->dcache_write(mem_addr, rsdata[t][1], 8);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
@@ -535,120 +663,6 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SYS_INST:
|
||||||
for (int t = 0; t < num_threads; ++t) {
|
for (int t = 0; t < num_threads; ++t) {
|
||||||
if (!tmask_.test(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(rsrc0);
|
||||||
trace->used_fregs.set(rsrc1);
|
trace->used_fregs.set(rsrc1);
|
||||||
break;
|
break;
|
||||||
case 0x0c: // RV32F: FDIV.D
|
case 0x0d: // RV32F: FDIV.D
|
||||||
rddata[t] = rv_fdiv_d(rsdata[t][0], rsdata[t][1], frm, &fflags);
|
rddata[t] = rv_fdiv_d(rsdata[t][0], rsdata[t][1], frm, &fflags);
|
||||||
trace->fpu.type = FpuType::FDIV;
|
trace->fpu.type = FpuType::FDIV;
|
||||||
trace->used_fregs.set(rsrc0);
|
trace->used_fregs.set(rsrc0);
|
||||||
@@ -848,19 +862,19 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
switch(rsrc1) {
|
switch(rsrc1) {
|
||||||
case 0:
|
case 0:
|
||||||
// RV32F: FCVT.W.S
|
// 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;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// RV32F: FCVT.WU.S
|
// 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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// RV64F: FCVT.L.S
|
// RV64F: FCVT.L.S
|
||||||
rddata[t] = rv_ftol(rsdata[0], frm, &fflags);
|
rddata[t] = rv_ftol(rsdata[t][0], frm, &fflags);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// RV64F: FCVT.LU.S
|
// RV64F: FCVT.LU.S
|
||||||
rddata[t] = rv_ftolu(rsdata[0], frm, &fflags);
|
rddata[t] = rv_ftolu(rsdata[t][0], frm, &fflags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace->fpu.type = FpuType::FCVT;
|
trace->fpu.type = FpuType::FCVT;
|
||||||
@@ -870,19 +884,19 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||||||
switch(rsrc1) {
|
switch(rsrc1) {
|
||||||
case 0:
|
case 0:
|
||||||
// RV32F: FCVT.W.D
|
// 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;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// RV32F: FCVT.WU.D
|
// 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;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// RV64F: FCVT.L.D
|
// RV64F: FCVT.L.D
|
||||||
rddata[t] = rv_ftol_d(rsdata[0], frm, &fflags);
|
rddata[t] = rv_ftol_d(rsdata[t][0], frm, &fflags);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// RV64F: FCVT.LU.D
|
// RV64F: FCVT.LU.D
|
||||||
rddata[t] = rv_ftolu_d(rsdata[0], frm, &fflags);
|
rddata[t] = rv_ftolu_d(rsdata[t][0], frm, &fflags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trace->fpu.type = FpuType::FCVT;
|
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) {
|
if (PC_ != nextPC) {
|
||||||
DP(3, "*** Next PC: " << std::hex << nextPC << std::dec);
|
DP(3, "*** Next PC: " << std::hex << nextPC << std::dec);
|
||||||
PC_ = nextPC;
|
PC_ = nextPC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
using namespace vortex;
|
using namespace vortex;
|
||||||
|
|
||||||
@@ -79,7 +80,8 @@ int main(int argc, char **argv) {
|
|||||||
processor.attach_ram(&ram);
|
processor.attach_ram(&ram);
|
||||||
|
|
||||||
// run simulation
|
// run simulation
|
||||||
processor.run();
|
exitcode = processor.run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riscv_test) {
|
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)
|
ALL_TESTS := $(wildcard *.hex)
|
||||||
|
|
||||||
EXCLUDED_TESTS := rv64ud-p-move.hex
|
EXCLUDED_TESTS := rv64ud-p-move.hex
|
||||||
@@ -23,19 +12,19 @@ TESTS := $(I_TESTS) $(M_TESTS) $(F_TESTS) $(D_TESTS)
|
|||||||
all:
|
all:
|
||||||
|
|
||||||
run-simx-i:
|
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:
|
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:
|
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:
|
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:
|
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:
|
run-rtlsim:
|
||||||
$(foreach test, $(TESTS), ../../../sim/rtlsim/rtlsim -r $(test) || exit;)
|
$(foreach test, $(TESTS), ../../../sim/rtlsim/rtlsim -r $(test) || exit;)
|
||||||
|
|||||||
Reference in New Issue
Block a user