adding floating extension to SimX

This commit is contained in:
Blaise Tine 2021-02-24 14:25:04 -08:00
parent 34ce0b8e89
commit 4fe345f269
11 changed files with 939 additions and 286 deletions

View file

@ -13,7 +13,7 @@ RTL_DIR = ../hw/rtl
PROJECT = simX
SRCS = util.cpp args.cpp mem.cpp core.cpp warp.cpp instr.cpp decode.cpp execute.cpp simX.cpp
SRCS = util.cpp args.cpp mem.cpp core.cpp warp.cpp instr.cpp decode.cpp execute.cpp main.cpp
# Debugigng
ifdef DEBUG
@ -27,6 +27,9 @@ all: $(PROJECT)
$(PROJECT): $(SRCS)
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
run: $(PROJECT)
./$(PROJECT)
.depend: $(SRCS)
$(CXX) $(CXXFLAGS) -MM $^ > .depend;

View file

@ -117,11 +117,6 @@ Core::Core(const ArchDef &arch, Decoder &decoder, MemoryUnit &mem, Word id)
warps_[0].setSpawned(true);
}
bool Core::interrupt(Word r0) {
warps_[0].interrupt(r0);
return false;
}
Core::~Core() {
//--
}

View file

@ -21,7 +21,6 @@ public:
Core(const ArchDef &arch, Decoder &decoder, MemoryUnit &mem, Word id = 0);
~Core();
bool interrupt(Word r0);
bool running() const;
void getCacheDelays(trace_inst_t *);

View file

@ -38,7 +38,14 @@ static const std::unordered_map<int, struct InstTableEntry_t> sc_instTable = {
{Opcode::GPGPU, {"gpgpu" , false, InstType::R_TYPE}},
{Opcode::VSET_ARITH, {"vsetvl", false, InstType::V_TYPE}},
{Opcode::VL, {"vl" , false, InstType::V_TYPE}},
{Opcode::VS, {"vs" , false, InstType::V_TYPE}}
{Opcode::VS, {"vs" , false, InstType::V_TYPE}},
{Opcode::FL, {"fl" , false, InstType::I_TYPE }},
{Opcode::FS, {"fs" , false, InstType::S_TYPE }},
{Opcode::FCI, {"fci" , false, InstType::R_TYPE }},
{Opcode::FMADD, {"fma" , false, InstType::R4_TYPE }},
{Opcode::FMSUB, {"fms" , false, InstType::R4_TYPE }},
{Opcode::FMNMADD, {"fmnma" , false, InstType::R4_TYPE }},
{Opcode::FMNMSUB, {"fmnms" , false, InstType::R4_TYPE }}
};
std::ostream &vortex::operator<<(std::ostream &os, Instr &instr) {
@ -50,6 +57,7 @@ Decoder::Decoder(const ArchDef &arch) {
inst_s_ = arch.getWordSize() * 8;
opcode_s_ = 7;
reg_s_ = 5;
func2_s_ = 2;
func3_s_ = 3;
mop_s_ = 3;
vmask_s_ = 1;
@ -60,6 +68,8 @@ Decoder::Decoder(const ArchDef &arch) {
shift_rs1_ = opcode_s_ + reg_s_ + func3_s_;
shift_rs2_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_;
shift_func7_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_func2_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_rs3_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + func2_s_;
shift_j_u_immed_ = opcode_s_ + reg_s_;
shift_s_b_immed_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_;
shift_i_immed_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_;
@ -71,6 +81,7 @@ Decoder::Decoder(const ArchDef &arch) {
shift_vset_ = opcode_s_ + reg_s_ + func3_s_ + reg_s_ + reg_s_ + 6;
reg_mask_ = 0x1f;
func2_mask_ = 0x2;
func3_mask_ = 0x7;
func6_mask_ = 0x3f;
func7_mask_ = 0x7f;
@ -96,13 +107,21 @@ std::shared_ptr<Instr> Decoder::decode(const std::vector<Byte> &v, Size &idx, tr
Word imeed, dest_bits, imm_bits, bit_11, bits_4_1, bit_10_5,
bit_12, bits_19_12, bits_10_1, bit_20, unordered, func3;
InstType curInstType = sc_instTable.at(op).iType; // get current inst type
if (op == Opcode::FL || op == Opcode::FS) { // need to find out whether it is vector or floating point inst
Word width_bits = (code >> shift_func3_) & func3_mask_;
if ((width_bits == 0x1) || (width_bits == 0x2)
|| (width_bits == 0x3) || (width_bits == 0x4)) {
curInstType = (op == Opcode::FL)? InstType::I_TYPE : InstType::S_TYPE;
}
}
// std::cout << "op: " << std::hex << op << " what " << sc_instTable[op].iType << "\n";
switch (sc_instTable.at(op).iType) {
switch (curInstType) {
case InstType::N_TYPE:
break;
case InstType::R_TYPE:
instr->setPred((code >> shift_rs1_) & reg_mask_);
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
@ -122,7 +141,7 @@ std::shared_ptr<Instr> Decoder::decode(const std::vector<Byte> &v, Size &idx, tr
func3 = (code >> shift_func3_) & func3_mask_;
instr->setFunc3(func3);
if ((func3 == 5) && (op != L_INST)) {
if ((func3 == 5) && (op != L_INST) && (op != FL)) {
// std::cout << "func7: " << func7 << "\n";
instr->setSrcImm(signExt(((code >> shift_rs2_) & reg_mask_), 5, reg_mask_));
} else {
@ -282,6 +301,20 @@ std::shared_ptr<Instr> Decoder::decode(const std::vector<Byte> &v, Size &idx, tr
std::abort();
}
break;
case R4_TYPE:
// RT: add R4_TYPE decoder
instr->setDestReg((code >> shift_rd_) & reg_mask_);
instr->setSrcReg((code >> shift_rs1_) & reg_mask_);
instr->setSrcReg((code >> shift_rs2_) & reg_mask_);
instr->setSrcReg((code >> shift_rs3_) & reg_mask_);
instr->setFunc3((code >> shift_func3_) & func3_mask_);
trace_inst->valid_inst = true;
trace_inst->rs1 = ((code >> shift_rs1_) & reg_mask_);
trace_inst->rs2 = ((code >> shift_rs2_) & reg_mask_);
trace_inst->rs3 = ((code >> shift_rs3_) & reg_mask_);
trace_inst->rd = ((code >> shift_rd_) & reg_mask_);
break;
default:
std::cout << "Unrecognized argument class in word decoder.\n";
std::abort();

View file

@ -21,11 +21,14 @@ private:
Word inst_s_;
Word opcode_s_;
Word reg_s_;
Word func2_s_;
Word func3_s_;
Word shift_opcode_;
Word shift_rd_;
Word shift_rs1_;
Word shift_rs2_;
Word shift_rs3_;
Word shift_func2_;
Word shift_func3_;
Word shift_func7_;
Word shift_j_u_immed_;
@ -33,6 +36,7 @@ private:
Word shift_i_immed_;
Word reg_mask_;
Word func2_mask_;
Word func3_mask_;
Word func6_mask_;
Word func7_mask_;

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,14 @@ enum Opcode {
VSET_ARITH= 0x57,
VL = 0x7,
VS = 0x27,
// F-Extension
FL = 0x7,
FS = 0x27,
FCI = 0x53,
FMADD = 0x43,
FMSUB = 0x47,
FMNMSUB = 0x4b,
FMNMADD = 0x4f,
};
enum InstType {
@ -35,25 +43,28 @@ enum InstType {
B_TYPE,
U_TYPE,
J_TYPE,
V_TYPE
V_TYPE,
R4_TYPE
};
class Instr {
public:
Instr()
: predicated_(false)
: opcode_(Opcode::NOP)
, nRsrc_(0)
, nPsrc_(0)
, hasImmSrc_(false)
, hasRDest_(false)
, hasPDest_(false)
, func2_(0)
, func3_(0)
, func7_(0)
{}
friend std::ostream &operator<<(std::ostream &, Instr &);
/* Setters used to "craft" the instruction. */
void setOpcode(Opcode opcode) { opcode_ = opcode; }
void setPred(RegNum pReg) { predicated_ = true; pred_ = pReg; }
void setDestReg(RegNum destReg) { hasRDest_ = true; rdest_ = destReg; }
void setSrcReg(RegNum srcReg) { rsrc_[nRsrc_++] = srcReg; }
void setFunc3(Word func3) { func3_ = func3; }
@ -69,7 +80,6 @@ public:
void setVsew(Word sew);
void setVediv(Word ediv);
void setFunc6(Word func6) { func6_ = func6; }
void setPrivileged(bool privileged) { privileged_ = privileged; }
/* Getters used by encoders. */
Opcode getOpcode() const { return opcode_; }
@ -80,10 +90,6 @@ public:
RegNum getRSrc(RegNum i) const { return rsrc_[i]; }
bool hasRDest() const { return hasRDest_; }
RegNum getRDest() const { return rdest_; }
bool hasPDest() const { return hasPDest_; }
RegNum getPDest() const { return pdest_; }
bool hasPred() const { return predicated_; }
RegNum getPred() const { return pred_; }
bool hasImm() const { return hasImmSrc_; }
Word getImm() const { return immsrc_; }
bool getVsetImm() const { return vsetImm_; }
@ -95,7 +101,6 @@ public:
Word getVlmul() const { return vlmul_; }
Word getVsew() const { return vsew_; }
Word getVediv() const { return vediv_; }
bool getPrivileged() const { return privileged_; }
private:
@ -104,20 +109,16 @@ private:
};
Opcode opcode_;
bool predicated_;
RegNum pred_;
int nRsrc_;
int nPsrc_;
RegNum rsrc_[MAX_REG_SOURCES];
bool hasImmSrc_;
bool hasRDest_;
Word immsrc_;
Word func2_;
Word func3_;
Word func7_;
bool hasRDest_;
bool hasPDest_;
RegNum rsrc_[MAX_REG_SOURCES];
RegNum rdest_;
RegNum pdest_;
bool privileged_;
//Vector
bool vsetImm_;

78
simX/main.cpp Normal file
View file

@ -0,0 +1,78 @@
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <sys/stat.h>
#include "debug.h"
#include "types.h"
#include "core.h"
#include "args.h"
using namespace vortex;
int main(int argc, char **argv) {
std::string archString("rv32i");
int num_cores(1);
int num_warps(NUM_WARPS);
int num_threads(NUM_THREADS);
std::string imgFileName;
bool showHelp(false);
bool showStats(false);
/* Read the command line arguments. */
CommandLineArgFlag fh("-h", "--help", "", showHelp);
CommandLineArgSetter<std::string> fa("-a", "--arch", "", archString);
CommandLineArgSetter<std::string> fi("-i", "--image", "", imgFileName);
CommandLineArgSetter<int> fc("-c", "--cores", "", num_cores);
CommandLineArgSetter<int> fw("-w", "--warps", "", num_warps);
CommandLineArgSetter<int> ft("-t", "--threads", "", num_threads);
CommandLineArgFlag fs("-s", "--stats", "", showStats);
CommandLineArg::readArgs(argc - 1, argv + 1);
if (showHelp || imgFileName.empty()) {
std::cout << "Vortex emulator command line arguments:\n"
" -i, --image <filename> Program RAM image\n"
" -c, --cores <num> Number of cores\n"
" -w, --warps <num> Number of warps\n"
" -t, --threads <num> Number of threads\n"
" -a, --arch <arch string> Architecture string\n"
" -s, --stats Print stats on exit.\n";
return 0;
}
ArchDef arch(archString, num_cores, num_warps, num_threads);
Decoder decoder(arch);
MemoryUnit mu(4096, arch.getWordSize(), true);
RAM old_ram;
old_ram.loadHexImpl(imgFileName.c_str());
mu.attach(old_ram, 0);
struct stat hello;
fstat(0, &hello);
std::vector<std::shared_ptr<Core>> cores(num_cores);
for (int i = 0; i < num_cores; ++i) {
cores[i] = std::make_shared<Core>(arch, decoder, mu);
}
bool running;
do {
running = false;
for (int i = 0; i < num_cores; ++i) {
if (!cores[i]->running())
continue;
running = true;
cores[i]->step();
}
} while (running);
return 0;
}

View file

@ -14,6 +14,7 @@ namespace vortex {
// Encoder
int rs1;
int rs2;
int rs3;
int rd;
//Encoder

View file

@ -16,12 +16,8 @@ Warp::Warp(Core *core, Word id)
, shadowPc_(0)
, activeThreads_(0)
, shadowActiveThreads_(0)
, shadowReg_(core_->arch().getNumRegs())
, shadowIReg_(core_->arch().getNumRegs())
, VLEN_(1024)
, interruptEnable_(true)
, shadowInterruptEnable_(false)
, supervisorMode_(true)
, shadowSupervisorMode_(false)
, spawned_(false)
, steps_(0)
, insts_(0)
@ -31,9 +27,9 @@ Warp::Warp(Core *core, Word id)
/* Build the register file. */
Word regNum(0);
for (Word j = 0; j < core_->arch().getNumThreads(); ++j) {
regFile_.push_back(std::vector<Reg<Word>>(0));
iRegFile_.push_back(std::vector<Reg<Word>>(0));
for (Word i = 0; i < core_->arch().getNumRegs(); ++i) {
regFile_[j].push_back(Reg<Word>(id, regNum++));
iRegFile_[j].push_back(Reg<Word>(id, regNum++));
}
bool act = false;
@ -44,11 +40,11 @@ Warp::Warp(Core *core, Word id)
}
for (Word i = 0; i < (1 << 12); i++) {
csrs_.push_back(Reg<uint16_t>(id, regNum++));
csrs_.push_back(Reg<uint32_t>(id, regNum++));
}
/* Set initial register contents. */
regFile_[0][0] = (core_->arch().getNumThreads() << (core_->arch().getWordSize() * 8 / 2)) | id;
iRegFile_[0][0] = (core_->arch().getNumThreads() << (core_->arch().getWordSize() * 8 / 2)) | id;
}
void Warp::step(trace_inst_t *trace_inst) {
@ -73,7 +69,7 @@ void Warp::step(trace_inst_t *trace_inst) {
unsigned fetchSize = 4;
fetchBuffer.resize(fetchSize);
Word fetched = core_->mem().fetch(pc_ + fetchPos, supervisorMode_);
Word fetched = core_->mem().fetch(pc_ + fetchPos, 0);
writeWord(fetchBuffer, fetchPos, fetchSize, fetched);
decPos = 0;
@ -87,11 +83,11 @@ void Warp::step(trace_inst_t *trace_inst) {
// At Debug Level 3, print debug info after each instruction.
D(3, "Register state:");
for (unsigned i = 0; i < regFile_[0].size(); ++i) {
for (unsigned i = 0; i < iRegFile_[0].size(); ++i) {
D_RAW(" %r" << std::setfill('0') << std::setw(2) << std::dec << i << ':');
for (unsigned j = 0; j < (activeThreads_); ++j)
D_RAW(' ' << std::setfill('0') << std::setw(8) << std::hex << regFile_[j][i] << std::setfill(' ') << ' ');
D_RAW('(' << shadowReg_[i] << ')' << std::endl);
D_RAW(' ' << std::setfill('0') << std::setw(8) << std::hex << iRegFile_[j][i] << std::setfill(' ') << ' ');
D_RAW('(' << shadowIReg_[i] << ')' << std::endl);
}
DPH(3, "Thread mask:");
@ -100,31 +96,6 @@ void Warp::step(trace_inst_t *trace_inst) {
DPN(3, "\n");
}
bool Warp::interrupt(Word r0) {
if (!interruptEnable_)
return false;
shadowActiveThreads_ = activeThreads_;
shadowTmask_ = tmask_;
shadowInterruptEnable_ = interruptEnable_; /* For traps. */
shadowSupervisorMode_ = supervisorMode_;
for (Word i = 0; i < regFile_[0].size(); ++i)
shadowReg_[i] = regFile_[0][i];
for (Word i = 0; i < regFile_.size(); ++i)
tmask_[i] = 1;
shadowPc_ = pc_;
activeThreads_ = 1;
interruptEnable_ = false;
supervisorMode_ = true;
regFile_[0][0] = r0;
pc_ = core_->interruptEntry();
return true;
}
void Warp::printStats() const {
std::cout << "Steps : " << steps_ << std::endl
<< "Insts : " << insts_ << std::endl

View file

@ -89,8 +89,6 @@ public:
void step(trace_inst_t *);
bool interrupt(Word r0);
bool running() const {
return (activeThreads_ != 0);
}
@ -125,14 +123,6 @@ public:
spawned_ = spawned;
}
void setSupervisorMode(bool supervisorMode) {
supervisorMode_ = supervisorMode;
}
bool getSupervisorMode() const {
return supervisorMode_;
}
void setTmask(size_t index, bool value) {
tmask_[index] = value;
}
@ -156,14 +146,16 @@ private:
Word shadowPc_;
Size activeThreads_;
Size shadowActiveThreads_;
std::vector<std::vector<Reg<Word>>> regFile_;
std::vector<Reg<uint16_t>> csrs_;
std::vector<std::vector<Reg<Word>>> iRegFile_;
std::vector<std::vector<Reg<Word>>> fRegFile_;
std::vector<Reg<uint32_t>> csrs_;
std::vector<bool> tmask_;
std::vector<bool> shadowTmask_;
std::stack<DomStackEntry> domStack_;
std::vector<Word> shadowReg_;
std::vector<Word> shadowIReg_;
std::vector<Word> shadowFReg_;
struct vtype vtype_; // both of them are XLEN WIDE
int vl_; // both of them are XLEN WIDE
@ -171,10 +163,6 @@ private:
std::vector<std::vector<Reg<char *>>> vregFile_; // 32 vector registers
bool interruptEnable_;
bool shadowInterruptEnable_;
bool supervisorMode_;
bool shadowSupervisorMode_;
bool spawned_;
unsigned long steps_;