Added namespace to project

This commit is contained in:
mariusmonton 2021-11-29 20:35:26 +01:00
parent e2981d8a50
commit fb84f197bf
28 changed files with 4895 additions and 4632 deletions

View File

@ -17,7 +17,9 @@
#include "MemoryInterface.h" #include "MemoryInterface.h"
#include "extension_base.h" #include "extension_base.h"
typedef enum { namespace riscv_tlm {
typedef enum {
OP_A_LR, OP_A_LR,
OP_A_SC, OP_A_SC,
OP_A_AMOSWAP, OP_A_AMOSWAP,
@ -31,9 +33,9 @@ typedef enum {
OP_A_AMOMAXU, OP_A_AMOMAXU,
OP_A_ERROR OP_A_ERROR
} op_A_Codes; } op_A_Codes;
typedef enum { typedef enum {
A_LR = 0b00010, A_LR = 0b00010,
A_SC = 0b00011, A_SC = 0b00011,
A_AMOSWAP = 0b00001, A_AMOSWAP = 0b00001,
@ -45,13 +47,13 @@ typedef enum {
A_AMOMAX = 0b10100, A_AMOMAX = 0b10100,
A_AMOMINU = 0b11000, A_AMOMINU = 0b11000,
A_AMOMAXU = 0b11100, A_AMOMAXU = 0b11100,
} A_Codes; } A_Codes;
/** /**
* @brief Instruction decoding and fields access * @brief Instruction decoding and fields access
*/ */
class A_extension: public extension_base { class A_extension : public extension_base {
public: public:
/** /**
* @brief Constructor, same as base class * @brief Constructor, same as base class
@ -77,24 +79,36 @@ public:
} }
bool Exec_A_LR(); bool Exec_A_LR();
bool Exec_A_SC(); bool Exec_A_SC();
bool Exec_A_AMOSWAP() const; bool Exec_A_AMOSWAP() const;
bool Exec_A_AMOADD() const; bool Exec_A_AMOADD() const;
bool Exec_A_AMOXOR() const; bool Exec_A_AMOXOR() const;
bool Exec_A_AMOAND() const; bool Exec_A_AMOAND() const;
bool Exec_A_AMOOR() const; bool Exec_A_AMOOR() const;
bool Exec_A_AMOMIN() const; bool Exec_A_AMOMIN() const;
bool Exec_A_AMOMAX() const; bool Exec_A_AMOMAX() const;
bool Exec_A_AMOMINU() const; bool Exec_A_AMOMINU() const;
bool Exec_A_AMOMAXU() const; bool Exec_A_AMOMAXU() const;
bool process_instruction(Instruction &inst); bool process_instruction(Instruction &inst);
void TLB_reserve(std::uint32_t address); void TLB_reserve(std::uint32_t address);
bool TLB_reserved(std::uint32_t address); bool TLB_reserved(std::uint32_t address);
private: private:
std::unordered_set<std::uint32_t> TLB_A_Entries; std::unordered_set<std::uint32_t> TLB_A_Entries;
}; };
}
#endif #endif

View File

@ -23,7 +23,9 @@
#include "A_extension.h" #include "A_extension.h"
#include "Registers.h" #include "Registers.h"
typedef enum { namespace riscv_tlm {
typedef enum {
OP_LUI, OP_LUI,
OP_AUIPC, OP_AUIPC,
OP_JAL, OP_JAL,
@ -85,13 +87,13 @@ typedef enum {
OP_SFENCE, OP_SFENCE,
OP_ERROR OP_ERROR
} opCodes; } opCodes;
/** /**
* @brief Risc_V execute module * @brief Risc_V execute module
*/ */
class BASE_ISA: public extension_base { class BASE_ISA : public extension_base {
public: public:
/** /**
* @brief Constructor, same as base class * @brief Constructor, same as base class
@ -119,7 +121,7 @@ public:
* @return immediate_I field * @return immediate_I field
*/ */
inline std::int32_t get_imm_I() const { inline std::int32_t get_imm_I() const {
std::int32_t aux = 0; std::uint32_t aux = 0;
aux = m_instr.range(31, 20); aux = m_instr.range(31, 20);
@ -128,7 +130,7 @@ public:
aux |= (0b11111111111111111111) << 12; aux |= (0b11111111111111111111) << 12;
} }
return aux; return static_cast<std::int32_t>(aux);
} }
/** /**
@ -144,7 +146,7 @@ public:
* @return immediate_S field * @return immediate_S field
*/ */
inline std::int32_t get_imm_S() const { inline std::int32_t get_imm_S() const {
std::int32_t aux = 0; std::uint32_t aux = 0;
aux = m_instr.range(31, 25) << 5; aux = m_instr.range(31, 25) << 5;
aux |= m_instr.range(11, 7); aux |= m_instr.range(11, 7);
@ -153,7 +155,7 @@ public:
aux |= (0b11111111111111111111) << 12; aux |= (0b11111111111111111111) << 12;
} }
return aux; return static_cast<std::int32_t>(aux);
} }
/** /**
@ -161,7 +163,7 @@ public:
* @return immediate_U field * @return immediate_U field
*/ */
inline std::int32_t get_imm_U() const { inline std::int32_t get_imm_U() const {
return m_instr.range(31, 12); return static_cast<std::int32_t>(m_instr.range(31, 12));
} }
/** /**
@ -266,67 +268,108 @@ public:
} }
bool Exec_LUI() const; bool Exec_LUI() const;
bool Exec_AUIPC() const; bool Exec_AUIPC() const;
bool Exec_JAL() const; bool Exec_JAL() const;
bool Exec_JALR(); bool Exec_JALR();
bool Exec_BEQ() const; bool Exec_BEQ() const;
bool Exec_BNE() const; bool Exec_BNE() const;
bool Exec_BLT() const; bool Exec_BLT() const;
bool Exec_BGE() const; bool Exec_BGE() const;
bool Exec_BLTU() const; bool Exec_BLTU() const;
bool Exec_BGEU() const; bool Exec_BGEU() const;
bool Exec_LB() const; bool Exec_LB() const;
bool Exec_LH() const; bool Exec_LH() const;
bool Exec_LW() const; bool Exec_LW() const;
bool Exec_LBU() const; bool Exec_LBU() const;
bool Exec_LHU() const; bool Exec_LHU() const;
bool Exec_SB() const; bool Exec_SB() const;
bool Exec_SH() const; bool Exec_SH() const;
bool Exec_SW() const; bool Exec_SW() const;
bool Exec_SBU() const; bool Exec_SBU() const;
bool Exec_SHU() const; bool Exec_SHU() const;
bool Exec_ADDI() const; bool Exec_ADDI() const;
bool Exec_SLTI() const; bool Exec_SLTI() const;
bool Exec_SLTIU() const; bool Exec_SLTIU() const;
bool Exec_XORI() const; bool Exec_XORI() const;
bool Exec_ORI() const; bool Exec_ORI() const;
bool Exec_ANDI() const; bool Exec_ANDI() const;
bool Exec_SLLI(); bool Exec_SLLI();
bool Exec_SRLI() const; bool Exec_SRLI() const;
bool Exec_SRAI() const; bool Exec_SRAI() const;
bool Exec_ADD() const; bool Exec_ADD() const;
bool Exec_SUB() const; bool Exec_SUB() const;
bool Exec_SLL() const; bool Exec_SLL() const;
bool Exec_SLT() const; bool Exec_SLT() const;
bool Exec_SLTU() const; bool Exec_SLTU() const;
bool Exec_XOR() const; bool Exec_XOR() const;
bool Exec_SRL() const; bool Exec_SRL() const;
bool Exec_SRA() const; bool Exec_SRA() const;
bool Exec_OR() const; bool Exec_OR() const;
bool Exec_AND() const; bool Exec_AND() const;
bool Exec_FENCE() const; bool Exec_FENCE() const;
bool Exec_ECALL(); bool Exec_ECALL();
bool Exec_EBREAK(); bool Exec_EBREAK();
bool Exec_CSRRW() const; bool Exec_CSRRW() const;
bool Exec_CSRRS() const; bool Exec_CSRRS() const;
bool Exec_CSRRC() const; bool Exec_CSRRC() const;
bool Exec_CSRRWI() const; bool Exec_CSRRWI() const;
bool Exec_CSRRSI() const; bool Exec_CSRRSI() const;
bool Exec_CSRRCI() const; bool Exec_CSRRCI() const;
/*********************** Privileged Instructions ******************************/ /*********************** Privileged Instructions ******************************/
bool Exec_MRET() const; bool Exec_MRET() const;
bool Exec_SRET() const; bool Exec_SRET() const;
bool Exec_WFI() const; bool Exec_WFI() const;
bool Exec_SFENCE() const; bool Exec_SFENCE() const;
/** /**
@ -341,6 +384,6 @@ public:
* @return opcode of instruction * @return opcode of instruction
*/ */
opCodes decode(); opCodes decode();
}; };
}
#endif #endif

View File

@ -20,6 +20,8 @@
#include "tlm_utils/simple_initiator_socket.h" #include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h" #include "tlm_utils/simple_target_socket.h"
namespace riscv_tlm {
/** /**
* Memory mapped Trace peripheral address * Memory mapped Trace peripheral address
*/ */
@ -41,8 +43,8 @@
* It will be expanded with more ports when required (for DMA, * It will be expanded with more ports when required (for DMA,
* other peripherals, etc.) * other peripherals, etc.)
*/ */
class BusCtrl: sc_core::sc_module { class BusCtrl : sc_core::sc_module {
public: public:
/** /**
* @brief TLM target socket CPU instruction memory bus * @brief TLM target socket CPU instruction memory bus
*/ */
@ -82,10 +84,11 @@ public:
virtual void b_transport(tlm::tlm_generic_payload &trans, virtual void b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay); sc_core::sc_time &delay);
private: private:
bool instr_direct_mem_ptr(tlm::tlm_generic_payload&, bool instr_direct_mem_ptr(tlm::tlm_generic_payload &,
tlm::tlm_dmi &dmi_data); tlm::tlm_dmi &dmi_data);
void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end);
};
void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end);
};
}
#endif #endif

View File

@ -26,12 +26,14 @@
#include "M_extension.h" #include "M_extension.h"
#include "A_extension.h" #include "A_extension.h"
namespace riscv_tlm {
/** /**
* @brief ISC_V CPU model * @brief ISC_V CPU model
* @param name name of the module * @param name name of the module
*/ */
class CPU: sc_core::sc_module { class CPU : sc_core::sc_module {
public: public:
/** /**
* @brief Instruction Memory bus socket * @brief Instruction Memory bus socket
@ -65,9 +67,9 @@ public:
bool CPU_step(); bool CPU_step();
Registers *getRegisterBank() {return register_bank;} Registers *getRegisterBank() { return register_bank; }
private: private:
Registers *register_bank; Registers *register_bank;
Performance *perf; Performance *perf;
std::shared_ptr<spdlog::logger> logger; std::shared_ptr<spdlog::logger> logger;
@ -89,7 +91,6 @@ private:
unsigned char *dmi_ptr = nullptr; unsigned char *dmi_ptr = nullptr;
/** /**
* *
* @brief Process and triggers IRQ if all conditions met * @brief Process and triggers IRQ if all conditions met
@ -119,6 +120,7 @@ private:
* @param end memory address region end * @param end memory address region end
*/ */
void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end); void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end);
}; };
}
#endif #endif

View File

@ -12,7 +12,9 @@
#include "systemc" #include "systemc"
#include "extension_base.h" #include "extension_base.h"
typedef enum { namespace riscv_tlm {
typedef enum {
OP_C_ADDI4SPN, OP_C_ADDI4SPN,
OP_C_FLD, OP_C_FLD,
OP_C_LW, OP_C_LW,
@ -52,9 +54,9 @@ typedef enum {
OP_C_FSWSP, OP_C_FSWSP,
OP_C_ERROR OP_C_ERROR
} op_C_Codes; } op_C_Codes;
typedef enum { typedef enum {
C_ADDI4SPN = 0b000, C_ADDI4SPN = 0b000,
C_FLD = 0b001, C_FLD = 0b001,
C_LW = 0b010, C_LW = 0b010,
@ -88,13 +90,13 @@ typedef enum {
C_FDSP = 0b101, C_FDSP = 0b101,
C_SWSP = 0b110, C_SWSP = 0b110,
C_FWWSP = 0b111, C_FWWSP = 0b111,
} C_Codes; } C_Codes;
/** /**
* @brief Instruction decoding and fields access * @brief Instruction decoding and fields access
*/ */
class C_extension: public extension_base { class C_extension : public extension_base {
public: public:
/** /**
* @brief Constructor, same as base clase * @brief Constructor, same as base clase
@ -237,6 +239,7 @@ public:
m_instr.range(11, 7) = aux.range(4, 1); m_instr.range(11, 7) = aux.range(4, 1);
m_instr[6] = aux[11]; m_instr[6] = aux[11];
} }
/** /**
* @brief Access to immediate field for J-type * @brief Access to immediate field for J-type
* @return immediate_J field * @return immediate_J field
@ -290,7 +293,7 @@ public:
return aux; return aux;
} }
inline std::int32_t get_imm_ADDI () const { inline std::int32_t get_imm_ADDI() const {
std::int32_t aux = 0; std::int32_t aux = 0;
aux = static_cast<std::int32_t>(m_instr[12] << 5); aux = static_cast<std::int32_t>(m_instr[12] << 5);
@ -380,32 +383,55 @@ public:
op_C_Codes decode() const; op_C_Codes decode() const;
bool Exec_C_JR(); bool Exec_C_JR();
bool Exec_C_MV(); bool Exec_C_MV();
bool Exec_C_LWSP(); bool Exec_C_LWSP();
bool Exec_C_ADDI4SPN(); bool Exec_C_ADDI4SPN();
bool Exec_C_SLLI(); bool Exec_C_SLLI();
bool Exec_C_ADDI16SP(); bool Exec_C_ADDI16SP();
bool Exec_C_SWSP(); bool Exec_C_SWSP();
bool Exec_C_BEQZ(); bool Exec_C_BEQZ();
bool Exec_C_BNEZ(); bool Exec_C_BNEZ();
bool Exec_C_LI(); bool Exec_C_LI();
bool Exec_C_SRLI(); bool Exec_C_SRLI();
bool Exec_C_SRAI(); bool Exec_C_SRAI();
bool Exec_C_ANDI(); bool Exec_C_ANDI();
bool Exec_C_ADD(); bool Exec_C_ADD();
bool Exec_C_SUB(); bool Exec_C_SUB();
bool Exec_C_XOR(); bool Exec_C_XOR();
bool Exec_C_OR(); bool Exec_C_OR();
bool Exec_C_AND(); bool Exec_C_AND();
bool Exec_C_ADDI() const; bool Exec_C_ADDI() const;
bool Exec_C_JALR(); bool Exec_C_JALR();
bool Exec_C_LW(); bool Exec_C_LW();
bool Exec_C_SW(); bool Exec_C_SW();
bool Exec_C_JAL(int m_rd); bool Exec_C_JAL(int m_rd);
bool Exec_C_EBREAK(); bool Exec_C_EBREAK();
bool process_instruction(Instruction &inst, bool *breakpoint = nullptr); bool process_instruction(Instruction &inst, bool *breakpoint = nullptr);
}; };
}
#endif #endif

View File

@ -12,7 +12,9 @@
#include "systemc" #include "systemc"
#include "extension_base.h" #include "extension_base.h"
typedef enum { namespace riscv_tlm {
typedef enum {
BASE_EXTENSION, BASE_EXTENSION,
M_EXTENSION, M_EXTENSION,
A_EXTENSION, A_EXTENSION,
@ -27,13 +29,13 @@ typedef enum {
V_EXTENSION, V_EXTENSION,
N_EXTENSION, N_EXTENSION,
UNKNOWN_EXTENSION UNKNOWN_EXTENSION
} extension_t; } extension_t;
/** /**
* @brief Instruction decoding and fields access * @brief Instruction decoding and fields access
*/ */
class Instruction { class Instruction {
public: public:
Instruction(std::uint32_t instr); Instruction(std::uint32_t instr);
@ -46,6 +48,7 @@ public:
void setInstr(std::uint32_t p_instr) { void setInstr(std::uint32_t p_instr) {
m_instr = p_instr; m_instr = p_instr;
} }
/** /**
* @brief return instruction * @brief return instruction
* @return all instruction bits (31:0) * @return all instruction bits (31:0)
@ -58,8 +61,9 @@ public:
std::cout << std::hex << "0x" << m_instr << std::dec << std::endl; std::cout << std::hex << "0x" << m_instr << std::dec << std::endl;
} }
private: private:
std::uint32_t m_instr; std::uint32_t m_instr;
}; };
}
#endif #endif

View File

@ -14,7 +14,9 @@
#include "extension_base.h" #include "extension_base.h"
#include "Registers.h" #include "Registers.h"
typedef enum { namespace riscv_tlm {
typedef enum {
OP_M_MUL, OP_M_MUL,
OP_M_MULH, OP_M_MULH,
OP_M_MULHSU, OP_M_MULHSU,
@ -25,9 +27,9 @@ typedef enum {
OP_M_REMU, OP_M_REMU,
OP_M_ERROR OP_M_ERROR
} op_M_Codes; } op_M_Codes;
typedef enum { typedef enum {
M_MUL = 0b000, M_MUL = 0b000,
M_MULH = 0b001, M_MULH = 0b001,
M_MULHSU = 0b010, M_MULHSU = 0b010,
@ -36,13 +38,13 @@ typedef enum {
M_DIVU = 0b101, M_DIVU = 0b101,
M_REM = 0b110, M_REM = 0b110,
M_REMU = 0b111, M_REMU = 0b111,
} M_Codes; } M_Codes;
/** /**
* @brief Instruction decoding and fields access * @brief Instruction decoding and fields access
*/ */
class M_extension: public extension_base { class M_extension : public extension_base {
public: public:
/** /**
* @brief Constructor, same as base clase * @brief Constructor, same as base clase
@ -60,17 +62,24 @@ public:
} }
bool Exec_M_MUL() const; bool Exec_M_MUL() const;
bool Exec_M_MULH() const; bool Exec_M_MULH() const;
bool Exec_M_MULHSU() const; bool Exec_M_MULHSU() const;
bool Exec_M_MULHU() const; bool Exec_M_MULHU() const;
bool Exec_M_DIV() const; bool Exec_M_DIV() const;
bool Exec_M_DIVU() const; bool Exec_M_DIVU() const;
bool Exec_M_REM() const; bool Exec_M_REM() const;
bool Exec_M_REMU() const; bool Exec_M_REMU() const;
bool process_instruction(Instruction &inst); bool process_instruction(Instruction &inst);
private: private:
/** /**
* @brief Access to opcode field * @brief Access to opcode field
@ -80,6 +89,7 @@ private:
return static_cast<std::int32_t>(m_instr.range(14, 12)); return static_cast<std::int32_t>(m_instr.range(14, 12));
} }
}; };
}
#endif #endif

View File

@ -21,11 +21,13 @@
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" #include "spdlog/sinks/basic_file_sink.h"
namespace riscv_tlm {
/** /**
* @brief Basic TLM-2 memory * @brief Basic TLM-2 memory
*/ */
class Memory: sc_core::sc_module { class Memory : sc_core::sc_module {
public: public:
// TLM-2 socket, defaults to 32-bits wide, base protocol // TLM-2 socket, defaults to 32-bits wide, base protocol
tlm_utils::simple_target_socket<Memory> socket; tlm_utils::simple_target_socket<Memory> socket;
@ -36,7 +38,8 @@ public:
const sc_core::sc_time LATENCY; const sc_core::sc_time LATENCY;
Memory(sc_core::sc_module_name const &name, std::string const &filename); Memory(sc_core::sc_module_name const &name, std::string const &filename);
explicit Memory(const sc_core::sc_module_name& name);
explicit Memory(const sc_core::sc_module_name &name);
~Memory() override; ~Memory() override;
@ -61,7 +64,7 @@ public:
// ********************************************* // *********************************************
virtual unsigned int transport_dbg(tlm::tlm_generic_payload &trans); virtual unsigned int transport_dbg(tlm::tlm_generic_payload &trans);
private: private:
/** /**
* @brief Memory array in bytes * @brief Memory array in bytes
@ -87,6 +90,7 @@ private:
* @brief Read Intel hex file * @brief Read Intel hex file
* @param filename file name to read * @param filename file name to read
*/ */
void readHexFile(const std::string& filename); void readHexFile(const std::string &filename);
}; };
}
#endif /* __MEMORY_H__ */ #endif /* __MEMORY_H__ */

View File

@ -17,17 +17,21 @@
#include "memory.h" #include "memory.h"
namespace riscv_tlm {
/** /**
* @brief Memory Interface * @brief Memory Interface
*/ */
class MemoryInterface { class MemoryInterface {
public: public:
tlm_utils::simple_initiator_socket<MemoryInterface> data_bus; tlm_utils::simple_initiator_socket<MemoryInterface> data_bus;
MemoryInterface(); MemoryInterface();
std::uint32_t readDataMem(std::uint32_t addr, int size);
void writeDataMem(std::uint32_t addr, std::uint32_t data, int size);
};
std::uint32_t readDataMem(std::uint32_t addr, int size);
void writeDataMem(std::uint32_t addr, std::uint32_t data, int size);
};
}
#endif /* INC_MEMORYINTERFACE_H_ */ #endif /* INC_MEMORYINTERFACE_H_ */

View File

@ -19,6 +19,8 @@
#include "Performance.h" #include "Performance.h"
#include "Memory.h" #include "Memory.h"
namespace riscv_tlm {
#define MISA_A_EXTENSION (1 << 0) #define MISA_A_EXTENSION (1 << 0)
#define MISA_B_EXTENSION (1 << 1) #define MISA_B_EXTENSION (1 << 1)
#define MISA_C_EXTENSION (1 << 2) #define MISA_C_EXTENSION (1 << 2)
@ -110,8 +112,8 @@
/** /**
* @brief Register file implementation * @brief Register file implementation
*/ */
class Registers { class Registers {
public: public:
enum { enum {
x0 = 0, x0 = 0,
@ -180,6 +182,7 @@ public:
t5 = x30, t5 = x30,
t6 = x31 t6 = x31
}; };
/** /**
* Default constructor * Default constructor
*/ */
@ -240,11 +243,12 @@ public:
* Dump register data to console * Dump register data to console
*/ */
void dump(); void dump();
private:
private:
/** /**
* bank of registers (32 regs of 32bits each) * bank of registers (32 regs of 32bits each)
*/ */
std::array<std::uint32_t, 32> register_bank = { {0} }; std::array<std::uint32_t, 32> register_bank = {{0}};
/** /**
* Program counter (32 bits width) * Program counter (32 bits width)
@ -260,6 +264,6 @@ private:
Performance *perf; Performance *perf;
void initCSR(); void initCSR();
}; };
}
#endif #endif

View File

@ -21,14 +21,15 @@
#include "BusCtrl.h" #include "BusCtrl.h"
namespace riscv_tlm::peripherals {
/** /**
* @brief Simple timer peripheral * @brief Simple timer peripheral
* *
* It runs a 1 ns (nanoseconds) pace * It runs a 1 ns (nanoseconds) pace
* *
*/ */
class Timer: sc_core::sc_module { class Timer : sc_core::sc_module {
public: public:
// TLM-2 socket, defaults to 32-bits wide, base protocol // TLM-2 socket, defaults to 32-bits wide, base protocol
tlm_utils::simple_target_socket<Timer> socket; tlm_utils::simple_target_socket<Timer> socket;
@ -61,10 +62,10 @@ public:
virtual void b_transport(tlm::tlm_generic_payload &trans, virtual void b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay); sc_core::sc_time &delay);
private: private:
sc_dt::sc_uint<64> m_mtime; /**< mtime register */ sc_dt::sc_uint<64> m_mtime; /**< mtime register */
sc_dt::sc_uint<64> m_mtimecmp; /**< mtimecmp register */ sc_dt::sc_uint<64> m_mtimecmp; /**< mtimecmp register */
sc_core::sc_event timer_event; /**< event */ sc_core::sc_event timer_event; /**< event */
}; };
}
#endif #endif

View File

@ -19,13 +19,14 @@
#include "tlm.h" #include "tlm.h"
#include "tlm_utils/simple_target_socket.h" #include "tlm_utils/simple_target_socket.h"
namespace riscv_tlm::peripherals {
/** /**
* @brief Simple trace peripheral * @brief Simple trace peripheral
* *
* This peripheral outputs to cout any character written to its unique register * This peripheral outputs to cout any character written to its unique register
*/ */
class Trace: sc_core::sc_module { class Trace : sc_core::sc_module {
public: public:
/** /**
* @brief Bus socket * @brief Bus socket
@ -43,19 +44,21 @@ public:
*/ */
~Trace() override; ~Trace() override;
private: private:
// TLM-2 blocking transport method // TLM-2 blocking transport method
virtual void b_transport(tlm::tlm_generic_payload &trans, virtual void b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay); sc_core::sc_time &delay);
void xtermLaunch(char *slaveName) const; void xtermLaunch(char *slaveName) const;
void xtermKill(); void xtermKill();
void xtermSetup(); void xtermSetup();
int ptSlave{}; int ptSlave{};
int ptMaster{}; int ptMaster{};
int xtermPid{}; int xtermPid{};
}; };
}
#endif #endif

View File

@ -26,15 +26,20 @@
#define EXCEPTION_CAUSE_LOAD_ADDR_MISALIGN 4 #define EXCEPTION_CAUSE_LOAD_ADDR_MISALIGN 4
#define EXCEPTION_CAUSE_LOAD_ACCESS_FAULT 5 #define EXCEPTION_CAUSE_LOAD_ACCESS_FAULT 5
class extension_base { namespace riscv_tlm {
public: class extension_base {
extension_base(const sc_dt::sc_uint<32> & instr, Registers *register_bank,
public:
extension_base(const sc_dt::sc_uint<32> &instr, Registers *register_bank,
MemoryInterface *mem_interface); MemoryInterface *mem_interface);
virtual ~extension_base() = 0; virtual ~extension_base() = 0;
void setInstr(std::uint32_t p_instr); void setInstr(std::uint32_t p_instr);
void RaiseException(std::uint32_t cause, std::uint32_t inst); void RaiseException(std::uint32_t cause, std::uint32_t inst);
bool NOP(); bool NOP();
/* pure virtual functions */ /* pure virtual functions */
@ -74,12 +79,13 @@ public:
virtual void dump() const; virtual void dump() const;
protected: protected:
sc_dt::sc_uint<32> m_instr; sc_dt::sc_uint<32> m_instr;
Registers *regs; Registers *regs;
Performance *perf; Performance *perf;
MemoryInterface *mem_intf; MemoryInterface *mem_intf;
std::shared_ptr<spdlog::logger> logger; std::shared_ptr<spdlog::logger> logger;
}; };
}
#endif /* INC_EXTENSION_BASE_H_ */ #endif /* INC_EXTENSION_BASE_H_ */

View File

@ -8,7 +8,9 @@
#include "A_extension.h" #include "A_extension.h"
op_A_Codes A_extension::decode() const { namespace riscv_tlm {
op_A_Codes A_extension::decode() const {
switch (opcode()) { switch (opcode()) {
case A_LR: case A_LR:
@ -51,9 +53,9 @@ op_A_Codes A_extension::decode() const {
} }
return OP_A_ERROR; return OP_A_ERROR;
} }
bool A_extension::Exec_A_LR() { bool A_extension::Exec_A_LR() {
std::uint32_t mem_addr = 0; std::uint32_t mem_addr = 0;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -76,13 +78,14 @@ bool A_extension::Exec_A_LR() {
TLB_reserve(mem_addr); TLB_reserve(mem_addr);
logger->debug("{} ns. PC: 0x{:x}. A.LR.W: x{:d}(0x{:x}) -> x{:d}(0x{:x}) ", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. A.LR.W: x{:d}(0x{:x}) -> x{:d}(0x{:x}) ", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, mem_addr, rd, data); rs1, mem_addr, rd, data);
return true; return true;
} }
bool A_extension::Exec_A_SC() { bool A_extension::Exec_A_SC() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -102,13 +105,14 @@ bool A_extension::Exec_A_SC() {
regs->setValue(rd, 1); // SC writes nonzero on failure regs->setValue(rd, 1); // SC writes nonzero on failure
} }
logger->debug("{} ns. PC: 0x{:x}. A.SC.W: (0x{:x}) <- x{:d}(0x{:x}) ", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. A.SC.W: (0x{:x}) <- x{:d}(0x{:x}) ", sc_core::sc_time_stamp().value(),
regs->getPC(),
mem_addr, rs2, data); mem_addr, rs2, data);
return true; return true;
} }
bool A_extension::Exec_A_AMOSWAP() const { bool A_extension::Exec_A_AMOSWAP() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -135,9 +139,9 @@ bool A_extension::Exec_A_AMOSWAP() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOSWAP"); logger->debug("{} ns. PC: 0x{:x}. A.AMOSWAP");
return true; return true;
} }
bool A_extension::Exec_A_AMOADD() const { bool A_extension::Exec_A_AMOADD() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -163,9 +167,9 @@ bool A_extension::Exec_A_AMOADD() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOADD"); logger->debug("{} ns. PC: 0x{:x}. A.AMOADD");
return true; return true;
} }
bool A_extension::Exec_A_AMOXOR() const { bool A_extension::Exec_A_AMOXOR() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -191,8 +195,9 @@ bool A_extension::Exec_A_AMOXOR() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOXOR"); logger->debug("{} ns. PC: 0x{:x}. A.AMOXOR");
return true; return true;
} }
bool A_extension::Exec_A_AMOAND() const {
bool A_extension::Exec_A_AMOAND() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -218,9 +223,9 @@ bool A_extension::Exec_A_AMOAND() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOAND"); logger->debug("{} ns. PC: 0x{:x}. A.AMOAND");
return true; return true;
} }
bool A_extension::Exec_A_AMOOR() const { bool A_extension::Exec_A_AMOOR() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -246,9 +251,9 @@ bool A_extension::Exec_A_AMOOR() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOOR"); logger->debug("{} ns. PC: 0x{:x}. A.AMOOR");
return true; return true;
} }
bool A_extension::Exec_A_AMOMIN() const { bool A_extension::Exec_A_AMOMIN() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -278,8 +283,9 @@ bool A_extension::Exec_A_AMOMIN() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOMIN"); logger->debug("{} ns. PC: 0x{:x}. A.AMOMIN");
return true; return true;
} }
bool A_extension::Exec_A_AMOMAX() const {
bool A_extension::Exec_A_AMOMAX() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -309,8 +315,9 @@ bool A_extension::Exec_A_AMOMAX() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOMAX"); logger->debug("{} ns. PC: 0x{:x}. A.AMOMAX");
return true; return true;
} }
bool A_extension::Exec_A_AMOMINU() const {
bool A_extension::Exec_A_AMOMINU() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -340,8 +347,9 @@ bool A_extension::Exec_A_AMOMINU() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOMINU"); logger->debug("{} ns. PC: 0x{:x}. A.AMOMINU");
return true; return true;
} }
bool A_extension::Exec_A_AMOMAXU() const {
bool A_extension::Exec_A_AMOMAXU() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t data; std::uint32_t data;
@ -371,22 +379,22 @@ bool A_extension::Exec_A_AMOMAXU() const {
logger->debug("{} ns. PC: 0x{:x}. A.AMOMAXU"); logger->debug("{} ns. PC: 0x{:x}. A.AMOMAXU");
return true; return true;
} }
void A_extension::TLB_reserve(std::uint32_t address) { void A_extension::TLB_reserve(std::uint32_t address) {
TLB_A_Entries.insert(address); TLB_A_Entries.insert(address);
} }
bool A_extension::TLB_reserved(std::uint32_t address) { bool A_extension::TLB_reserved(std::uint32_t address) {
if (TLB_A_Entries.count(address) == 1) { if (TLB_A_Entries.count(address) == 1) {
TLB_A_Entries.erase(address); TLB_A_Entries.erase(address);
return true; return true;
} else { } else {
return false; return false;
} }
} }
bool A_extension::process_instruction(Instruction &inst) { bool A_extension::process_instruction(Instruction &inst) {
bool PC_not_affected = true; bool PC_not_affected = true;
setInstr(inst.getInstr()); setInstr(inst.getInstr());
@ -433,4 +441,5 @@ bool A_extension::process_instruction(Instruction &inst) {
} }
return PC_not_affected; return PC_not_affected;
}
} }

View File

@ -11,7 +11,9 @@
#include "BASE_ISA.h" #include "BASE_ISA.h"
enum Codes { namespace riscv_tlm {
enum Codes {
LUI = 0b0110111, LUI = 0b0110111,
AUIPC = 0b0010111, AUIPC = 0b0010111,
JAL = 0b1101111, JAL = 0b1101111,
@ -83,9 +85,9 @@ enum Codes {
CSRRWI = 0b101, CSRRWI = 0b101,
CSRRSI = 0b110, CSRRSI = 0b110,
CSRRCI = 0b111, CSRRCI = 0b111,
}; };
bool BASE_ISA::Exec_LUI() const { bool BASE_ISA::Exec_LUI() const {
int rd; int rd;
std::uint32_t imm; std::uint32_t imm;
@ -97,9 +99,9 @@ bool BASE_ISA::Exec_LUI() const {
rd, imm); rd, imm);
return true; return true;
} }
bool BASE_ISA::Exec_AUIPC() const { bool BASE_ISA::Exec_AUIPC() const {
int rd; int rd;
std::uint32_t imm; std::uint32_t imm;
std::uint32_t new_pc; std::uint32_t new_pc;
@ -110,14 +112,15 @@ bool BASE_ISA::Exec_AUIPC() const {
regs->setValue(rd, new_pc); regs->setValue(rd, new_pc);
logger->debug("{} ns. PC: 0x{:x}. AUIPC: x{:d} <- 0x{:x} + PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. AUIPC: x{:d} <- 0x{:x} + PC (0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rd, imm, new_pc); rd, imm, new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_JAL() const { bool BASE_ISA::Exec_JAL() const {
int32_t mem_addr; std::int32_t mem_addr;
int rd; int rd;
std::uint32_t new_pc, old_pc; std::uint32_t new_pc, old_pc;
@ -131,13 +134,14 @@ bool BASE_ISA::Exec_JAL() const {
old_pc = old_pc + 4; old_pc = old_pc + 4;
regs->setValue(rd, old_pc); regs->setValue(rd, old_pc);
logger->debug("{} ns. PC: 0x{:x}. JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rd, old_pc, mem_addr, new_pc); rd, old_pc, mem_addr, new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_JALR() { bool BASE_ISA::Exec_JALR() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::uint32_t new_pc, old_pc; std::uint32_t new_pc, old_pc;
@ -151,9 +155,10 @@ bool BASE_ISA::Exec_JALR() {
new_pc = static_cast<std::uint32_t>((regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE); new_pc = static_cast<std::uint32_t>((regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE);
if( (new_pc & 0x00000003) != 0) { if ((new_pc & 0x00000003) != 0) {
// not aligned // not aligned
logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x} PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x} PC <- 0x{:x}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rd, old_pc + 4, new_pc); rd, old_pc + 4, new_pc);
logger->debug("{} ns. PC: 0x{:x}. JALR : Exception"); logger->debug("{} ns. PC: 0x{:x}. JALR : Exception");
@ -162,13 +167,14 @@ bool BASE_ISA::Exec_JALR() {
regs->setPC(new_pc); regs->setPC(new_pc);
} }
logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x}. PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x}. PC <- 0x{:x}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rd, old_pc + 4, new_pc); rd, old_pc + 4, new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BEQ() const { bool BASE_ISA::Exec_BEQ() const {
int rs1, rs2; int rs1, rs2;
std::uint32_t new_pc; std::uint32_t new_pc;
@ -183,13 +189,14 @@ bool BASE_ISA::Exec_BEQ() const {
new_pc = static_cast<std::uint32_t>(regs->getPC()); new_pc = static_cast<std::uint32_t>(regs->getPC());
} }
logger->debug("{} ns. PC: 0x{:x}. BEQ: x{:d}(0x{:x}) == x{:d}(0x{:x})? -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BEQ: x{:d}(0x{:x}) == x{:d}(0x{:x})? -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BNE() const { bool BASE_ISA::Exec_BNE() const {
int rs1, rs2; int rs1, rs2;
std::uint32_t new_pc; std::uint32_t new_pc;
std::uint32_t val1, val2; std::uint32_t val1, val2;
@ -208,60 +215,63 @@ bool BASE_ISA::Exec_BNE() const {
new_pc = static_cast<std::uint32_t>(regs->getPC()); new_pc = static_cast<std::uint32_t>(regs->getPC());
} }
logger->debug("{} ns. PC: 0x{:x}. BNE: x{:d}(0x{:x}) != x{:d}(0x{:x})? -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BNE: x{:d}(0x{:x}) != x{:d}(0x{:x})? -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, val1, rs2, val2, new_pc); rs1, val1, rs2, val2, new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BLT() const { bool BASE_ISA::Exec_BLT() const {
int rs1, rs2; int rs1, rs2;
std::uint32_t new_pc = 0; std::uint32_t new_pc = 0;
rs1 = get_rs1(); rs1 = get_rs1();
rs2 = get_rs2(); rs2 = get_rs2();
if ( static_cast<std::int32_t>(regs->getValue(rs1)) < static_cast<std::int32_t>(regs->getValue(rs2)) ) { if (static_cast<std::int32_t>(regs->getValue(rs1)) < static_cast<std::int32_t>(regs->getValue(rs2))) {
new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B()); new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B());
regs->setPC(new_pc); regs->setPC(new_pc);
} else { } else {
regs->incPC(); regs->incPC();
} }
logger->debug("{} ns. PC: 0x{:x}. BLT: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BLT: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BGE() const { bool BASE_ISA::Exec_BGE() const {
int rs1, rs2; int rs1, rs2;
std::uint32_t new_pc = 0; std::uint32_t new_pc = 0;
rs1 = get_rs1(); rs1 = get_rs1();
rs2 = get_rs2(); rs2 = get_rs2();
if ( static_cast<std::int32_t>(regs->getValue(rs1)) >= static_cast<std::int32_t>( regs->getValue(rs2)) ) { if (static_cast<std::int32_t>(regs->getValue(rs1)) >= static_cast<std::int32_t>( regs->getValue(rs2))) {
new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B()); new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B());
regs->setPC(new_pc); regs->setPC(new_pc);
} else { } else {
regs->incPC(); regs->incPC();
} }
logger->debug("{} ns. PC: 0x{:x}. BGE: x{:d}(0x{:x}) > x{:d}(0x{:x})? -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BGE: x{:d}(0x{:x}) > x{:d}(0x{:x})? -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BLTU() const { bool BASE_ISA::Exec_BLTU() const {
int rs1, rs2; int rs1, rs2;
std::uint32_t new_pc; std::uint32_t new_pc;
rs1 = get_rs1(); rs1 = get_rs1();
rs2 = get_rs2(); rs2 = get_rs2();
if ( static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(regs->getValue(rs2)) ) { if (static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(regs->getValue(rs2))) {
new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B()); new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B());
regs->setPC(new_pc); regs->setPC(new_pc);
} else { } else {
@ -269,37 +279,40 @@ bool BASE_ISA::Exec_BLTU() const {
new_pc = static_cast<std::uint32_t>(regs->getPC()); new_pc = static_cast<std::uint32_t>(regs->getPC());
} }
logger->debug("{} ns. PC: 0x{:x}. BLTU: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BLTU: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc);
return true; return true;
} }
bool BASE_ISA::Exec_BGEU() const { bool BASE_ISA::Exec_BGEU() const {
int rs1, rs2; int rs1, rs2;
rs1 = get_rs1(); rs1 = get_rs1();
rs2 = get_rs2(); rs2 = get_rs2();
if ( static_cast<std::uint32_t>(regs->getValue(rs1)) >= static_cast<std::uint32_t>(regs->getValue(rs2)) ) { if (static_cast<std::uint32_t>(regs->getValue(rs1)) >= static_cast<std::uint32_t>(regs->getValue(rs2))) {
std::uint32_t new_pc; std::uint32_t new_pc;
new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B()); new_pc = static_cast<std::uint32_t>(regs->getPC() + get_imm_B());
logger->debug("{} ns. PC: 0x{:x}. BGEU: x{:d}(0x{:x}) > x{:d}(0x{:x}) -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BGEU: x{:d}(0x{:x}) > x{:d}(0x{:x}) -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), new_pc);
regs->setPC(new_pc); regs->setPC(new_pc);
} else { } else {
logger->debug("{} ns. PC: 0x{:x}. BGEU: x{:d}(0x{:x}) > x{:d}(0x{:x}) -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. BGEU: x{:d}(0x{:x}) > x{:d}(0x{:x}) -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), regs->getPC() + 4); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), regs->getPC() + 4);
regs->incPC(); regs->incPC();
} }
return true; return true;
} }
bool BASE_ISA::Exec_LB() const { bool BASE_ISA::Exec_LB() const {
std::uint32_t mem_addr ; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::int8_t data; std::int8_t data;
@ -313,14 +326,15 @@ bool BASE_ISA::Exec_LB() const {
perf->dataMemoryRead(); perf->dataMemoryRead();
regs->setValue(rd, data); regs->setValue(rd, data);
logger->debug("{} ns. PC: 0x{:x}. LB: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. LB: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, mem_addr, rd); rs1, imm, mem_addr, rd);
return true; return true;
} }
bool BASE_ISA::Exec_LH() const { bool BASE_ISA::Exec_LH() const {
std::uint32_t mem_addr ; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
int16_t data; int16_t data;
@ -334,13 +348,14 @@ bool BASE_ISA::Exec_LH() const {
perf->dataMemoryRead(); perf->dataMemoryRead();
regs->setValue(rd, data); regs->setValue(rd, data);
logger->debug("{} ns. PC: 0x{:x}. LH: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. LH: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, mem_addr, rd); rs1, imm, mem_addr, rd);
return true; return true;
} }
bool BASE_ISA::Exec_LW() const { bool BASE_ISA::Exec_LW() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -355,13 +370,14 @@ bool BASE_ISA::Exec_LW() const {
perf->dataMemoryRead(); perf->dataMemoryRead();
regs->setValue(rd, static_cast<std::int32_t>(data)); regs->setValue(rd, static_cast<std::int32_t>(data));
logger->debug("{} ns. PC: 0x{:x}. LW: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. LW: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, mem_addr, rd); rs1, imm, mem_addr, rd);
return true; return true;
} }
bool BASE_ISA::Exec_LBU() const { bool BASE_ISA::Exec_LBU() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -376,13 +392,14 @@ bool BASE_ISA::Exec_LBU() const {
perf->dataMemoryRead(); perf->dataMemoryRead();
regs->setValue(rd, static_cast<std::int32_t>(data)); regs->setValue(rd, static_cast<std::int32_t>(data));
logger->debug("{} ns. PC: 0x{:x}. LBU: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. LBU: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, mem_addr, rd); rs1, imm, mem_addr, rd);
return true; return true;
} }
bool BASE_ISA::Exec_LHU() const { bool BASE_ISA::Exec_LHU() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -398,13 +415,14 @@ bool BASE_ISA::Exec_LHU() const {
regs->setValue(rd, data); regs->setValue(rd, data);
logger->debug("{} ns. PC: 0x{:x}. LHU: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. LHU: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, mem_addr, rd); rs1, imm, mem_addr, rd);
return true; return true;
} }
bool BASE_ISA::Exec_SB() const { bool BASE_ISA::Exec_SB() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1, rs2; int rs1, rs2;
std::int32_t imm; std::int32_t imm;
@ -420,13 +438,14 @@ bool BASE_ISA::Exec_SB() const {
mem_intf->writeDataMem(mem_addr, data, 1); mem_intf->writeDataMem(mem_addr, data, 1);
perf->dataMemoryWrite(); perf->dataMemoryWrite();
logger->debug("{} ns. PC: 0x{:x}. SB: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SB: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs2, rs1, imm, mem_addr); rs2, rs1, imm, mem_addr);
return true; return true;
} }
bool BASE_ISA::Exec_SH() const { bool BASE_ISA::Exec_SH() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1, rs2; int rs1, rs2;
std::int32_t imm; std::int32_t imm;
@ -442,13 +461,14 @@ bool BASE_ISA::Exec_SH() const {
mem_intf->writeDataMem(mem_addr, data, 2); mem_intf->writeDataMem(mem_addr, data, 2);
perf->dataMemoryWrite(); perf->dataMemoryWrite();
logger->debug("{} ns. PC: 0x{:x}. SH: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SH: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs2, rs1, imm, mem_addr); rs2, rs1, imm, mem_addr);
return true; return true;
} }
bool BASE_ISA::Exec_SW() const { bool BASE_ISA::Exec_SW() const {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1, rs2; int rs1, rs2;
std::int32_t imm; std::int32_t imm;
@ -464,13 +484,14 @@ bool BASE_ISA::Exec_SW() const {
mem_intf->writeDataMem(mem_addr, data, 4); mem_intf->writeDataMem(mem_addr, data, 4);
perf->dataMemoryWrite(); perf->dataMemoryWrite();
logger->debug("{} ns. PC: 0x{:x}. SW: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SW: x{:d} -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs2, rs1, imm, mem_addr); rs2, rs1, imm, mem_addr);
return true; return true;
} }
bool BASE_ISA::Exec_ADDI() const { bool BASE_ISA::Exec_ADDI() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::int32_t calc; std::int32_t calc;
@ -482,13 +503,14 @@ bool BASE_ISA::Exec_ADDI() const {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm; calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. ADDI: x{:d} + x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. ADDI: x{:d} + x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd, calc); rs1, imm, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SLTI() const { bool BASE_ISA::Exec_SLTI() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -499,18 +521,20 @@ bool BASE_ISA::Exec_SLTI() const {
if (static_cast<std::int32_t>(regs->getValue(rs1)) < imm) { if (static_cast<std::int32_t>(regs->getValue(rs1)) < imm) {
regs->setValue(rd, 1); regs->setValue(rd, 1);
logger->debug("{} ns. PC: 0x{:x}. SLTI: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTI: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
} else { } else {
regs->setValue(rd, 0); regs->setValue(rd, 0);
logger->debug("{} ns. PC: 0x{:x}. SLTI: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTI: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
} }
return true; return true;
} }
bool BASE_ISA::Exec_SLTIU() const { bool BASE_ISA::Exec_SLTIU() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -520,18 +544,20 @@ bool BASE_ISA::Exec_SLTIU() const {
if (static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(imm)) { if (static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(imm)) {
regs->setValue(rd, 1); regs->setValue(rd, 1);
logger->debug("{} ns. PC: 0x{:x}. SLTIU: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTIU: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
} else { } else {
regs->setValue(rd, 0); regs->setValue(rd, 0);
logger->debug("{} ns. PC: 0x{:x}. SLTIU: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTIU: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
} }
return true; return true;
} }
bool BASE_ISA::Exec_XORI() const { bool BASE_ISA::Exec_XORI() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::uint32_t calc; std::uint32_t calc;
@ -543,13 +569,14 @@ bool BASE_ISA::Exec_XORI() const {
calc = regs->getValue(rs1) ^ imm; calc = regs->getValue(rs1) ^ imm;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. XORI: x{:d} XOR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. XORI: x{:d} XOR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
return true; return true;
} }
bool BASE_ISA::Exec_ORI() const { bool BASE_ISA::Exec_ORI() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::uint32_t calc; std::uint32_t calc;
@ -561,13 +588,14 @@ bool BASE_ISA::Exec_ORI() const {
calc = regs->getValue(rs1) | imm; calc = regs->getValue(rs1) | imm;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. ORI: x{:d} OR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. ORI: x{:d} OR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, imm, rd); rs1, imm, rd);
return true; return true;
} }
bool BASE_ISA::Exec_ANDI() const { bool BASE_ISA::Exec_ANDI() const {
int rd, rs1; int rd, rs1;
std::uint32_t imm; std::uint32_t imm;
std::uint32_t calc; std::uint32_t calc;
@ -581,13 +609,14 @@ bool BASE_ISA::Exec_ANDI() const {
calc = aux & imm; calc = aux & imm;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. ANDI: x{:d}(0x{:x}) AND 0x{:x} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. ANDI: x{:d}(0x{:x}) AND 0x{:x} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, aux, imm, rd); rs1, aux, imm, rd);
return true; return true;
} }
bool BASE_ISA::Exec_SLLI() { bool BASE_ISA::Exec_SLLI() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -608,13 +637,14 @@ bool BASE_ISA::Exec_SLLI() {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. SLLI: x{:d} << {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLLI: x{:d} << {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SRLI() const { bool BASE_ISA::Exec_SRLI() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -628,13 +658,14 @@ bool BASE_ISA::Exec_SRLI() const {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. SRLI: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SRLI: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SRAI() const { bool BASE_ISA::Exec_SRAI() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::int32_t calc; std::int32_t calc;
@ -648,13 +679,14 @@ bool BASE_ISA::Exec_SRAI() const {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. SRAI: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SRAI: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_ADD() const { bool BASE_ISA::Exec_ADD() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
rd = get_rd(); rd = get_rd();
@ -665,13 +697,14 @@ bool BASE_ISA::Exec_ADD() const {
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. ADD: x{:d} + x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. ADD: x{:d} + x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SUB() const { bool BASE_ISA::Exec_SUB() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
rd = get_rd(); rd = get_rd();
@ -681,13 +714,14 @@ bool BASE_ISA::Exec_SUB() const {
calc = regs->getValue(rs1) - regs->getValue(rs2); calc = regs->getValue(rs1) - regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SLL() const { bool BASE_ISA::Exec_SLL() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -701,13 +735,14 @@ bool BASE_ISA::Exec_SLL() const {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. SLL: x{:d} << x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLL: x{:d} << x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SLT() const { bool BASE_ISA::Exec_SLT() const {
int rd, rs1, rs2; int rd, rs1, rs2;
rd = get_rd(); rd = get_rd();
@ -716,38 +751,42 @@ bool BASE_ISA::Exec_SLT() const {
if (regs->getValue(rs1) < regs->getValue(rs2)) { if (regs->getValue(rs1) < regs->getValue(rs2)) {
regs->setValue(rd, 1); regs->setValue(rd, 1);
logger->debug("{} ns. PC: 0x{:x}. SLT: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLT: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
} else { } else {
regs->setValue(rd, 0); regs->setValue(rd, 0);
logger->debug("{} ns. PC: 0x{:x}. SLT: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLT: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
} }
return true; return true;
} }
bool BASE_ISA::Exec_SLTU() const { bool BASE_ISA::Exec_SLTU() const {
int rd, rs1, rs2; int rd, rs1, rs2;
rd = get_rd(); rd = get_rd();
rs1 = get_rs1(); rs1 = get_rs1();
rs2 = get_rs2(); rs2 = get_rs2();
if ( static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(regs->getValue(rs2)) ) { if (static_cast<std::uint32_t>(regs->getValue(rs1)) < static_cast<std::uint32_t>(regs->getValue(rs2))) {
regs->setValue(rd, 1); regs->setValue(rd, 1);
logger->debug("{} ns. PC: 0x{:x}. SLTU: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTU: x{:d} < x{:d} => 1 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
} else { } else {
regs->setValue(rd, 0); regs->setValue(rd, 0);
logger->debug("{} ns. PC: 0x{:x}. SLTU: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SLTU: x{:d} < x{:d} => 0 -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
} }
return true; return true;
} }
bool BASE_ISA::Exec_XOR() const { bool BASE_ISA::Exec_XOR() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -758,13 +797,14 @@ bool BASE_ISA::Exec_XOR() const {
calc = regs->getValue(rs1) ^ regs->getValue(rs2); calc = regs->getValue(rs1) ^ regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. XOR: x{:d} XOR x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. XOR: x{:d} XOR x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SRL() const { bool BASE_ISA::Exec_SRL() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -778,13 +818,14 @@ bool BASE_ISA::Exec_SRL() const {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. SRL: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SRL: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_SRA() const { bool BASE_ISA::Exec_SRA() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::int32_t calc; std::int32_t calc;
@ -798,13 +839,14 @@ bool BASE_ISA::Exec_SRA() const {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. SRA: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. SRA: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_OR() const { bool BASE_ISA::Exec_OR() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -815,13 +857,14 @@ bool BASE_ISA::Exec_OR() const {
calc = regs->getValue(rs1) | regs->getValue(rs2); calc = regs->getValue(rs1) | regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. OR: x{:d} OR x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. OR: x{:d} OR x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_AND() const { bool BASE_ISA::Exec_AND() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -832,19 +875,20 @@ bool BASE_ISA::Exec_AND() const {
calc = regs->getValue(rs1) & regs->getValue(rs2); calc = regs->getValue(rs1) & regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. AND: x{:d} AND x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. AND: x{:d} AND x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool BASE_ISA::Exec_FENCE() const { bool BASE_ISA::Exec_FENCE() const {
logger->debug("{} ns. PC: 0x{:x}. FENCE"); logger->debug("{} ns. PC: 0x{:x}. FENCE");
return true; return true;
} }
bool BASE_ISA::Exec_ECALL() { bool BASE_ISA::Exec_ECALL() {
logger->debug("{} ns. PC: 0x{:x}. ECALL"); logger->debug("{} ns. PC: 0x{:x}. ECALL");
@ -867,9 +911,9 @@ bool BASE_ISA::Exec_ECALL() {
RaiseException(11, m_instr); RaiseException(11, m_instr);
#endif #endif
return true; return true;
} }
bool BASE_ISA::Exec_EBREAK() { bool BASE_ISA::Exec_EBREAK() {
logger->debug("{} ns. PC: 0x{:x}. EBREAK"); logger->debug("{} ns. PC: 0x{:x}. EBREAK");
std::cout << std::endl << "EBRAK Instruction called, dumping information" std::cout << std::endl << "EBRAK Instruction called, dumping information"
@ -881,9 +925,9 @@ bool BASE_ISA::Exec_EBREAK() {
RaiseException(11, m_instr); RaiseException(11, m_instr);
return false; return false;
} }
bool BASE_ISA::Exec_CSRRW() const { bool BASE_ISA::Exec_CSRRW() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t aux; std::uint32_t aux;
@ -901,13 +945,14 @@ bool BASE_ISA::Exec_CSRRW() const {
aux = regs->getValue(rs1); aux = regs->getValue(rs1);
regs->setCSR(csr, aux); regs->setCSR(csr, aux);
logger->debug("{} ns. PC: 0x{:x}. CSRRW: CSR #{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRW: CSR #{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
csr, rd, aux); csr, rd, aux);
return true; return true;
} }
bool BASE_ISA::Exec_CSRRS() const { bool BASE_ISA::Exec_CSRRS() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t bitmask, aux, aux2; std::uint32_t bitmask, aux, aux2;
@ -930,13 +975,14 @@ bool BASE_ISA::Exec_CSRRS() const {
aux2 = aux | bitmask; aux2 = aux | bitmask;
regs->setCSR(csr, aux2); regs->setCSR(csr, aux2);
logger->debug("{} ns. PC: 0x{:x}. CSRRS: CSR #{:d}(0x{:x}) -> x{:d}(0x{:x}) & CSR #{:d} <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRS: CSR #{:d}(0x{:x}) -> x{:d}(0x{:x}) & CSR #{:d} <- 0x{:x}",
sc_core::sc_time_stamp().value(), regs->getPC(),
csr, aux, rd, rs1, csr, aux2); csr, aux, rd, rs1, csr, aux2);
return true; return true;
} }
bool BASE_ISA::Exec_CSRRC() const { bool BASE_ISA::Exec_CSRRC() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t bitmask, aux, aux2; std::uint32_t bitmask, aux, aux2;
@ -959,13 +1005,14 @@ bool BASE_ISA::Exec_CSRRC() const {
aux2 = aux & ~bitmask; aux2 = aux & ~bitmask;
regs->setCSR(csr, aux2); regs->setCSR(csr, aux2);
logger->debug("{} ns. PC: 0x{:x}. CSRRC: CSR #{:d}(0x{:x}) -> x{:d}(0x{:x}) & CSR #{:d} <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRC: CSR #{:d}(0x{:x}) -> x{:d}(0x{:x}) & CSR #{:d} <- 0x{:x}",
sc_core::sc_time_stamp().value(), regs->getPC(),
csr, aux, rd, rs1, csr, aux2); csr, aux, rd, rs1, csr, aux2);
return true; return true;
} }
bool BASE_ISA::Exec_CSRRWI() const { bool BASE_ISA::Exec_CSRRWI() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t aux; std::uint32_t aux;
@ -982,13 +1029,14 @@ bool BASE_ISA::Exec_CSRRWI() const {
aux = rs1; aux = rs1;
regs->setCSR(csr, aux); regs->setCSR(csr, aux);
logger->debug("{} ns. PC: 0x{:x}. CSRRWI: CSR #{:d} -> x{:d}. x{:d} -> CSR #{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRWI: CSR #{:d} -> x{:d}. x{:d} -> CSR #{:d}",
sc_core::sc_time_stamp().value(), regs->getPC(),
csr, rd, rs1, csr); csr, rd, rs1, csr);
return true; return true;
} }
bool BASE_ISA::Exec_CSRRSI() const { bool BASE_ISA::Exec_CSRRSI() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t bitmask, aux; std::uint32_t bitmask, aux;
@ -1009,13 +1057,14 @@ bool BASE_ISA::Exec_CSRRSI() const {
aux = aux | bitmask; aux = aux | bitmask;
regs->setCSR(csr, aux); regs->setCSR(csr, aux);
logger->debug("{} ns. PC: 0x{:x}. CSRRSI: CSR #{:d} -> x{:d}. x{:d} & CSR #{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRSI: CSR #{:d} -> x{:d}. x{:d} & CSR #{:d}(0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
csr, rd, rs1, csr, aux); csr, rd, rs1, csr, aux);
return true; return true;
} }
bool BASE_ISA::Exec_CSRRCI() const { bool BASE_ISA::Exec_CSRRCI() const {
int rd, rs1; int rd, rs1;
int csr; int csr;
std::uint32_t bitmask, aux; std::uint32_t bitmask, aux;
@ -1036,15 +1085,16 @@ bool BASE_ISA::Exec_CSRRCI() const {
aux = aux & ~bitmask; aux = aux & ~bitmask;
regs->setCSR(csr, aux); regs->setCSR(csr, aux);
logger->debug("{} ns. PC: 0x{:x}. CSRRCI: CSR #{:d} -> x{:d}. x{:d} & CSR #{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. CSRRCI: CSR #{:d} -> x{:d}. x{:d} & CSR #{:d}(0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
csr, rd, rs1, csr, aux); csr, rd, rs1, csr, aux);
return true; return true;
} }
/*********************** Privileged Instructions ******************************/ /*********************** Privileged Instructions ******************************/
bool BASE_ISA::Exec_MRET() const { bool BASE_ISA::Exec_MRET() const {
std::uint32_t new_pc = 0; std::uint32_t new_pc = 0;
new_pc = regs->getCSR(CSR_MEPC); new_pc = regs->getCSR(CSR_MEPC);
@ -1062,9 +1112,9 @@ bool BASE_ISA::Exec_MRET() const {
regs->setCSR(CSR_MSTATUS, csr_temp); regs->setCSR(CSR_MSTATUS, csr_temp);
return true; return true;
} }
bool BASE_ISA::Exec_SRET() const { bool BASE_ISA::Exec_SRET() const {
std::uint32_t new_pc = 0; std::uint32_t new_pc = 0;
new_pc = regs->getCSR(CSR_SEPC); new_pc = regs->getCSR(CSR_SEPC);
@ -1072,19 +1122,19 @@ bool BASE_ISA::Exec_SRET() const {
logger->debug("{} ns. PC: 0x{:x}. SRET: PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC()); logger->debug("{} ns. PC: 0x{:x}. SRET: PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC());
return true; return true;
} }
bool BASE_ISA::Exec_WFI() const { bool BASE_ISA::Exec_WFI() const {
logger->debug("{} ns. PC: 0x{:x}. WFI"); logger->debug("{} ns. PC: 0x{:x}. WFI");
return true; return true;
} }
bool BASE_ISA::Exec_SFENCE() const { bool BASE_ISA::Exec_SFENCE() const {
logger->debug("{} ns. PC: 0x{:x}. SFENCE"); logger->debug("{} ns. PC: 0x{:x}. SFENCE");
return true; return true;
} }
bool BASE_ISA::process_instruction(Instruction &inst, bool *breakpoint) { bool BASE_ISA::process_instruction(Instruction &inst, bool *breakpoint) {
bool PC_not_affected = true; bool PC_not_affected = true;
*breakpoint = false; *breakpoint = false;
@ -1263,9 +1313,9 @@ bool BASE_ISA::process_instruction(Instruction &inst, bool *breakpoint) {
} }
return PC_not_affected; return PC_not_affected;
} }
opCodes BASE_ISA::decode() { opCodes BASE_ISA::decode() {
switch (opcode()) { switch (opcode()) {
case LUI: case LUI:
return OP_LUI; return OP_LUI;
@ -1429,4 +1479,5 @@ opCodes BASE_ISA::decode() {
} }
return OP_ERROR; return OP_ERROR;
}
} }

View File

@ -8,8 +8,11 @@
#include "BusCtrl.h" #include "BusCtrl.h"
SC_HAS_PROCESS(BusCtrl); namespace riscv_tlm {
BusCtrl::BusCtrl(sc_core::sc_module_name const &name) :
SC_HAS_PROCESS(BusCtrl);
BusCtrl::BusCtrl(sc_core::sc_module_name const &name) :
sc_module(name), cpu_instr_socket("cpu_instr_socket"), cpu_data_socket( sc_module(name), cpu_instr_socket("cpu_instr_socket"), cpu_data_socket(
"cpu_data_socket"), memory_socket("memory_socket"), trace_socket( "cpu_data_socket"), memory_socket("memory_socket"), trace_socket(
"trace_socket") { "trace_socket") {
@ -20,9 +23,9 @@ BusCtrl::BusCtrl(sc_core::sc_module_name const &name) :
&BusCtrl::instr_direct_mem_ptr); &BusCtrl::instr_direct_mem_ptr);
memory_socket.register_invalidate_direct_mem_ptr(this, memory_socket.register_invalidate_direct_mem_ptr(this,
&BusCtrl::invalidate_direct_mem_ptr); &BusCtrl::invalidate_direct_mem_ptr);
} }
void BusCtrl::b_transport(tlm::tlm_generic_payload &trans, void BusCtrl::b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay) { sc_core::sc_time &delay) {
sc_dt::uint64 adr = trans.get_address() / 4; sc_dt::uint64 adr = trans.get_address() / 4;
@ -57,15 +60,15 @@ void BusCtrl::b_transport(tlm::tlm_generic_payload &trans,
#endif #endif
trans.set_response_status(tlm::TLM_OK_RESPONSE); trans.set_response_status(tlm::TLM_OK_RESPONSE);
} }
bool BusCtrl::instr_direct_mem_ptr(tlm::tlm_generic_payload &gp, bool BusCtrl::instr_direct_mem_ptr(tlm::tlm_generic_payload &gp,
tlm::tlm_dmi &dmi_data) { tlm::tlm_dmi &dmi_data) {
return memory_socket->get_direct_mem_ptr(gp, dmi_data); return memory_socket->get_direct_mem_ptr(gp, dmi_data);
} }
void BusCtrl::invalidate_direct_mem_ptr(sc_dt::uint64 start, void BusCtrl::invalidate_direct_mem_ptr(sc_dt::uint64 start,
sc_dt::uint64 end) { sc_dt::uint64 end) {
cpu_instr_socket->invalidate_direct_mem_ptr(start, end); cpu_instr_socket->invalidate_direct_mem_ptr(start, end);
}
} }

View File

@ -7,8 +7,11 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#include "CPU.h" #include "CPU.h"
SC_HAS_PROCESS(CPU); namespace riscv_tlm {
CPU::CPU(sc_core::sc_module_name const &name, std::uint32_t PC, bool debug) :
SC_HAS_PROCESS(CPU);
CPU::CPU(sc_core::sc_module_name const &name, std::uint32_t PC, bool debug) :
sc_module(name), instr_bus("instr_bus"), inst(0), default_time(10, sc_module(name), instr_bus("instr_bus"), inst(0), default_time(10,
sc_core::SC_NS), INSTR(0) { sc_core::SC_NS), INSTR(0) {
register_bank = new Registers(); register_bank = new Registers();
@ -38,7 +41,7 @@ CPU::CPU(sc_core::sc_module_name const &name, std::uint32_t PC, bool debug) :
m_qk->reset(); m_qk->reset();
trans.set_command(tlm::TLM_READ_COMMAND); trans.set_command(tlm::TLM_READ_COMMAND);
trans.set_data_ptr(reinterpret_cast<unsigned char*>(&INSTR)); trans.set_data_ptr(reinterpret_cast<unsigned char *>(&INSTR));
trans.set_data_length(4); trans.set_data_length(4);
trans.set_streaming_width(4); // = data_length to indicate no streaming trans.set_streaming_width(4); // = data_length to indicate no streaming
trans.set_byte_enable_ptr(nullptr); // 0 indicates unused trans.set_byte_enable_ptr(nullptr); // 0 indicates unused
@ -50,9 +53,9 @@ CPU::CPU(sc_core::sc_module_name const &name, std::uint32_t PC, bool debug) :
} }
logger = spdlog::get("my_logger"); logger = spdlog::get("my_logger");
} }
CPU::~CPU() { CPU::~CPU() {
delete register_bank; delete register_bank;
delete mem_intf; delete mem_intf;
delete exec; delete exec;
@ -60,16 +63,17 @@ CPU::~CPU() {
delete m_inst; delete m_inst;
delete a_inst; delete a_inst;
delete m_qk; delete m_qk;
} }
bool CPU::cpu_process_IRQ() { bool CPU::cpu_process_IRQ() {
std::uint32_t csr_temp; std::uint32_t csr_temp;
bool ret_value = false; bool ret_value = false;
if (interrupt) { if (interrupt) {
csr_temp = register_bank->getCSR(CSR_MSTATUS); csr_temp = register_bank->getCSR(CSR_MSTATUS);
if ((csr_temp & MSTATUS_MIE) == 0) { if ((csr_temp & MSTATUS_MIE) == 0) {
logger->debug("{} ns. PC: 0x{:x}. Interrupt delayed", sc_core::sc_time_stamp().value(), register_bank->getPC()); logger->debug("{} ns. PC: 0x{:x}. Interrupt delayed", sc_core::sc_time_stamp().value(),
register_bank->getPC());
return ret_value; return ret_value;
} }
@ -80,14 +84,16 @@ bool CPU::cpu_process_IRQ() {
csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit) csr_temp |= MIP_MEIP; // MEIP bit in MIP register (11th bit)
register_bank->setCSR(CSR_MIP, csr_temp); register_bank->setCSR(CSR_MIP, csr_temp);
logger->debug("{} ns. PC: 0x{:x}. Interrupt!", sc_core::sc_time_stamp().value(), register_bank->getPC()); logger->debug("{} ns. PC: 0x{:x}. Interrupt!", sc_core::sc_time_stamp().value(),
register_bank->getPC());
/* updated MEPC register */ /* updated MEPC register */
std::uint32_t old_pc = register_bank->getPC(); std::uint32_t old_pc = register_bank->getPC();
register_bank->setCSR(CSR_MEPC, old_pc); register_bank->setCSR(CSR_MEPC, old_pc);
logger->debug("{} ns. PC: 0x{:x}. Old PC Value 0x{:x}", sc_core::sc_time_stamp().value(), register_bank->getPC(), logger->debug("{} ns. PC: 0x{:x}. Old PC Value 0x{:x}", sc_core::sc_time_stamp().value(),
register_bank->getPC(),
old_pc); old_pc);
/* update MCAUSE register */ /* update MCAUSE register */
@ -96,7 +102,8 @@ bool CPU::cpu_process_IRQ() {
/* set new PC address */ /* set new PC address */
std::uint32_t new_pc = register_bank->getCSR(CSR_MTVEC); std::uint32_t new_pc = register_bank->getCSR(CSR_MTVEC);
//new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0 //new_pc = new_pc & 0xFFFFFFFC; // last two bits always to 0
logger->debug("{} ns. PC: 0x{:x}. NEW PC Value 0x{:x}", sc_core::sc_time_stamp().value(), register_bank->getPC(), logger->debug("{} ns. PC: 0x{:x}. NEW PC Value 0x{:x}", sc_core::sc_time_stamp().value(),
register_bank->getPC(),
new_pc); new_pc);
register_bank->setPC(new_pc); register_bank->setPC(new_pc);
@ -114,9 +121,9 @@ bool CPU::cpu_process_IRQ() {
} }
return ret_value; return ret_value;
} }
bool CPU::CPU_step() { bool CPU::CPU_step() {
bool PC_not_affected = false; bool PC_not_affected = false;
/* Get new PC value */ /* Get new PC value */
@ -185,9 +192,9 @@ bool CPU::CPU_step() {
perf->instructionsInc(); perf->instructionsInc();
return breakpoint; return breakpoint;
} }
[[noreturn]] void CPU::CPU_thread() { [[noreturn]] void CPU::CPU_thread() {
sc_core::sc_time instr_time = default_time; sc_core::sc_time instr_time = default_time;
@ -211,18 +218,19 @@ bool CPU::CPU_step() {
sc_core::wait(instr_time); sc_core::wait(instr_time);
#endif #endif
} // while(1) } // while(1)
} // CPU_thread } // CPU_thread
void CPU::call_interrupt(tlm::tlm_generic_payload &m_trans, void CPU::call_interrupt(tlm::tlm_generic_payload &m_trans,
sc_core::sc_time &delay) { sc_core::sc_time &delay) {
interrupt = true; interrupt = true;
/* Socket caller send a cause (its id) */ /* Socket caller send a cause (its id) */
memcpy(&int_cause, m_trans.get_data_ptr(), sizeof(std::uint32_t)); memcpy(&int_cause, m_trans.get_data_ptr(), sizeof(std::uint32_t));
delay = sc_core::SC_ZERO_TIME; delay = sc_core::SC_ZERO_TIME;
} }
void CPU::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) { void CPU::invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end) {
(void) start; (void) start;
(void) end; (void) end;
dmi_ptr_valid = false; dmi_ptr_valid = false;
}
} }

View File

@ -6,7 +6,9 @@
*/ */
#include "C_extension.h" #include "C_extension.h"
op_C_Codes C_extension::decode() const { namespace riscv_tlm {
op_C_Codes C_extension::decode() const {
switch (opcode()) { switch (opcode()) {
@ -131,7 +133,8 @@ op_C_Codes C_extension::decode() const {
return OP_C_SWSP; return OP_C_SWSP;
break; break;
case C_FWWSP: case C_FWWSP:
[[unlikely]] default: [[unlikely]]
default:
return OP_C_ERROR; return OP_C_ERROR;
break; break;
} }
@ -143,9 +146,9 @@ op_C_Codes C_extension::decode() const {
break; break;
} }
return OP_C_ERROR; return OP_C_ERROR;
} }
bool C_extension::Exec_C_JR() { bool C_extension::Exec_C_JR() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1; int rs1;
int new_pc; int new_pc;
@ -153,16 +156,17 @@ bool C_extension::Exec_C_JR() {
rs1 = get_rs1(); rs1 = get_rs1();
mem_addr = 0; mem_addr = 0;
new_pc = static_cast<std::int32_t>(static_cast<std::int32_t>((regs->getValue(rs1)) + static_cast<std::int32_t>(mem_addr)) & 0xFFFFFFFE); new_pc = static_cast<std::int32_t>(
static_cast<std::int32_t>((regs->getValue(rs1)) + static_cast<std::int32_t>(mem_addr)) & 0xFFFFFFFE);
logger->debug("{} ns. PC: 0x{:x}. C.JR: PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), new_pc); logger->debug("{} ns. PC: 0x{:x}. C.JR: PC <- 0x{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), new_pc);
regs->setPC(new_pc); regs->setPC(new_pc);
return true; return true;
} }
bool C_extension::Exec_C_MV() { bool C_extension::Exec_C_MV() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -173,13 +177,14 @@ bool C_extension::Exec_C_MV() {
calc = regs->getValue(rs1) + regs->getValue(rs2); calc = regs->getValue(rs1) + regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.MV: x{:d}(0x{:x}) + x{:d}(0x{:x}) -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.MV: x{:d}(0x{:x}) + x{:d}(0x{:x}) -> x{:d}(0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), rd, calc); rs1, regs->getValue(rs1), rs2, regs->getValue(rs2), rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_ADD() { bool C_extension::Exec_C_ADD() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -190,13 +195,14 @@ bool C_extension::Exec_C_ADD() {
calc = regs->getValue(rs1) + regs->getValue(rs2); calc = regs->getValue(rs1) + regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.ADD: x{:d} + x{} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.ADD: x{:d} + x{} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_LWSP() { bool C_extension::Exec_C_LWSP() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -215,13 +221,14 @@ bool C_extension::Exec_C_LWSP() {
regs->setValue(rd, data); regs->setValue(rd, data);
logger->debug("{} ns. PC: 0x{:x}. C.LWSP: x{:d} + {:d}(@0x{:x}) -> x{:d}({:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.LWSP: x{:d} + {:d}(@0x{:x}) -> x{:d}({:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, imm, mem_addr, rd, data); rs1, imm, mem_addr, rd, data);
return true; return true;
} }
bool C_extension::Exec_C_ADDI4SPN() { bool C_extension::Exec_C_ADDI4SPN() {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::int32_t calc; std::int32_t calc;
@ -238,13 +245,14 @@ bool C_extension::Exec_C_ADDI4SPN() {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm; calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. C.ADDI4SN: x{:d} + (0x{:x}) + {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.ADDI4SN: x{:d} + (0x{:x}) + {:d} -> x{:d}(0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), imm, rd, calc); rs1, regs->getValue(rs1), imm, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_ADDI16SP() { bool C_extension::Exec_C_ADDI16SP() {
// addi x2, x2, nzimm[9:4] // addi x2, x2, nzimm[9:4]
int rd; int rd;
std::int32_t imm; std::int32_t imm;
@ -260,7 +268,8 @@ bool C_extension::Exec_C_ADDI16SP() {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm; calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. C.ADDI16SP: x{:d} + {:d} -> x{:d} (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.ADDI16SP: x{:d} + {:d} -> x{:d} (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, imm, rd, calc); rs1, imm, rd, calc);
} else { } else {
/* C.LUI OPCODE */ /* C.LUI OPCODE */
@ -273,9 +282,9 @@ bool C_extension::Exec_C_ADDI16SP() {
} }
return true; return true;
} }
bool C_extension::Exec_C_SWSP() { bool C_extension::Exec_C_SWSP() {
// sw rs2, offset(x2) // sw rs2, offset(x2)
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1, rs2; int rs1, rs2;
@ -292,13 +301,14 @@ bool C_extension::Exec_C_SWSP() {
mem_intf->writeDataMem(mem_addr, data, 4); mem_intf->writeDataMem(mem_addr, data, 4);
perf->dataMemoryWrite(); perf->dataMemoryWrite();
logger->debug("{} ns. PC: 0x{:x}. C.SWSP: x{:d}(0x{:x}) -> x{:d} + {} (@0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SWSP: x{:d}(0x{:x}) -> x{:d} + {} (@0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs2, data, rs1, imm, mem_addr); rs2, data, rs1, imm, mem_addr);
return true; return true;
} }
bool C_extension::Exec_C_BEQZ() { bool C_extension::Exec_C_BEQZ() {
int rs1; int rs1;
int new_pc; int new_pc;
std::uint32_t val1; std::uint32_t val1;
@ -314,13 +324,14 @@ bool C_extension::Exec_C_BEQZ() {
new_pc = static_cast<std::int32_t>(regs->getPC()); new_pc = static_cast<std::int32_t>(regs->getPC());
} }
logger->debug("{} ns. PC: 0x{:x}. C.BEQZ: x{:d}(0x{:x}) == 0? -> PC (0xx{:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.BEQZ: x{:d}(0x{:x}) == 0? -> PC (0xx{:d})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, val1, new_pc); rs1, val1, new_pc);
return true; return true;
} }
bool C_extension::Exec_C_BNEZ() { bool C_extension::Exec_C_BNEZ() {
int rs1; int rs1;
int new_pc; int new_pc;
std::uint32_t val1; std::uint32_t val1;
@ -336,13 +347,14 @@ bool C_extension::Exec_C_BNEZ() {
new_pc = static_cast<std::int32_t>(regs->getPC()); new_pc = static_cast<std::int32_t>(regs->getPC());
} }
logger->debug("{} ns. PC: 0x{:x}. C.BNEZ: x{:d}(0x{:x}) != 0? -> PC (0xx{:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.BNEZ: x{:d}(0x{:x}) != 0? -> PC (0xx{:d})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, val1, new_pc); rs1, val1, new_pc);
return true; return true;
} }
bool C_extension::Exec_C_LI() { bool C_extension::Exec_C_LI() {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::int32_t calc; std::int32_t calc;
@ -354,13 +366,14 @@ bool C_extension::Exec_C_LI() {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm; calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. C.LI: x{:d} ({:d}) + {:d} -> x{:d}(0x{:x}) ", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.LI: x{:d} ({:d}) + {:d} -> x{:d}(0x{:x}) ",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), imm, rd, calc); rs1, regs->getValue(rs1), imm, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_SRLI() { bool C_extension::Exec_C_SRLI() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -374,13 +387,14 @@ bool C_extension::Exec_C_SRLI() {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.SRLI: x{:d} >> {} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SRLI: x{:d} >> {} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd); rs1, shift, rd);
return true; return true;
} }
bool C_extension::Exec_C_SRAI() { bool C_extension::Exec_C_SRAI() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::int32_t calc; std::int32_t calc;
@ -394,13 +408,14 @@ bool C_extension::Exec_C_SRAI() {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift; calc = static_cast<std::int32_t>(regs->getValue(rs1)) >> shift;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. C.SRAI: x{:d} >> {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SRAI: x{:d} >> {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_SLLI() { bool C_extension::Exec_C_SLLI() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t shift; std::uint32_t shift;
std::uint32_t calc; std::uint32_t calc;
@ -414,13 +429,14 @@ bool C_extension::Exec_C_SLLI() {
calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift; calc = static_cast<std::uint32_t>(regs->getValue(rs1)) << shift;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.SLLI: x{:d} << {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SLLI: x{:d} << {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, shift, rd, calc); rs1, shift, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_ANDI() { bool C_extension::Exec_C_ANDI() {
int rd, rs1; int rd, rs1;
std::uint32_t imm; std::uint32_t imm;
std::uint32_t aux; std::uint32_t aux;
@ -434,13 +450,14 @@ bool C_extension::Exec_C_ANDI() {
calc = aux & imm; calc = aux & imm;
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.ANDI: x{:d}(0x{:x}) AND 0x{:x} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.ANDI: x{:d}(0x{:x}) AND 0x{:x} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, aux, imm, rd); rs1, aux, imm, rd);
return true; return true;
} }
bool C_extension::Exec_C_SUB() { bool C_extension::Exec_C_SUB() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -451,13 +468,14 @@ bool C_extension::Exec_C_SUB() {
calc = regs->getValue(rs1) - regs->getValue(rs2); calc = regs->getValue(rs1) - regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, calc); rs1, rs2, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_XOR() { bool C_extension::Exec_C_XOR() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -468,13 +486,14 @@ bool C_extension::Exec_C_XOR() {
calc = regs->getValue(rs1) ^ regs->getValue(rs2); calc = regs->getValue(rs1) ^ regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.XOR: x{:d} XOR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.XOR: x{:d} XOR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
return true; return true;
} }
bool C_extension::Exec_C_OR() { bool C_extension::Exec_C_OR() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -485,13 +504,14 @@ bool C_extension::Exec_C_OR() {
calc = regs->getValue(rs1) | regs->getValue(rs2); calc = regs->getValue(rs1) | regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.OR: x{:d} OR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.OR: x{:d} OR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
return true; return true;
} }
bool C_extension::Exec_C_AND() { bool C_extension::Exec_C_AND() {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t calc; std::uint32_t calc;
@ -502,13 +522,14 @@ bool C_extension::Exec_C_AND() {
calc = regs->getValue(rs1) & regs->getValue(rs2); calc = regs->getValue(rs1) & regs->getValue(rs2);
regs->setValue(rd, static_cast<std::int32_t>(calc)); regs->setValue(rd, static_cast<std::int32_t>(calc));
logger->debug("{} ns. PC: 0x{:x}. C.AND: x{:d} AND x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.AND: x{:d} AND x{:d} -> x{:d}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd); rs1, rs2, rd);
return true; return true;
} }
bool C_extension::Exec_C_ADDI() const { bool C_extension::Exec_C_ADDI() const {
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
std::int32_t calc; std::int32_t calc;
@ -520,12 +541,13 @@ bool C_extension::Exec_C_ADDI() const {
calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm; calc = static_cast<std::int32_t>(regs->getValue(rs1)) + imm;
regs->setValue(rd, calc); regs->setValue(rd, calc);
logger->debug("{} ns. PC: 0x{:x}. C.ADDI: x{:d} + {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), rs1, imm, rd, calc); logger->debug("{} ns. PC: 0x{:x}. C.ADDI: x{:d} + {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(),
regs->getPC(), rs1, imm, rd, calc);
return true; return true;
} }
bool C_extension::Exec_C_JALR() { bool C_extension::Exec_C_JALR() {
std::uint32_t mem_addr = 0; std::uint32_t mem_addr = 0;
int rd, rs1; int rd, rs1;
int new_pc, old_pc; int new_pc, old_pc;
@ -539,13 +561,14 @@ bool C_extension::Exec_C_JALR() {
new_pc = static_cast<std::int32_t>((regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE); new_pc = static_cast<std::int32_t>((regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE);
regs->setPC(new_pc); regs->setPC(new_pc);
logger->debug("{} ns. PC: 0x{:x}. C.JALR: x{:d} <- 0x{:x} PC <- 0xx{:x}", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.JALR: x{:d} <- 0x{:x} PC <- 0xx{:x}", sc_core::sc_time_stamp().value(),
regs->getPC(),
rd, old_pc + 4, new_pc); rd, old_pc + 4, new_pc);
return true; return true;
} }
bool C_extension::Exec_C_LW() { bool C_extension::Exec_C_LW() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rd, rs1; int rd, rs1;
std::int32_t imm; std::int32_t imm;
@ -560,13 +583,14 @@ bool C_extension::Exec_C_LW() {
perf->dataMemoryRead(); perf->dataMemoryRead();
regs->setValue(rd, static_cast<std::int32_t>(data)); regs->setValue(rd, static_cast<std::int32_t>(data));
logger->debug("{} ns. PC: 0x{:x}. C.LW: x{:d}(0x{:x}) + {:d} (@0x{:x}) -> {:d} (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.LW: x{:d}(0x{:x}) + {:d} (@0x{:x}) -> {:d} (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs1, regs->getValue(rs1), imm, mem_addr, rd, data); rs1, regs->getValue(rs1), imm, mem_addr, rd, data);
return true; return true;
} }
bool C_extension::Exec_C_SW() { bool C_extension::Exec_C_SW() {
std::uint32_t mem_addr; std::uint32_t mem_addr;
int rs1, rs2; int rs1, rs2;
std::int32_t imm; std::int32_t imm;
@ -582,13 +606,14 @@ bool C_extension::Exec_C_SW() {
mem_intf->writeDataMem(mem_addr, data, 4); mem_intf->writeDataMem(mem_addr, data, 4);
perf->dataMemoryWrite(); perf->dataMemoryWrite();
logger->debug("{} ns. PC: 0x{:x}. C.SW: x{:d}(0x{:x}) -> x{:d} + 0x{:x}(@0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.SW: x{:d}(0x{:x}) -> x{:d} + 0x{:x}(@0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rs2, data, rs1, imm, mem_addr); rs2, data, rs1, imm, mem_addr);
return true; return true;
} }
bool C_extension::Exec_C_JAL(int m_rd) { bool C_extension::Exec_C_JAL(int m_rd) {
std::int32_t mem_addr; std::int32_t mem_addr;
int rd; int rd;
int new_pc, old_pc; int new_pc, old_pc;
@ -603,13 +628,14 @@ bool C_extension::Exec_C_JAL(int m_rd) {
old_pc = old_pc + 2; old_pc = old_pc + 2;
regs->setValue(rd, old_pc); regs->setValue(rd, old_pc);
logger->debug("{} ns. PC: 0x{:x}. C.JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. C.JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})",
sc_core::sc_time_stamp().value(), regs->getPC(),
rd, old_pc, mem_addr, new_pc); rd, old_pc, mem_addr, new_pc);
return true; return true;
} }
bool C_extension::Exec_C_EBREAK() { bool C_extension::Exec_C_EBREAK() {
logger->debug("C.EBREAK"); logger->debug("C.EBREAK");
std::cout << "\n" << "C.EBRAK Instruction called, dumping information" std::cout << "\n" << "C.EBRAK Instruction called, dumping information"
@ -621,9 +647,9 @@ bool C_extension::Exec_C_EBREAK() {
sc_core::sc_stop(); sc_core::sc_stop();
return true; return true;
} }
bool C_extension::process_instruction(Instruction &inst, bool *breakpoint) { bool C_extension::process_instruction(Instruction &inst, bool *breakpoint) {
bool PC_not_affected = true; bool PC_not_affected = true;
*breakpoint = false; *breakpoint = false;
@ -722,4 +748,6 @@ bool C_extension::process_instruction(Instruction &inst, bool *breakpoint) {
} }
return PC_not_affected; return PC_not_affected;
}
} }

View File

@ -18,10 +18,12 @@
#include "Debug.h" #include "Debug.h"
constexpr char nibble_to_hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', namespace riscv_tlm {
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
Debug::Debug(CPU *cpu, Memory* mem): sc_module(sc_core::sc_module_name("Debug")) { constexpr char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
Debug::Debug(riscv_tlm::CPU *cpu, Memory *mem) : sc_module(sc_core::sc_module_name("Debug")) {
dbg_cpu = cpu; dbg_cpu = cpu;
dbg_mem = mem; dbg_mem = mem;
@ -43,21 +45,21 @@ Debug::Debug(CPU *cpu, Memory* mem): sc_module(sc_core::sc_module_name("Debug"))
conn = accept(sock, (struct sockaddr *) &addr, &len); conn = accept(sock, (struct sockaddr *) &addr, &len);
handle_gdb_loop(); handle_gdb_loop();
} }
Debug::~Debug() { Debug::~Debug() {
} }
void Debug::send_packet(int conn, const std::string &msg) { void Debug::send_packet(int conn, const std::string &msg) {
std::string frame = "+$" + msg + "#" + compute_checksum_string(msg); std::string frame = "+$" + msg + "#" + compute_checksum_string(msg);
memcpy(iobuf, frame.c_str(), frame.size()); memcpy(iobuf, frame.c_str(), frame.size());
::send(conn, iobuf, frame.size(), 0); ::send(conn, iobuf, frame.size(), 0);
} }
std::string Debug::receive_packet() { std::string Debug::receive_packet() {
int nbytes = ::recv(conn, iobuf, bufsize, 0); int nbytes = ::recv(conn, iobuf, bufsize, 0);
if (nbytes == 0) { if (nbytes == 0) {
@ -72,9 +74,9 @@ std::string Debug::receive_packet() {
return message; return message;
} }
} }
void Debug::handle_gdb_loop() { void Debug::handle_gdb_loop() {
std::cout << "Handle_GDB_Loop\n"; std::cout << "Handle_GDB_Loop\n";
Registers *register_bank = dbg_cpu->getRegisterBank(); Registers *register_bank = dbg_cpu->getRegisterBank();
@ -135,13 +137,13 @@ void Debug::handle_gdb_loop() {
stream << std::setw(8) << htonl(reg_value); stream << std::setw(8) << htonl(reg_value);
send_packet(conn, stream.str()); send_packet(conn, stream.str());
} else if (boost::starts_with(msg, "P")) { } else if (boost::starts_with(msg, "P")) {
char * pEnd; char *pEnd;
long reg = strtol(msg.c_str() + 1, &pEnd, 16); long reg = strtol(msg.c_str() + 1, &pEnd, 16);
int val = strtol(pEnd + 1, 0, 16); int val = strtol(pEnd + 1, 0, 16);
register_bank->setValue(reg + 1, val); register_bank->setValue(reg + 1, val);
send_packet(conn, "OK"); send_packet(conn, "OK");
} else if (boost::starts_with(msg, "m")) { } else if (boost::starts_with(msg, "m")) {
char * pEnd; char *pEnd;
long addr = strtol(msg.c_str() + 1, &pEnd, 16);; long addr = strtol(msg.c_str() + 1, &pEnd, 16);;
int len = strtol(pEnd + 1, &pEnd, 16); int len = strtol(pEnd + 1, &pEnd, 16);
@ -153,7 +155,7 @@ void Debug::handle_gdb_loop() {
std::stringstream stream; std::stringstream stream;
stream << std::setfill('0') << std::hex; stream << std::setfill('0') << std::hex;
for (auto &c : pyld_array) { for (auto &c: pyld_array) {
stream << std::setw(2) << (0xFF & c); stream << std::setw(2) << (0xFF & c);
} }
@ -208,26 +210,26 @@ void Debug::handle_gdb_loop() {
send_packet(conn, "OK"); send_packet(conn, "OK");
break; break;
} else if (boost::starts_with(msg, "Z1")) { } else if (boost::starts_with(msg, "Z1")) {
char * pEnd; char *pEnd;
long addr = strtol(msg.c_str() + 3, &pEnd, 16);; long addr = strtol(msg.c_str() + 3, &pEnd, 16);;
breakpoints.insert(addr); breakpoints.insert(addr);
std::cout << "Breakpoint set to address 0x"<< std::hex << addr << std::endl; std::cout << "Breakpoint set to address 0x" << std::hex << addr << std::endl;
send_packet(conn, "OK"); send_packet(conn, "OK");
} else if (boost::starts_with(msg, "z1")) { } else if (boost::starts_with(msg, "z1")) {
char * pEnd; char *pEnd;
long addr = strtol(msg.c_str() + 3, &pEnd, 16);; long addr = strtol(msg.c_str() + 3, &pEnd, 16);;
breakpoints.erase(addr); breakpoints.erase(addr);
send_packet(conn, "OK"); send_packet(conn, "OK");
} else if (boost::starts_with(msg, "z0")) { } else if (boost::starts_with(msg, "z0")) {
char * pEnd; char *pEnd;
long addr = strtol(msg.c_str() + 3, &pEnd, 16);; long addr = strtol(msg.c_str() + 3, &pEnd, 16);;
breakpoints.erase(addr); breakpoints.erase(addr);
send_packet(conn, ""); send_packet(conn, "");
} else if (boost::starts_with(msg, "Z0")) { } else if (boost::starts_with(msg, "Z0")) {
char * pEnd; char *pEnd;
long addr = strtol(msg.c_str() + 3, &pEnd, 16);; long addr = strtol(msg.c_str() + 3, &pEnd, 16);;
breakpoints.insert(addr); breakpoints.insert(addr);
std::cout << "Breakpoint set to address 0x"<< std::hex << addr << std::endl; std::cout << "Breakpoint set to address 0x" << std::hex << addr << std::endl;
send_packet(conn, "OK"); send_packet(conn, "OK");
} else { } else {
std::cout << "unsupported message '" << msg std::cout << "unsupported message '" << msg
@ -235,11 +237,11 @@ void Debug::handle_gdb_loop() {
break; break;
} }
} }
} }
std::string Debug::compute_checksum_string(const std::string &msg) { std::string Debug::compute_checksum_string(const std::string &msg) {
unsigned sum = 0; unsigned sum = 0;
for (auto c : msg) { for (auto c: msg) {
sum += unsigned(c); sum += unsigned(c);
} }
sum = sum % 256; sum = sum % 256;
@ -248,4 +250,6 @@ std::string Debug::compute_checksum_string(const std::string &msg) {
char high = nibble_to_hex[(sum & (0xf << 4)) >> 4]; char high = nibble_to_hex[(sum & (0xf << 4)) >> 4];
return {high, low}; return {high, low};
}
} }

View File

@ -8,13 +8,15 @@
#include "Instruction.h" #include "Instruction.h"
Instruction::Instruction(std::uint32_t instr) { namespace riscv_tlm {
m_instr = instr;
}
extension_t Instruction::check_extension() const { Instruction::Instruction(std::uint32_t instr) {
m_instr = instr;
}
extension_t Instruction::check_extension() const {
if (((m_instr & 0x0000007F) == 0b0110011) if (((m_instr & 0x0000007F) == 0b0110011)
&& ( ((m_instr & 0x7F000000) >> 25) == 0b0000001)) { && (((m_instr & 0x7F000000) >> 25) == 0b0000001)) {
return M_EXTENSION; return M_EXTENSION;
} else if ((m_instr & 0x0000007F) == 0b0101111) { } else if ((m_instr & 0x0000007F) == 0b0101111) {
return A_EXTENSION; return A_EXTENSION;
@ -27,7 +29,7 @@ extension_t Instruction::check_extension() const {
} else { } else {
return BASE_EXTENSION; return BASE_EXTENSION;
} }
}
} }

View File

@ -8,7 +8,9 @@
#include "M_extension.h" #include "M_extension.h"
op_M_Codes M_extension::decode() const { namespace riscv_tlm {
op_M_Codes M_extension::decode() const {
switch (opcode()) { switch (opcode()) {
case M_MUL: case M_MUL:
@ -41,9 +43,9 @@ op_M_Codes M_extension::decode() const {
} }
return OP_M_ERROR; return OP_M_ERROR;
} }
bool M_extension::Exec_M_MUL() const { bool M_extension::Exec_M_MUL() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::int32_t multiplier, multiplicand; std::int32_t multiplier, multiplicand;
std::int64_t result; std::int64_t result;
@ -59,13 +61,14 @@ bool M_extension::Exec_M_MUL() const {
result = result & 0x00000000FFFFFFFF; result = result & 0x00000000FFFFFFFF;
regs->setValue(rd, static_cast<std::int32_t>(result)); regs->setValue(rd, static_cast<std::int32_t>(result));
logger->debug("{} ns. PC: 0x{:x}. M.MUL: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.MUL: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_MULH() const { bool M_extension::Exec_M_MULH() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::int32_t multiplier, multiplicand; std::int32_t multiplier, multiplicand;
std::int64_t result; std::int64_t result;
@ -83,13 +86,14 @@ bool M_extension::Exec_M_MULH() const {
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF); ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
regs->setValue(rd, ret_value); regs->setValue(rd, ret_value);
logger->debug("{} ns. PC: 0x{:x}. M.MULH: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.MULH: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_MULHSU() const { bool M_extension::Exec_M_MULHSU() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::int32_t multiplier; std::int32_t multiplier;
std::uint32_t multiplicand; std::uint32_t multiplicand;
@ -106,13 +110,14 @@ bool M_extension::Exec_M_MULHSU() const {
result = (result >> 32) & 0x00000000FFFFFFFF; result = (result >> 32) & 0x00000000FFFFFFFF;
regs->setValue(rd, static_cast<std::int32_t>(result)); regs->setValue(rd, static_cast<std::int32_t>(result));
logger->debug("{} ns. PC: 0x{:x}. M.MULHSU: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.MULHSU: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_MULHU() const { bool M_extension::Exec_M_MULHU() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t multiplier, multiplicand; std::uint32_t multiplier, multiplicand;
std::uint64_t result; std::uint64_t result;
@ -129,13 +134,14 @@ bool M_extension::Exec_M_MULHU() const {
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF); ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
regs->setValue(rd, ret_value); regs->setValue(rd, ret_value);
logger->debug("{} ns. PC: 0x{:x}. M.MULHU: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.MULHU: x{:d} * x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_DIV() const { bool M_extension::Exec_M_DIV() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::int32_t divisor, dividend; std::int32_t divisor, dividend;
std::int64_t result; std::int64_t result;
@ -149,7 +155,7 @@ bool M_extension::Exec_M_DIV() const {
if (divisor == 0) { if (divisor == 0) {
result = -1; result = -1;
} else if ((divisor == -1) && (dividend == static_cast<std::int32_t>(0x80000000)) ) { } else if ((divisor == -1) && (dividend == static_cast<std::int32_t>(0x80000000))) {
result = 0x0000000080000000; result = 0x0000000080000000;
} else { } else {
result = dividend / divisor; result = dividend / divisor;
@ -158,13 +164,14 @@ bool M_extension::Exec_M_DIV() const {
regs->setValue(rd, static_cast<std::int32_t>(result)); regs->setValue(rd, static_cast<std::int32_t>(result));
logger->debug("{} ns. PC: 0x{:x}. M.DIV: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.DIV: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_DIVU() const { bool M_extension::Exec_M_DIVU() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t divisor, dividend; std::uint32_t divisor, dividend;
std::uint64_t result; std::uint64_t result;
@ -185,13 +192,14 @@ bool M_extension::Exec_M_DIVU() const {
regs->setValue(rd, static_cast<std::int32_t>(result)); regs->setValue(rd, static_cast<std::int32_t>(result));
logger->debug("{} ns. PC: 0x{:x}. M.DIVU: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.DIVU: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_REM() const { bool M_extension::Exec_M_REM() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::int32_t divisor, dividend; std::int32_t divisor, dividend;
std::int32_t result; std::int32_t result;
@ -205,7 +213,7 @@ bool M_extension::Exec_M_REM() const {
if (divisor == 0) { if (divisor == 0) {
result = dividend; result = dividend;
} else if ((divisor == -1) && (dividend == static_cast<std::int32_t>(0x80000000)) ) { } else if ((divisor == -1) && (dividend == static_cast<std::int32_t>(0x80000000))) {
result = 0; result = 0;
} else { } else {
result = dividend % divisor; result = dividend % divisor;
@ -213,13 +221,14 @@ bool M_extension::Exec_M_REM() const {
regs->setValue(rd, result); regs->setValue(rd, result);
logger->debug("{} ns. PC: 0x{:x}. M.REM: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.REM: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::Exec_M_REMU() const { bool M_extension::Exec_M_REMU() const {
int rd, rs1, rs2; int rd, rs1, rs2;
std::uint32_t divisor, dividend; std::uint32_t divisor, dividend;
std::uint32_t result; std::uint32_t result;
@ -239,13 +248,14 @@ bool M_extension::Exec_M_REMU() const {
regs->setValue(rd, static_cast<std::int32_t>(result)); regs->setValue(rd, static_cast<std::int32_t>(result));
logger->debug("{} ns. PC: 0x{:x}. M.REMU: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. M.REMU: x{:d} / x{:d} -> x{:d}({:d})", sc_core::sc_time_stamp().value(),
regs->getPC(),
rs1, rs2, rd, result); rs1, rs2, rd, result);
return true; return true;
} }
bool M_extension::process_instruction(Instruction &inst) { bool M_extension::process_instruction(Instruction &inst) {
bool PC_not_affected = true; bool PC_not_affected = true;
setInstr(inst.getInstr()); setInstr(inst.getInstr());
@ -284,4 +294,6 @@ bool M_extension::process_instruction(Instruction &inst) {
} }
return PC_not_affected; return PC_not_affected;
}
} }

View File

@ -8,8 +8,11 @@
#include "Memory.h" #include "Memory.h"
SC_HAS_PROCESS(Memory); namespace riscv_tlm {
Memory::Memory(sc_core::sc_module_name const &name, std::string const &filename) :
SC_HAS_PROCESS(Memory);
Memory::Memory(sc_core::sc_module_name const &name, std::string const &filename) :
sc_module(name), socket("socket"), LATENCY(sc_core::SC_ZERO_TIME) { sc_module(name), socket("socket"), LATENCY(sc_core::SC_ZERO_TIME) {
// Register callbacks for incoming interface method calls // Register callbacks for incoming interface method calls
socket.register_b_transport(this, &Memory::b_transport); socket.register_b_transport(this, &Memory::b_transport);
@ -22,9 +25,9 @@ Memory::Memory(sc_core::sc_module_name const &name, std::string const &filename)
logger = spdlog::get("my_logger"); logger = spdlog::get("my_logger");
logger->debug("Using file {}", filename); logger->debug("Using file {}", filename);
} }
Memory::Memory(sc_core::sc_module_name const& name) : Memory::Memory(sc_core::sc_module_name const &name) :
sc_module(name), socket("socket"), LATENCY(sc_core::SC_ZERO_TIME) { sc_module(name), socket("socket"), LATENCY(sc_core::SC_ZERO_TIME) {
socket.register_b_transport(this, &Memory::b_transport); socket.register_b_transport(this, &Memory::b_transport);
socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr); socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr);
@ -34,15 +37,16 @@ Memory::Memory(sc_core::sc_module_name const& name) :
logger = spdlog::get("my_logger"); logger = spdlog::get("my_logger");
logger->debug("Memory instantiated wihtout file"); logger->debug("Memory instantiated wihtout file");
} }
Memory::~Memory() = default; Memory::~Memory() = default;
std::uint32_t Memory::getPCfromHEX() { std::uint32_t Memory::getPCfromHEX() {
return program_counter; return program_counter;
} }
void Memory::b_transport(tlm::tlm_generic_payload &trans,
void Memory::b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay) { sc_core::sc_time &delay) {
tlm::tlm_command cmd = trans.get_command(); tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address(); sc_dt::uint64 adr = trans.get_address();
@ -87,9 +91,9 @@ void Memory::b_transport(tlm::tlm_generic_payload &trans,
// Obliged to set response status to indicate successful completion // Obliged to set response status to indicate successful completion
trans.set_response_status(tlm::TLM_OK_RESPONSE); trans.set_response_status(tlm::TLM_OK_RESPONSE);
} }
bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload &trans, bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
tlm::tlm_dmi &dmi_data) { tlm::tlm_dmi &dmi_data) {
(void) trans; (void) trans;
@ -102,16 +106,16 @@ bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
dmi_data.allow_read_write(); dmi_data.allow_read_write();
// Set other details of DMI region // Set other details of DMI region
dmi_data.set_dmi_ptr(reinterpret_cast<unsigned char*>(&mem[0])); dmi_data.set_dmi_ptr(reinterpret_cast<unsigned char *>(&mem[0]));
dmi_data.set_start_address(0); dmi_data.set_start_address(0);
dmi_data.set_end_address(Memory::SIZE * 4 - 1); dmi_data.set_end_address(Memory::SIZE * 4 - 1);
dmi_data.set_read_latency(LATENCY); dmi_data.set_read_latency(LATENCY);
dmi_data.set_write_latency(LATENCY); dmi_data.set_write_latency(LATENCY);
return true; return true;
} }
unsigned int Memory::transport_dbg(tlm::tlm_generic_payload &trans) { unsigned int Memory::transport_dbg(tlm::tlm_generic_payload &trans) {
tlm::tlm_command cmd = trans.get_command(); tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 adr = trans.get_address(); sc_dt::uint64 adr = trans.get_address();
unsigned char *ptr = trans.get_data_ptr(); unsigned char *ptr = trans.get_data_ptr();
@ -132,9 +136,9 @@ unsigned int Memory::transport_dbg(tlm::tlm_generic_payload &trans) {
} }
return num_bytes; return num_bytes;
} }
void Memory::readHexFile(std::string const& filename) { void Memory::readHexFile(std::string const &filename) {
std::ifstream hexfile; std::ifstream hexfile;
std::string line; std::string line;
std::uint32_t memory_offset = 0; std::uint32_t memory_offset = 0;
@ -198,4 +202,5 @@ void Memory::readHexFile(std::string const& filename) {
} else { } else {
SC_REPORT_ERROR("Memory", "Open file error"); SC_REPORT_ERROR("Memory", "Open file error");
} }
}
} }

View File

@ -8,8 +8,9 @@
#include "MemoryInterface.h" #include "MemoryInterface.h"
namespace riscv_tlm {
MemoryInterface::MemoryInterface() : MemoryInterface::MemoryInterface() :
data_bus("data_bus") {} data_bus("data_bus") {}
/** /**
@ -18,13 +19,13 @@ MemoryInterface::MemoryInterface() :
* @param size size of the data to read in bytes * @param size size of the data to read in bytes
* @return data value read * @return data value read
*/ */
std::uint32_t MemoryInterface::readDataMem(std::uint32_t addr, int size) { std::uint32_t MemoryInterface::readDataMem(std::uint32_t addr, int size) {
std::uint32_t data; std::uint32_t data;
tlm::tlm_generic_payload trans; tlm::tlm_generic_payload trans;
sc_core::sc_time delay = sc_core::SC_ZERO_TIME; sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
trans.set_command(tlm::TLM_READ_COMMAND); trans.set_command(tlm::TLM_READ_COMMAND);
trans.set_data_ptr(reinterpret_cast<unsigned char*>(&data)); trans.set_data_ptr(reinterpret_cast<unsigned char *>(&data));
trans.set_data_length(size); trans.set_data_length(size);
trans.set_streaming_width(4); // = data_length to indicate no streaming trans.set_streaming_width(4); // = data_length to indicate no streaming
trans.set_byte_enable_ptr(nullptr); // 0 indicates unused trans.set_byte_enable_ptr(nullptr); // 0 indicates unused
@ -38,7 +39,7 @@ std::uint32_t MemoryInterface::readDataMem(std::uint32_t addr, int size) {
SC_REPORT_ERROR("Memory", "Read memory"); SC_REPORT_ERROR("Memory", "Read memory");
} }
return data; return data;
} }
/** /**
* Acces data memory to write data * Acces data memory to write data
@ -47,12 +48,12 @@ std::uint32_t MemoryInterface::readDataMem(std::uint32_t addr, int size) {
* @param data data to write * @param data data to write
* @param size size of the data to write in bytes * @param size size of the data to write in bytes
*/ */
void MemoryInterface::writeDataMem(std::uint32_t addr, std::uint32_t data, int size) { void MemoryInterface::writeDataMem(std::uint32_t addr, std::uint32_t data, int size) {
tlm::tlm_generic_payload trans; tlm::tlm_generic_payload trans;
sc_core::sc_time delay = sc_core::SC_ZERO_TIME; sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
trans.set_command(tlm::TLM_WRITE_COMMAND); trans.set_command(tlm::TLM_WRITE_COMMAND);
trans.set_data_ptr(reinterpret_cast<unsigned char*>(&data)); trans.set_data_ptr(reinterpret_cast<unsigned char *>(&data));
trans.set_data_length(size); trans.set_data_length(size);
trans.set_streaming_width(4); // = data_length to indicate no streaming trans.set_streaming_width(4); // = data_length to indicate no streaming
trans.set_byte_enable_ptr(nullptr); // 0 indicates unused trans.set_byte_enable_ptr(nullptr); // 0 indicates unused
@ -61,4 +62,5 @@ void MemoryInterface::writeDataMem(std::uint32_t addr, std::uint32_t data, int s
trans.set_address(addr); trans.set_address(addr);
data_bus->b_transport(trans, delay); data_bus->b_transport(trans, delay);
}
} }

View File

@ -8,15 +8,17 @@
#include "Registers.h" #include "Registers.h"
Registers::Registers() { namespace riscv_tlm {
Registers::Registers() {
perf = Performance::getInstance(); perf = Performance::getInstance();
initCSR(); initCSR();
register_bank[sp] = Memory::SIZE - 4; // default stack at the end of the memory register_bank[sp] = Memory::SIZE - 4; // default stack at the end of the memory
register_PC = 0x80000000; // default _start address register_PC = 0x80000000; // default _start address
} }
void Registers::dump() { void Registers::dump() {
std::cout << "************************************" << std::endl; std::cout << "************************************" << std::endl;
std::cout << "Registers dump" << std::dec << std::endl; std::cout << "Registers dump" << std::dec << std::endl;
std::cout << std::setfill('0') << std::uppercase; std::cout << std::setfill('0') << std::uppercase;
@ -94,33 +96,33 @@ void Registers::dump() {
std::cout << "PC: 0x" << std::setw(8) << std::hex << register_PC << std::dec << std::endl; std::cout << "PC: 0x" << std::setw(8) << std::hex << register_PC << std::dec << std::endl;
std::cout << "************************************" << std::endl; std::cout << "************************************" << std::endl;
} }
void Registers::setValue(int reg_num, std::int32_t value) { void Registers::setValue(int reg_num, std::int32_t value) {
if ((reg_num != 0) && (reg_num < 32)) { if ((reg_num != 0) && (reg_num < 32)) {
register_bank[reg_num] = value; register_bank[reg_num] = value;
perf->registerWrite(); perf->registerWrite();
} }
} }
std::uint32_t Registers::getValue(int reg_num) const { std::uint32_t Registers::getValue(int reg_num) const {
if ((reg_num >= 0) && (reg_num < 32)) { if ((reg_num >= 0) && (reg_num < 32)) {
perf->registerRead(); perf->registerRead();
return register_bank[reg_num]; return register_bank[reg_num];
} else { } else {
return static_cast<std::int32_t>(0xFFFFFFFF); return static_cast<std::int32_t>(0xFFFFFFFF);
} }
} }
std::uint32_t Registers::getPC() const { std::uint32_t Registers::getPC() const {
return register_PC; return register_PC;
} }
void Registers::setPC(std::uint32_t new_pc) { void Registers::setPC(std::uint32_t new_pc) {
register_PC = new_pc; register_PC = new_pc;
} }
std::uint32_t Registers::getCSR(const int csr) { std::uint32_t Registers::getCSR(const int csr) {
std::uint32_t ret_value; std::uint32_t ret_value;
switch (csr) { switch (csr) {
@ -155,19 +157,20 @@ std::uint32_t Registers::getCSR(const int csr) {
break; break;
} }
return ret_value; return ret_value;
} }
void Registers::setCSR(int csr, std::uint32_t value) { void Registers::setCSR(int csr, std::uint32_t value) {
/* @FIXME: rv32mi-p-ma_fetch tests doesn't allow MISA to be writable, /* @FIXME: rv32mi-p-ma_fetch tests doesn't allow MISA to be writable,
* but Volume II: Privileged Architecture v1.10 says MISA is writable (?) * but Volume II: Privileged Architecture v1.10 says MISA is writable (?)
*/ */
if (csr != CSR_MISA) { if (csr != CSR_MISA) {
CSR[csr] = value; CSR[csr] = value;
} }
} }
void Registers::initCSR() { void Registers::initCSR() {
CSR[CSR_MISA] = MISA_MXL | MISA_M_EXTENSION | MISA_C_EXTENSION CSR[CSR_MISA] = MISA_MXL | MISA_M_EXTENSION | MISA_C_EXTENSION
| MISA_A_EXTENSION | MISA_I_BASE; | MISA_A_EXTENSION | MISA_I_BASE;
CSR[CSR_MSTATUS] = MISA_MXL; CSR[CSR_MSTATUS] = MISA_MXL;
}
} }

View File

@ -39,23 +39,23 @@ uint32_t dump_addr_end = 0;
*/ */
class Simulator : sc_core::sc_module { class Simulator : sc_core::sc_module {
public: public:
CPU *cpu; riscv_tlm::CPU *cpu;
Memory *MainMemory; riscv_tlm::Memory *MainMemory;
BusCtrl *Bus; riscv_tlm::BusCtrl *Bus;
Trace *trace; riscv_tlm::peripherals::Trace *trace;
Timer *timer; riscv_tlm::peripherals::Timer *timer;
explicit Simulator(sc_core::sc_module_name const &name): sc_module(name) { explicit Simulator(sc_core::sc_module_name const &name): sc_module(name) {
std::uint32_t start_PC; std::uint32_t start_PC;
MainMemory = new Memory("Main_Memory", filename); MainMemory = new riscv_tlm::Memory("Main_Memory", filename);
start_PC = MainMemory->getPCfromHEX(); start_PC = MainMemory->getPCfromHEX();
cpu = new CPU("cpu", start_PC, debug_session); cpu = new riscv_tlm::CPU("cpu", start_PC, debug_session);
Bus = new BusCtrl("BusCtrl"); Bus = new riscv_tlm::BusCtrl("BusCtrl");
trace = new Trace("Trace"); trace = new riscv_tlm::peripherals::Trace("Trace");
timer = new Timer("Timer"); timer = new riscv_tlm::peripherals::Timer("Timer");
cpu->instr_bus.bind(Bus->cpu_instr_socket); cpu->instr_bus.bind(Bus->cpu_instr_socket);
cpu->mem_intf->data_bus.bind(Bus->cpu_data_socket); cpu->mem_intf->data_bus.bind(Bus->cpu_data_socket);
@ -67,7 +67,7 @@ public:
timer->irq_line.bind(cpu->irq_line_socket); timer->irq_line.bind(cpu->irq_line_socket);
if (debug_session) { if (debug_session) {
Debug debug(cpu, MainMemory); riscv_tlm::Debug debug(cpu, MainMemory);
} }
} }

View File

@ -9,22 +9,24 @@
#include <cstdint> #include <cstdint>
#include "Timer.h" #include "Timer.h"
SC_HAS_PROCESS(Timer); namespace riscv_tlm::peripherals {
Timer::Timer(sc_core::sc_module_name const &name) : SC_HAS_PROCESS(Timer);
Timer::Timer(sc_core::sc_module_name const &name) :
sc_module(name), socket("timer_socket"), m_mtime(0), m_mtimecmp(0) { sc_module(name), socket("timer_socket"), m_mtime(0), m_mtimecmp(0) {
socket.register_b_transport(this, &Timer::b_transport); socket.register_b_transport(this, &Timer::b_transport);
SC_THREAD(run); SC_THREAD(run);
} }
[[noreturn]] void Timer::run() { [[noreturn]] void Timer::run() {
auto *irq_trans = new tlm::tlm_generic_payload; auto *irq_trans = new tlm::tlm_generic_payload;
sc_core::sc_time delay = sc_core::SC_ZERO_TIME; sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
std::uint32_t cause = 1 << 31 | 0x07; // Machine timer interrupt std::uint32_t cause = 1 << 31 | 0x07; // Machine timer interrupt
irq_trans->set_command(tlm::TLM_WRITE_COMMAND); irq_trans->set_command(tlm::TLM_WRITE_COMMAND);
irq_trans->set_data_ptr(reinterpret_cast<unsigned char*>(&cause)); irq_trans->set_data_ptr(reinterpret_cast<unsigned char *>(&cause));
irq_trans->set_data_length(4); irq_trans->set_data_length(4);
irq_trans->set_streaming_width(4); irq_trans->set_streaming_width(4);
irq_trans->set_byte_enable_ptr(nullptr); irq_trans->set_byte_enable_ptr(nullptr);
@ -36,9 +38,9 @@ Timer::Timer(sc_core::sc_module_name const &name) :
wait(timer_event); wait(timer_event);
irq_line->b_transport(*irq_trans, delay); irq_line->b_transport(*irq_trans, delay);
} }
} }
void Timer::b_transport(tlm::tlm_generic_payload &trans, void Timer::b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay) { sc_core::sc_time &delay) {
tlm::tlm_command cmd = trans.get_command(); tlm::tlm_command cmd = trans.get_command();
@ -98,4 +100,6 @@ void Timer::b_transport(tlm::tlm_generic_payload &trans,
} }
trans.set_response_status(tlm::TLM_OK_RESPONSE); trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
} }

View File

@ -20,11 +20,13 @@
#include "Trace.h" #include "Trace.h"
void Trace::xtermLaunch(char *slaveName) const { namespace riscv_tlm::peripherals {
void Trace::xtermLaunch(char *slaveName) const {
char *arg; char *arg;
char *fin = &(slaveName[strlen(slaveName) - 2]); char *fin = &(slaveName[strlen(slaveName) - 2]);
if ( nullptr == strchr(fin, '/')) { if (nullptr == strchr(fin, '/')) {
arg = new char[2 + 1 + 1 + 20 + 1]; arg = new char[2 + 1 + 1 + 20 + 1];
sprintf(arg, "-S%c%c%d", fin[0], fin[1], ptMaster); sprintf(arg, "-S%c%c%d", fin[0], fin[1], ptMaster);
} else { } else {
@ -34,14 +36,14 @@ void Trace::xtermLaunch(char *slaveName) const {
} }
char *argv[3]; char *argv[3];
argv[0] = (char*) ("xterm"); argv[0] = (char *) ("xterm");
argv[1] = arg; argv[1] = arg;
argv[2] = nullptr; argv[2] = nullptr;
execvp("xterm", argv); execvp("xterm", argv);
} }
void Trace::xtermKill() { void Trace::xtermKill() {
if (-1 != ptSlave) { // Close down the slave if (-1 != ptSlave) { // Close down the slave
close(ptSlave); // Close the FD close(ptSlave); // Close the FD
@ -57,9 +59,9 @@ void Trace::xtermKill() {
kill(xtermPid, SIGKILL); kill(xtermPid, SIGKILL);
waitpid(xtermPid, nullptr, 0); waitpid(xtermPid, nullptr, 0);
} }
} }
void Trace::xtermSetup() { void Trace::xtermSetup() {
ptMaster = open("/dev/ptmx", O_RDWR); ptMaster = open("/dev/ptmx", O_RDWR);
if (ptMaster != -1) { if (ptMaster != -1) {
@ -83,22 +85,23 @@ void Trace::xtermSetup() {
xtermLaunch(ptSlaveName); xtermLaunch(ptSlaveName);
} }
} }
} }
SC_HAS_PROCESS(Trace); SC_HAS_PROCESS(Trace);
Trace::Trace(sc_core::sc_module_name const &name) :
Trace::Trace(sc_core::sc_module_name const &name) :
sc_module(name), socket("socket") { sc_module(name), socket("socket") {
socket.register_b_transport(this, &Trace::b_transport); socket.register_b_transport(this, &Trace::b_transport);
xtermSetup(); xtermSetup();
} }
Trace::~Trace() { Trace::~Trace() {
xtermKill(); xtermKill();
} }
void Trace::b_transport(tlm::tlm_generic_payload &trans, void Trace::b_transport(tlm::tlm_generic_payload &trans,
sc_core::sc_time &delay) { sc_core::sc_time &delay) {
unsigned char *ptr = trans.get_data_ptr(); unsigned char *ptr = trans.get_data_ptr();
@ -108,4 +111,6 @@ void Trace::b_transport(tlm::tlm_generic_payload &trans,
(void) a; (void) a;
trans.set_response_status(tlm::TLM_OK_RESPONSE); trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
} }

View File

@ -8,25 +8,27 @@
#include "extension_base.h" #include "extension_base.h"
extension_base::extension_base(const sc_dt::sc_uint<32> & instr, namespace riscv_tlm {
extension_base::extension_base(const sc_dt::sc_uint<32> &instr,
Registers *register_bank, MemoryInterface *mem_interface) : Registers *register_bank, MemoryInterface *mem_interface) :
m_instr(instr), regs(register_bank), mem_intf(mem_interface) { m_instr(instr), regs(register_bank), mem_intf(mem_interface) {
perf = Performance::getInstance(); perf = Performance::getInstance();
logger = spdlog::get("my_logger"); logger = spdlog::get("my_logger");
} }
extension_base::~extension_base() =default; extension_base::~extension_base() = default;
void extension_base::setInstr(std::uint32_t p_instr) { void extension_base::setInstr(std::uint32_t p_instr) {
m_instr = sc_dt::sc_uint<32>(p_instr); m_instr = sc_dt::sc_uint<32>(p_instr);
} }
void extension_base::dump() const { void extension_base::dump() const {
std::cout << std::hex << "0x" << m_instr << std::dec << std::endl; std::cout << std::hex << "0x" << m_instr << std::dec << std::endl;
} }
void extension_base::RaiseException(std::uint32_t cause, std::uint32_t inst) { void extension_base::RaiseException(std::uint32_t cause, std::uint32_t inst) {
std::uint32_t new_pc, current_pc, m_cause; std::uint32_t new_pc, current_pc, m_cause;
current_pc = regs->getPC(); current_pc = regs->getPC();
@ -50,11 +52,12 @@ void extension_base::RaiseException(std::uint32_t cause, std::uint32_t inst) {
logger->debug("{} ns. PC: 0x{:x}. Exception! new PC 0x{:x} ", sc_core::sc_time_stamp().value(), regs->getPC(), logger->debug("{} ns. PC: 0x{:x}. Exception! new PC 0x{:x} ", sc_core::sc_time_stamp().value(), regs->getPC(),
new_pc); new_pc);
} }
bool extension_base::NOP() { bool extension_base::NOP() {
logger->debug("{} ns. PC: 0x{:x}. NOP! new PC 0x{:x} ", sc_core::sc_time_stamp().value(), regs->getPC()); logger->debug("{} ns. PC: 0x{:x}. NOP! new PC 0x{:x} ", sc_core::sc_time_stamp().value(), regs->getPC());
sc_core::sc_stop(); sc_core::sc_stop();
return true; return true;
}
} }