File instr_branch.h
File List > projects > simtix > src > simtix > sm > instr_branch.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 InstrBranch : public Instr {
public:
using Op = void (InstrBranch::*)();
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_ && rs2_data_ready_;
}
bool CanCommit() const override { return executed_; }
bool CanRetire() const override { return committed_; }
bool may_change_ctrl_flow() const override { return true; }
// Helper functions
static inline int64_t DecodeImmBtype(uint32_t iword) {
// (((iword & 0x80000000) >> 31 << 12) + ((iword & 0x80) >> 7 << 11) +
// ((iword & 0x7e000000) >> 25 << 5) + ((iword & 0xf00) >> 8 << 1))
return ((int32_t(iword & 0x80000000) >> 19) + (int32_t(iword & 0x80) << 4) +
(int32_t(iword & 0x7e000000) >> 20) +
(int32_t(iword & 0xf00) >> 7));
}
protected:
InstrBranch(Warp *warp, uint32_t iword, uint64_t wpc);
void Reinitialize(Warp *warp, uint32_t iword, uint64_t wpc) override;
Op op_ = nullptr;
bool rs1_data_ready_ = false;
bool rs2_data_ready_ = false;
bool executed_ = false;
bool committed_ = false;
int64_t imm_ = 0;
// Register data
std::vector<int64_t> rs1_data_;
std::vector<int64_t> rs2_data_;
// Next PC
std::vector<uint64_t> next_pc_;
private:
// Operations defined in this Opcode
void beq_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] =
(rs1_data_[tid] == rs2_data_[tid]) ? wpc_ + imm_ : wpc_ + 4;
}
}
void bne_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] =
(rs1_data_[tid] != rs2_data_[tid]) ? wpc_ + imm_ : wpc_ + 4;
}
}
void blt_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] =
(rs1_data_[tid] < rs2_data_[tid]) ? wpc_ + imm_ : wpc_ + 4;
}
}
void bge_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] =
(rs1_data_[tid] >= rs2_data_[tid]) ? wpc_ + imm_ : wpc_ + 4;
}
}
void bltu_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] = (uint64_t(rs1_data_[tid]) < uint64_t(rs2_data_[tid]))
? wpc_ + imm_
: wpc_ + 4;
}
}
void bgeu_() {
for (Thread *t : active_threads_) {
uint32_t tid = t->tid();
next_pc_[tid] = (uint64_t(rs1_data_[tid]) >= uint64_t(rs2_data_[tid]))
? wpc_ + imm_
: wpc_ + 4;
}
}
void nop_() {}
// Make InstrPool friend so that they can call our protected constructor
template <class InstrType>
friend class InstrPool;
};
} // namespace simtix