File instr_system.h
File List > projects > simtix > src > simtix > sm > instr_system.h
Go to the documentation of this file
#pragma once
#include <cstdint>
#include <vector>
#include "sm/instr.h"
#include "sm/warp.h"
namespace simtix {
class InstrSystem : public Instr {
public:
using Op = void (InstrSystem::*)();
void Decode() override;
void Issue() override;
void OperandCollect() override;
void Execute() override;
void Commit() override;
void Reset() override;
void Assign(const Instr* other) override;
bool CanIssue() const override;
bool CanExecute() const override { return rs1_data_ready_; }
bool CanCommit() const override { return true; }
bool CanRetire() const override { return committed_; }
bool exception_valid() const override {
return illegal_ || op_ == &InstrSystem::ecall_;
}
static inline uint16_t DecodeCSR(uint32_t iword) {
return (uint16_t)(iword >> 20);
}
static inline uint64_t DecodeUimm(uint32_t iword) {
return (uint64_t)(iword >> 15) & (uint64_t)0x1f;
}
protected:
InstrSystem(Warp* warp, uint32_t iword, uint64_t wpc);
void Reinitialize(Warp* warp, uint32_t iword, uint64_t wpc) override;
Op op_ = nullptr;
uint16_t csr_ = 0;
uint64_t uimm_ = 0;
bool rs1_data_ready_ = false;
bool committed_ = false;
// Register data
std::vector<int64_t> rs1_data_;
std::vector<int64_t> rd_data_;
private:
void csrrw_() {
for (Thread* t : active_threads_) {
if (rd_) {
// regfile[rd_] = csr[csr_]
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
rd_data_[t->tid()] = csr_data;
}
// csr[csr_] = regfile[rs1_]
if (t->WriteCSR(csr_, rs1_data_[t->tid()]) == -1) {
illegal_ = true;
return;
}
}
}
void csrrs_() {
for (Thread* t : active_threads_) {
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
if (rs1_) {
// csr[csr_] = regfile[rs1_] | csr[csr_]
uint64_t set_csr_data = csr_data | rs1_data_[t->tid()];
if (t->WriteCSR(csr_, set_csr_data) == -1) {
illegal_ = true;
return;
}
}
// regfile[rd_] = csr[csr_]
rd_data_[t->tid()] = csr_data;
}
}
void csrrc_() {
for (Thread* t : active_threads_) {
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
if (rs1_) {
// csr[csr_] = csr[csr_] & ~regfile[rs1_]
uint64_t clear_csr_data = csr_data & ~rs1_data_[t->tid()];
if (t->WriteCSR(csr_, clear_csr_data) == -1) {
illegal_ = true;
return;
}
}
// regfile[rd_] = csr[csr_]
rd_data_[t->tid()] = csr_data;
}
}
void csrrwi_() {
for (Thread* t : active_threads_) {
if (rd_) {
// regfile[rd_] = csr[csr_]
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
rd_data_[t->tid()] = csr_data;
}
// csr[csr_] = uimm_
if (t->WriteCSR(csr_, uimm_) == -1) {
illegal_ = true;
return;
}
}
}
void csrrsi_() {
for (Thread* t : active_threads_) {
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
// regfile[rd_] = csr[csr_]
rd_data_[t->tid()] = csr_data;
if (rs1_ & (uint8_t)0x1f) {
// csr[csr_] = uimm_ | csr[csr_]
uint64_t set_csr_data = csr_data | uimm_;
if (t->WriteCSR(csr_, set_csr_data) == -1) {
illegal_ = true;
return;
}
}
}
}
void csrrci_() {
for (Thread* t : active_threads_) {
uint64_t csr_data;
t->ReadCSR(csr_, &csr_data);
// regfile[rd_] = csr[csr_]
rd_data_[t->tid()] = csr_data;
if (rs1_ & (uint8_t)0x1f) {
// csr[csr_] = csr[csr_] & ~uimm_
uint64_t clear_csr_data = csr_data & ~uimm_;
if (t->WriteCSR(csr_, clear_csr_data) == -1) {
illegal_ = true;
return;
}
}
}
}
void ecall_() {
warp_->set_mepc(wpc_);
warp_->set_mcause(11); // E-call from m mode
warp_->set_mtval(0);
illegal_ = false;
}
void nop_() {}
// Make InstrPool friend so that they can call our protected constructor
template <class InstrType>
friend class InstrPool;
};
} // namespace simtix