mirror of
https://github.com/vortexgpgpu/vortex.git
synced 2025-04-23 21:39:10 -04:00
Added FLEN parameterization for RV32/64 F and D instructions
This commit is contained in:
parent
ad92c09f5b
commit
7aa93a735d
10 changed files with 140 additions and 96 deletions
|
@ -3,6 +3,7 @@
|
|||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include "xlen.h"
|
||||
|
||||
constexpr uint32_t count_leading_zeros(uint32_t value) {
|
||||
return value ? __builtin_clz(value) : 32;
|
||||
|
@ -71,10 +72,11 @@ inline uint64_t bit_getw(uint64_t bits, uint32_t start, uint32_t end) {
|
|||
}
|
||||
|
||||
// Apply integer sign extension
|
||||
inline uint32_t sext32(uint32_t word, uint32_t width) {
|
||||
inline uintx_t sext(uintx_t word, uint32_t width) {
|
||||
assert(width > 1);
|
||||
assert(width <= 32);
|
||||
uint32_t mask = (1 << width) - 1;
|
||||
uintx_t unity = 1;
|
||||
uintx_t mask = (unity << width) - 1;
|
||||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
||||
|
||||
|
@ -86,14 +88,15 @@ inline uint64_t sext64(uint64_t word, uint64_t width) {
|
|||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
||||
|
||||
inline __uint128_t sext128(__uint128_t word, uint32_t width) {
|
||||
inline uintm_t sext_mul(uintm_t word, uint32_t width) {
|
||||
assert(width > 1);
|
||||
assert(width <= 128);
|
||||
__uint128_t unity = 1;
|
||||
__uint128_t mask = (unity << width) - 1;
|
||||
assert(width <= 32);
|
||||
uintm_t unity = 1;
|
||||
uintm_t mask = (unity << width) - 1;
|
||||
return ((word >> (width - 1)) & 0x1) ? (word | ~mask) : word;
|
||||
}
|
||||
|
||||
inline uint64_t nan_box(uint32_t word) {
|
||||
return word | 0xFFFFFFFF00000000;
|
||||
inline uintf_t nan_box(uint32_t word) {
|
||||
uintf_t mask = uintf_t(0xffffffff00000000);
|
||||
return word | mask;
|
||||
}
|
|
@ -300,10 +300,12 @@ uint64_t rv_fle_d(uint64_t a, uint64_t b, uint32_t* fflags) {
|
|||
|
||||
uint32_t rv_feq_s(uint64_t a, uint64_t b, uint32_t* fflags) {
|
||||
|
||||
#if FLEN == 64
|
||||
// Either a or b isn't NaN boxed
|
||||
if ((a >> 32 != 0xffffffff) || (b >> 32 != 0xffffffff)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto r = f32_eq(to_float32_t(a), to_float32_t(b));
|
||||
if (fflags) { *fflags = get_fflags(); }
|
||||
|
@ -436,6 +438,7 @@ uint64_t rv_fclss_d(uint64_t a) {
|
|||
|
||||
uint32_t rv_fsgnj_s(uint64_t a, uint64_t b) {
|
||||
|
||||
#if FLEN == 64
|
||||
// Both a and b aren't NaN boxed
|
||||
if ((a >> 32 != 0xffffffff) && (b >> 32 != 0xffffffff)) {
|
||||
return 0x7fc00000;
|
||||
|
@ -447,6 +450,7 @@ uint32_t rv_fsgnj_s(uint64_t a, uint64_t b) {
|
|||
// b is NaN boxed but a isn't
|
||||
if(a >> 32 != 0xffffffff)
|
||||
return 0xffc00000;
|
||||
#endif
|
||||
|
||||
int sign = b & F32_SIGN;
|
||||
int r = sign | (a & ~F32_SIGN);
|
||||
|
@ -464,6 +468,7 @@ uint64_t rv_fsgnj_d(uint64_t a, uint64_t b) {
|
|||
|
||||
uint32_t rv_fsgnjn_s(uint64_t a, uint64_t b) {
|
||||
|
||||
#if FLEN == 64
|
||||
// Both a and b aren't NaN boxed
|
||||
if ((a >> 32 != 0xffffffff) && (b >> 32 != 0xffffffff)) {
|
||||
return 0x7fc00000;
|
||||
|
@ -475,6 +480,7 @@ uint32_t rv_fsgnjn_s(uint64_t a, uint64_t b) {
|
|||
// b is NaN boxed but a isn't
|
||||
if(a >> 32 != 0xffffffff)
|
||||
return 0xffc00000;
|
||||
#endif
|
||||
|
||||
int sign = ~b & F32_SIGN;
|
||||
int r = sign | (a & ~F32_SIGN);
|
||||
|
@ -492,6 +498,7 @@ uint64_t rv_fsgnjn_d(uint64_t a, uint64_t b) {
|
|||
|
||||
uint32_t rv_fsgnjx_s(uint64_t a, uint64_t b) {
|
||||
|
||||
#if FLEN == 64
|
||||
// Both a and b aren't NaN boxed
|
||||
if ((a >> 32 != 0xffffffff) && (b >> 32 != 0xffffffff)) {
|
||||
return 0x7fc00000;
|
||||
|
@ -503,7 +510,8 @@ uint32_t rv_fsgnjx_s(uint64_t a, uint64_t b) {
|
|||
// b is NaN boxed but a isn't
|
||||
if(a >> 32 != 0xffffffff)
|
||||
return 0xffc00000;
|
||||
|
||||
#endif
|
||||
|
||||
int sign1 = a & F32_SIGN;
|
||||
int sign2 = b & F32_SIGN;
|
||||
int r = (sign1 ^ sign2) | (a & ~F32_SIGN);
|
||||
|
|
35
sim/common/xlen.h
Normal file
35
sim/common/xlen.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef XLEN
|
||||
#define XLEN 32
|
||||
#endif
|
||||
|
||||
#ifndef FLEN
|
||||
#define FLEN 32
|
||||
#endif
|
||||
|
||||
#if XLEN == 32
|
||||
#define uintx_t uint32_t
|
||||
#define intx_t int32_t
|
||||
#define intm_t int64_t
|
||||
#define uintm_t uint64_t
|
||||
#elif XLEN == 64
|
||||
#define uintx_t uint64_t
|
||||
#define intx_t int64_t
|
||||
#define intm_t __int128_t
|
||||
#define uintm_t __uint128_t
|
||||
#else
|
||||
#error unsupported XLEN
|
||||
#endif
|
||||
|
||||
#if FLEN >= XLEN
|
||||
#if FLEN == 32
|
||||
#define uintf_t uint32_t
|
||||
#elif FLEN == 64
|
||||
#define uintf_t uint64_t
|
||||
#else
|
||||
#error unsupported FLEN
|
||||
#endif
|
||||
#else
|
||||
#error unsupported FLEN
|
||||
#endif
|
|
@ -34,8 +34,11 @@ endif
|
|||
# XLEN parameterization
|
||||
ifdef XLEN
|
||||
CXXFLAGS += -DXLEN=$(XLEN)
|
||||
else
|
||||
CXXFLAGS += -DXLEN=32
|
||||
endif
|
||||
|
||||
# FLEN parameterization
|
||||
ifdef FLEN
|
||||
CXXFLAGS += -DFLEN=$(FLEN)
|
||||
endif
|
||||
|
||||
PROJECT = simx
|
||||
|
|
|
@ -487,11 +487,13 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
break;
|
||||
case Opcode::I_INST:
|
||||
if (func3 == 0x1 || func3 == 0x5) {
|
||||
// int6
|
||||
instr->setImm(sext64(((func7 & 0x1) << 5) | rs2, 6));
|
||||
// int5 (XLEN = 32) / int6 (XLEN = 64)
|
||||
int shamt_width = log2up(XLEN);
|
||||
int shamt = ((func7 & 0x1) << 5) | rs2;
|
||||
instr->setImm(sext(shamt, shamt_width));
|
||||
} else {
|
||||
// int12
|
||||
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||
instr->setImm(sext(code >> shift_rs2_, 12));
|
||||
}
|
||||
break;
|
||||
case Opcode::I_INST_64:
|
||||
|
@ -505,7 +507,7 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
break;
|
||||
default:
|
||||
// int12
|
||||
instr->setImm(sext64(code >> shift_rs2_, 12));
|
||||
instr->setImm(sext(code >> shift_rs2_, 12));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
@ -518,7 +520,7 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
}
|
||||
instr->setFunc3(func3);
|
||||
XWord imm = (func7 << reg_s_) | rd;
|
||||
instr->setImm(sext64(imm, 12));
|
||||
instr->setImm(sext(imm, 12));
|
||||
} break;
|
||||
|
||||
case InstType::B_TYPE: {
|
||||
|
@ -530,12 +532,12 @@ std::shared_ptr<Instr> Decoder::decode(Word code) const {
|
|||
Word bit_10_5 = func7 & 0x3f;
|
||||
Word bit_12 = func7 >> 6;
|
||||
XWord imm = (bits_4_1 << 1) | (bit_10_5 << 5) | (bit_11 << 11) | (bit_12 << 12);
|
||||
instr->setImm(sext64(imm, 13));
|
||||
instr->setImm(sext(imm, 13));
|
||||
} break;
|
||||
|
||||
case InstType::U_TYPE:
|
||||
instr->setDestReg(rd);
|
||||
instr->setImm(sext64(code >> shift_func3_, 20));
|
||||
instr->setImm(sext(code >> shift_func3_, 20));
|
||||
break;
|
||||
|
||||
case InstType::J_TYPE: {
|
||||
|
@ -545,7 +547,7 @@ 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;
|
||||
XWord imm = 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
|
||||
XWord imm = (XWord) 0 | (bits_10_1 << 1) | (bit_11 << 11) | (bits_19_12 << 12) | (bit_20 << 20);
|
||||
if (bit_20) {
|
||||
imm |= ~j_imm_mask_;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <assert.h>
|
||||
#include <util.h>
|
||||
#include <rvfloats.h>
|
||||
#include <xlen.h>
|
||||
#include "warp.h"
|
||||
#include "instr.h"
|
||||
#include "core.h"
|
||||
|
@ -69,8 +70,8 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
|
||||
int num_threads = core_->arch().num_threads();
|
||||
|
||||
std::vector<XWord[3]> rsdata(num_threads);
|
||||
std::vector<XWord> rddata(num_threads);
|
||||
std::vector<FWord[3]> rsdata(num_threads);
|
||||
std::vector<FWord> rddata(num_threads);
|
||||
|
||||
int num_rsrcs = instr.getNRSrc();
|
||||
if (num_rsrcs) {
|
||||
|
@ -117,23 +118,25 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
switch (opcode) {
|
||||
case NOP:
|
||||
break;
|
||||
// RV32I: LUI
|
||||
case LUI_INST:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::ARITH;
|
||||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
rddata[t] = (immsrc << 12) & 0xfffffffffffff000;
|
||||
rddata[t] = immsrc << 12;
|
||||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
// RV32I: AUIPC
|
||||
case AUIPC_INST:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::ARITH;
|
||||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
rddata[t] = ((immsrc << 12) & 0xfffffffffffff000) + PC_;
|
||||
rddata[t] = (immsrc << 12) + PC_;
|
||||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
|
@ -154,32 +157,33 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
break;
|
||||
case 1: {
|
||||
// RV32M: MULH
|
||||
__int128_t first = sext128((__int128_t)rsdata[t][0], 64);
|
||||
__int128_t second = sext128((__int128_t)rsdata[t][1], 64);
|
||||
rddata[t] = ((first * second) >> 64) & 0xFFFFFFFFFFFFFFFF;
|
||||
intm_t first = sext_mul((intm_t)rsdata[t][0], XLEN);
|
||||
intm_t second = sext_mul((intm_t)rsdata[t][1], XLEN);
|
||||
rddata[t] = ((first * second) >> XLEN) & 0xFFFFFFFFFFFFFFFF;
|
||||
trace->alu.type = AluType::IMUL;
|
||||
} break;
|
||||
case 2: {
|
||||
// RV32M: MULHSU
|
||||
__int128_t first = sext128((__int128_t)rsdata[t][0], 64);
|
||||
__int128_t second = (__int128_t)rsdata[t][1];
|
||||
rddata[t] = ((first * second) >> 64) & 0xFFFFFFFFFFFFFFFF;
|
||||
intm_t first = sext_mul((intm_t)rsdata[t][0], XLEN);
|
||||
intm_t second = (intm_t)rsdata[t][1];
|
||||
rddata[t] = ((first * second) >> XLEN) & 0xFFFFFFFFFFFFFFFF;
|
||||
trace->alu.type = AluType::IMUL;
|
||||
} break;
|
||||
case 3: {
|
||||
// RV32M: MULHU
|
||||
__uint128_t first = (__int128_t)rsdata[t][0];
|
||||
__uint128_t second = (__int128_t)rsdata[t][1];
|
||||
rddata[t] = ((first * second) >> 64) & 0xFFFFFFFFFFFFFFFF;
|
||||
intm_t first = (intm_t)rsdata[t][0];
|
||||
intm_t second = (intm_t)rsdata[t][1];
|
||||
rddata[t] = ((first * second) >> XLEN) & 0xFFFFFFFFFFFFFFFF;
|
||||
trace->alu.type = AluType::IMUL;
|
||||
} break;
|
||||
case 4: {
|
||||
// RV32M: DIV
|
||||
XWordI dividen = rsdata[t][0];
|
||||
XWordI divisor = rsdata[t][1];
|
||||
XWordI divisor = rsdata[t][1];
|
||||
XWordI largest_negative = XWordI(1) << (XLEN-1);
|
||||
if (divisor == 0) {
|
||||
rddata[t] = -1;
|
||||
} else if (dividen == XWordI(0x8000000000000000) && divisor == XWordI(0xffffffffffffffff)) {
|
||||
} else if (dividen == largest_negative && divisor == -1) {
|
||||
rddata[t] = dividen;
|
||||
} else {
|
||||
rddata[t] = dividen / divisor;
|
||||
|
@ -201,9 +205,10 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
// RV32M: REM
|
||||
XWordI dividen = rsdata[t][0];
|
||||
XWordI divisor = rsdata[t][1];
|
||||
XWordI largest_negative = XWordI(1) << (XLEN-1);
|
||||
if (rsdata[t][1] == 0) {
|
||||
rddata[t] = dividen;
|
||||
} else if (dividen == XWordI(0x8000000000000000) && divisor == XWordI(0xffffffffffffffff)) {
|
||||
} else if (dividen == largest_negative && divisor == -1) {
|
||||
rddata[t] = 0;
|
||||
} else {
|
||||
rddata[t] = dividen % divisor;
|
||||
|
@ -236,15 +241,15 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
break;
|
||||
case 1:
|
||||
// RV32I: SHL
|
||||
// RV32I: SLL
|
||||
rddata[t] = rsdata[t][0] << rsdata[t][1];
|
||||
break;
|
||||
case 2:
|
||||
// RV32I: LT
|
||||
// RV32I: SLT
|
||||
rddata[t] = (XWordI(rsdata[t][0]) < XWordI(rsdata[t][1]));
|
||||
break;
|
||||
case 3:
|
||||
// RV32I: LTU
|
||||
// RV32I: SLTU
|
||||
rddata[t] = (XWord(rsdata[t][0]) < XWord(rsdata[t][1]));
|
||||
break;
|
||||
case 4:
|
||||
|
@ -256,7 +261,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
// RV32I: SRA
|
||||
rddata[t] = XWordI(rsdata[t][0]) >> XWordI(rsdata[t][1]);
|
||||
} else {
|
||||
// RV32I: SHR
|
||||
// RV32I: SRL
|
||||
rddata[t] = XWord(rsdata[t][0]) >> XWord(rsdata[t][1]);
|
||||
}
|
||||
break;
|
||||
|
@ -288,7 +293,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
rddata[t] = rsdata[t][0] + immsrc;
|
||||
break;
|
||||
case 1:
|
||||
// RV32I: SLLI
|
||||
// RV64I: SLLI
|
||||
rddata[t] = rsdata[t][0] << immsrc;
|
||||
break;
|
||||
case 2:
|
||||
|
@ -305,11 +310,11 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
break;
|
||||
case 5:
|
||||
if (func7) {
|
||||
// RV32I: SRAI
|
||||
// RV64I: SRAI
|
||||
XWord result = XWordI(rsdata[t][0]) >> immsrc;
|
||||
rddata[t] = result;
|
||||
} else {
|
||||
// RV32I: SRLI
|
||||
// RV64I: SRLI
|
||||
XWord result = rsdata[t][0] >> immsrc;
|
||||
rddata[t] = result;
|
||||
}
|
||||
|
@ -339,6 +344,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
case 0:
|
||||
// RV64M: MULW
|
||||
rddata[t] = sext64((WordI)rsdata[t][0] * (WordI)rsdata[t][1], 32);
|
||||
trace->alu.type = AluType::IMUL;
|
||||
break;
|
||||
case 4: {
|
||||
// RV64M: DIVW
|
||||
|
@ -351,6 +357,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
trace->alu.type = AluType::IDIV;
|
||||
} break;
|
||||
case 5: {
|
||||
// RV64M: DIVUW
|
||||
|
@ -361,6 +368,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
} else {
|
||||
rddata[t] = sext64(dividen / divisor, 32);
|
||||
}
|
||||
trace->alu.type = AluType::IDIV;
|
||||
} break;
|
||||
case 6: {
|
||||
// RV64M: REMW
|
||||
|
@ -373,6 +381,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
trace->alu.type = AluType::IDIV;
|
||||
} break;
|
||||
case 7: {
|
||||
// RV64M: REMUW
|
||||
|
@ -383,6 +392,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
} else {
|
||||
rddata[t] = sext64(dividen % divisor, 32);
|
||||
}
|
||||
trace->alu.type = AluType::IDIV;
|
||||
} break;
|
||||
default:
|
||||
std::abort();
|
||||
|
@ -505,6 +515,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
trace->fetch_stall = true;
|
||||
break;
|
||||
// RV32I: JAL
|
||||
case JAL_INST:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::BRANCH;
|
||||
|
@ -518,6 +529,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
rd_write = true;
|
||||
break;
|
||||
// RV32I: JALR
|
||||
case JALR_INST:
|
||||
trace->exe_type = ExeType::ALU;
|
||||
trace->alu.type = AluType::BRANCH;
|
||||
|
@ -543,23 +555,23 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
for (int t = 0; t < num_threads; ++t) {
|
||||
if (!tmask_.test(t))
|
||||
continue;
|
||||
XWord mem_addr = ((rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFFC); // double word aligned
|
||||
XWord shift_by = ((rsdata[t][0] + immsrc) & 0x00000003) * 8;
|
||||
XWord data_read = core_->dcache_read(mem_addr, 8);
|
||||
trace->mem_addrs.at(t).push_back({mem_addr, 8});
|
||||
XWord mem_addr = (rsdata[t][0] + immsrc) & 0xFFFFFFFFFFFFFFFC;
|
||||
XWord shift_by = ((rsdata[t][0] + immsrc) & 0x3) * 8;
|
||||
XWord data_read = (opcode == FL) ? core_->dcache_read(mem_addr, sizeof(FWord)) : core_->dcache_read(mem_addr, sizeof(XWord));
|
||||
trace->mem_addrs.at(t).push_back({mem_addr, sizeof(XWord)});
|
||||
DP(4, "LOAD MEM: ADDRESS=0x" << std::hex << mem_addr << ", DATA=0x" << data_read);
|
||||
switch (func3) {
|
||||
case 0:
|
||||
// RV32I: LBI
|
||||
rddata[t] = sext64((data_read >> shift_by) & 0xFF, 8);
|
||||
// RV32I: LB
|
||||
rddata[t] = sext((data_read >> shift_by) & 0xFF, 8);
|
||||
break;
|
||||
case 1:
|
||||
// RV32I: LHI
|
||||
rddata[t] = sext64((data_read >> shift_by) & 0xFFFF, 16);
|
||||
// RV32I: LH
|
||||
rddata[t] = sext((data_read >> shift_by) & 0xFFFF, 16);
|
||||
break;
|
||||
case 2:
|
||||
// RV32I: LW / RV32F: FLW
|
||||
rddata[t] = (opcode == FL) ? nan_box((data_read >> shift_by) & 0xFFFFFFFF) : sext64((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
||||
rddata[t] = (opcode == FL) ? nan_box((data_read >> shift_by) & 0xFFFFFFFF) : sext((data_read >> shift_by) & 0xFFFFFFFF, 32);
|
||||
break;
|
||||
case 3:
|
||||
// RV64I: LD / RV32D: FLD
|
||||
|
@ -730,6 +742,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
// RV32I: FENCE
|
||||
case FENCE:
|
||||
trace->exe_type = ExeType::LSU;
|
||||
trace->lsu.type = LsuType::FENCE;
|
||||
|
@ -895,11 +908,11 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
case 0x61:
|
||||
switch(rsrc1) {
|
||||
case 0:
|
||||
// RV32F: FCVT.W.D
|
||||
// RV32D: FCVT.W.D
|
||||
rddata[t] = sext64(rv_ftoi_d(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 1:
|
||||
// RV32F: FCVT.WU.D
|
||||
// RV32D: FCVT.WU.D
|
||||
rddata[t] = sext64(rv_ftou_d(rsdata[t][0], frm, &fflags), 32);
|
||||
break;
|
||||
case 2:
|
||||
|
@ -1003,7 +1016,7 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
rddata[t] = rv_itof_d(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
case 1:
|
||||
// RV32F: FCVT.D.WU
|
||||
// RV32D: FCVT.D.WU
|
||||
rddata[t] = rv_utof_d(rsdata[t][0], frm, &fflags);
|
||||
break;
|
||||
case 2:
|
||||
|
@ -2126,8 +2139,8 @@ void Warp::execute(const Instr &instr, pipeline_trace_t *trace) {
|
|||
DPN(2, "-");
|
||||
continue;
|
||||
}
|
||||
ireg_file_.at(t)[rdest] = rddata[t];
|
||||
DPN(2, "0x" << std::hex << rddata[t]);
|
||||
ireg_file_.at(t)[rdest] = XWord(rddata[t]);
|
||||
DPN(2, "0x" << std::hex << XWord(rddata[t]));
|
||||
}
|
||||
DPN(2, "}" << std::endl);
|
||||
trace->used_iregs[rdest] = 1;
|
||||
|
|
|
@ -7,24 +7,16 @@
|
|||
#include <util.h>
|
||||
#include <VX_config.h>
|
||||
#include <simobject.h>
|
||||
|
||||
#if XLEN == 32
|
||||
#define uintx_t uint32_t
|
||||
#define intx_t int32_t
|
||||
#elif XLEN == 64
|
||||
#define uintx_t uint64_t
|
||||
#define intx_t int64_t
|
||||
#else
|
||||
#error unsupported XLEN
|
||||
#endif
|
||||
#include <xlen.h>
|
||||
|
||||
namespace vortex {
|
||||
|
||||
typedef uint8_t Byte;
|
||||
typedef uint32_t Word;
|
||||
typedef int32_t WordI;
|
||||
typedef uintx_t XWord;
|
||||
typedef uintx_t XWord;
|
||||
typedef intx_t XWordI;
|
||||
typedef uintf_t FWord;
|
||||
|
||||
typedef uintx_t Addr;
|
||||
typedef uint32_t Size;
|
||||
|
|
|
@ -14,7 +14,7 @@ Warp::Warp(Core *core, Word id)
|
|||
: id_(id)
|
||||
, core_(core)
|
||||
, ireg_file_(core->arch().num_threads(), std::vector<XWord>(core->arch().num_regs()))
|
||||
, freg_file_(core->arch().num_threads(), std::vector<XWord>(core->arch().num_regs()))
|
||||
, freg_file_(core->arch().num_threads(), std::vector<FWord>(core->arch().num_regs()))
|
||||
, vreg_file_(core->arch().num_threads(), std::vector<Byte>(core->arch().vsize()))
|
||||
{
|
||||
this->clear();
|
||||
|
@ -70,12 +70,14 @@ void Warp::eval(pipeline_trace_t *trace) {
|
|||
DP(4, "Register state:");
|
||||
for (int i = 0; i < core_->arch().num_regs(); ++i) {
|
||||
DPN(4, " %r" << std::setfill('0') << std::setw(2) << std::dec << i << ':');
|
||||
// Integer register file
|
||||
for (int j = 0; j < core_->arch().num_threads(); ++j) {
|
||||
DPN(4, ' ' << std::setfill('0') << std::setw(16) << std::hex << ireg_file_.at(j).at(i) << std::setfill(' ') << ' ');
|
||||
DPN(4, ' ' << std::setfill('0') << std::setw(XLEN/4) << std::hex << ireg_file_.at(j).at(i) << std::setfill(' ') << ' ');
|
||||
}
|
||||
// delete later: printing floating point reg file
|
||||
DPN(4, '|');
|
||||
// Floating point register file
|
||||
for (int j = 0; j < core_->arch().num_threads(); ++j) {
|
||||
DPN(4, ' ' << std::setfill('0') << std::setw(16) << std::hex << freg_file_.at(j).at(i) << std::setfill(' ') << ' ');
|
||||
DPN(4, ' ' << std::setfill('0') << std::setw(FLEN/4) << std::hex << freg_file_.at(j).at(i) << std::setfill(' ') << ' ');
|
||||
}
|
||||
DPN(4, std::endl);
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ private:
|
|||
ThreadMask tmask_;
|
||||
|
||||
std::vector<std::vector<XWord>> ireg_file_;
|
||||
std::vector<std::vector<XWord>> freg_file_;
|
||||
std::vector<std::vector<FWord>> freg_file_;
|
||||
std::vector<std::vector<Byte>> vreg_file_;
|
||||
std::stack<DomStackEntry> dom_stack_;
|
||||
|
||||
|
|
|
@ -2,16 +2,11 @@ ALL_TESTS := $(wildcard *.hex)
|
|||
ALL_TESTS_32 := $(wildcard rv32*.hex)
|
||||
ALL_TESTS_64 := $(wildcard rv64*.hex)
|
||||
|
||||
D_TESTS := $(wildcard *ud-p-*.hex)
|
||||
|
||||
D_TESTS_32 := $(wildcard rv32ud-p-*.hex)
|
||||
V_TESTS := $(wildcard *-v-*.hex)
|
||||
I_TESTS := $(wildcard rv64ui-p-*.hex)
|
||||
M_TESTS := $(wildcard rv64um-p-*.hex)
|
||||
F_TESTS := $(wildcard rv64uf-p-*.hex)
|
||||
D_TESTS_64 := $(wildcard rv64ud-p-*.hex)
|
||||
|
||||
|
||||
|
||||
EXCLUDED_TESTS_32 := $(V_TESTS) $(D_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
|
||||
EXCLUDED_TESTS_32 := $(V_TESTS) $(D_TESTS_32) 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
|
||||
EXCLUDED_TESTS_64 := rv64ud-p-ldst.hex rv64ud-p-recoding.hex
|
||||
|
||||
TESTS_32 := $(filter-out $(EXCLUDED_TESTS_32), $(ALL_TESTS_32))
|
||||
|
@ -19,25 +14,16 @@ TESTS_64 := $(filter-out $(EXCLUDED_TESTS_64), $(ALL_TESTS_64))
|
|||
|
||||
all:
|
||||
|
||||
run-simx-32:
|
||||
$(foreach test, $(TESTS_32), ../../../sim/simx/simx -r -a rv32i -c 1 -i $(test) || exit;)
|
||||
run-simx-32imf:
|
||||
$(foreach test, $(TESTS_32), ../../../sim/simx/simx -r -a rv32imf -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64:
|
||||
run-simx-32imfd:
|
||||
$(foreach test, $(TESTS_32) $(D_TESTS_32), ../../../sim/simx/simx -r -a rv32imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64imfd:
|
||||
$(foreach test, $(TESTS_64), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64-i:
|
||||
$(foreach test, $(I_TESTS), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64-m:
|
||||
$(foreach test, $(M_TESTS), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64-f:
|
||||
$(foreach test, $(F_TESTS), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-simx-64-d:
|
||||
$(foreach test, $(D_TESTS_64), ../../../sim/simx/simx -r -a rv64imfd -c 1 -i $(test) || exit;)
|
||||
|
||||
run-rtlsim:
|
||||
$(foreach test, $(TESTS), ../../../sim/rtlsim/rtlsim -r $(test) || exit;)
|
||||
$(foreach test, $(TESTS_32), ../../../sim/rtlsim/rtlsim -r $(test) || exit;)
|
||||
|
||||
clean:
|
Loading…
Add table
Add a link
Reference in a new issue