File instr.h
File List > projects > simtix > src > simtix > sm > instr.h
Go to the documentation of this file
#pragma once
#include <stdint.h>
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
#include "sm/thread.h"
#include "sm/warp.h"
// Execution latency
#ifndef LATENCY_IMUL
#define LATENCY_IMUL 2
#endif
#ifndef LATENCY_IDIV
#define LATENCY_IDIV 8
#endif
#ifndef SUBWARP_INTERLEAVING
#define SUBWARP_INTERLEAVING 1
#endif
namespace simtix {
class Instr {
public:
enum Opcode : uint8_t {
// clang-format off
kLoad = 0b0000011,
kStore = 0b0100011,
kBranch = 0b1100011,
kCustom1 = 0b0101011,
kOpImm = 0b0010011,
kOp = 0b0110011,
kSystem = 0b1110011,
kAuipc = 0b0010111,
kLui = 0b0110111,
kOpImm32 = 0b0011011,
kOp32 = 0b0111011,
kFmadd = 0b1000011,
kFmsub = 0b1000111,
kFnmsub = 0b1001011,
kFnmadd = 0b1001111,
kOpFp = 0b1010011,
kJal = 0b1101111,
kJalr = 0b1100111
// clang-format on
};
enum ExecutionUnit : uint8_t { kALU = 0, kLSU, kMul, kDiv, kFPU };
// Operations for different pipeline stage
virtual void Decode();
virtual void Issue();
virtual void OperandCollect() = 0;
virtual void Execute() = 0;
virtual void Commit() = 0;
virtual void Reset();
virtual void Assign(const Instr *other);
// Check scoreboard
virtual bool CanIssue() const = 0;
virtual bool CanExecute() const = 0;
virtual bool CanCommit() const = 0;
virtual bool CanRetire() const = 0;
void set_ssw(std::optional<uint32_t> ssw) { ssw_ = ssw; }
// Public getters
uint32_t wid() const {
return (warp_ == nullptr) ? UINT32_MAX : warp_->wid();
}
uint32_t iword() const { return iword_; }
uint64_t wpc() const { return wpc_; }
uint8_t opcode() const { return opcode_; }
bool illegal() const { return illegal_; }
uint8_t tswid() const { return tswid_; }
uint32_t sswid() const { return ssw_.value_or(0); }
ExecutionUnit execution_unit() const { return execution_unit_; }
// implement by each instruction
virtual bool may_change_ctrl_flow() const { return false; }
virtual bool barrier_valid() const { return false; }
virtual bool exception_valid() const { return illegal_; }
// Helper functions for decoding common bit fields
static constexpr uint32_t BitMask(uint32_t width) { return (1 << width) - 1; }
static inline uint8_t DecodeOpcode(uint32_t iword) {
return iword & BitMask(7);
}
static inline uint8_t DecodeRd(uint32_t iword) {
return (iword >> 7) & BitMask(5);
}
static inline uint8_t DecodeFunct3(uint32_t iword) {
return (iword >> 12) & BitMask(3);
}
static inline uint8_t DecodeRs1(uint32_t iword) {
return (iword >> 15) & BitMask(5);
}
static inline uint8_t DecodeRs2(uint32_t iword) {
return (iword >> 20) & BitMask(5);
}
static inline uint8_t DecodeFunct7(uint32_t iword) {
return (iword >> 25) & BitMask(7);
}
protected:
// Protected constructor
Instr(Warp *warp, uint32_t iword, uint64_t wpc)
: warp_(warp), iword_(iword), wpc_(wpc) {}
virtual ~Instr() = default;
// Protected function to reinitialize the instruction
virtual void Reinitialize(Warp *warp, uint32_t iword, uint64_t wpc) {
warp_ = warp;
iword_ = iword;
wpc_ = wpc;
}
// Reference to the warp
Warp *warp_;
// The instruction word
uint32_t iword_;
// Instruction PC (warp PC)
uint64_t wpc_;
// Opcode
uint8_t opcode_ = 0;
// Function code
uint8_t funct3_ = 0, funct7_ = 0;
// Registers
uint8_t rs1_ = 0, rs2_ = 0, rd_ = 0;
// Is illegal instruction or not
bool illegal_ = false;
// Execution unit
ExecutionUnit execution_unit_ = kALU;
// Instruction mnemonic
std::string mnemonic_;
std::optional<uint32_t> ssw_;
uint8_t tswid_ = 0;
std::vector<Thread *> active_threads_;
private:
template <class InstrType>
friend class InstrPool;
friend class InstrPtr;
};
} // namespace simtix