Added FLEN parameterization for RV32/64 F and D instructions

This commit is contained in:
Santosh Srivatsan
2022-01-24 15:42:15 -05:00
parent ad92c09f5b
commit 7aa93a735d
10 changed files with 140 additions and 96 deletions

View File

@@ -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

View File

@@ -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_;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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_;