diff --git a/inc/BASE_ISA.h b/inc/BASE_ISA.h index 3e96301..a246175 100644 --- a/inc/BASE_ISA.h +++ b/inc/BASE_ISA.h @@ -88,6 +88,20 @@ namespace riscv_tlm { OP_WFI, OP_SFENCE, + /* RV64 */ + OP_LWU, + OP_LD, + OP_SD, + OP_ADDIW, + OP_SLLIW, + OP_SRLIW, + OP_SRAIW, + OP_ADDW, + OP_SUBW, + OP_SLLW, + OP_SRLW, + OP_SRAW, + OP_ERROR } opCodes; @@ -111,11 +125,14 @@ namespace riscv_tlm { LW_F = 0b010, LBU_F = 0b100, LHU_F = 0b101, + LWU_F = 0b110, + LD_F = 0b011, SB = 0b0100011, SB_F = 0b000, SH_F = 0b001, SW_F = 0b010, + SD_F = 0b011, ADDI = 0b0010011, ADDI_F = 0b000, @@ -126,8 +143,8 @@ namespace riscv_tlm { ANDI_F = 0b111, SLLI_F = 0b001, SRLI_F = 0b101, - SRLI_F7 = 0b0000000, - SRAI_F7 = 0b0100000, + SRLI_F7 = 0b000000, + SRAI_F7 = 0b010000, ADD = 0b0110011, ADD_F = 0b000, @@ -163,6 +180,21 @@ namespace riscv_tlm { CSRRWI = 0b101, CSRRSI = 0b110, CSRRCI = 0b111, + + ADDIW = 0b0011011, + ADDIW_F = 0b000, + SLLIW_F = 0b001, + SRLIW_F = 0b101, + SRLIW_F7 = 0b000000, + SRAIW_F7 = 0b010000, + ADDW = 0b0111011, + ADDW_F = 0b000, + ADDW_F7 = 0b000000, + SUBW_F7 = 0b010000, + SLLW = 0b001, + SRLW = 0b101, + SRLW_F7 = 0b000000, + SRAW_F7 = 0b010000, }; /** @@ -191,10 +223,16 @@ namespace riscv_tlm { * @brief Access to funct7 field * @return funct7 field */ - inline std::int32_t get_funct7() const { + inline std::uint32_t get_funct7() const { return this->m_instr.range(31, 25); } + /** + * @brief Access to funct7 field in case of RV64 SLLL, SRLI, SRAI is different + * @return funct7 field + */ + std::uint32_t get_funct7b() const; + /** * @brief Gets immediate field value for I-type * @return immediate_I field @@ -260,7 +298,7 @@ namespace riscv_tlm { unsigned_T imm; rd = this->get_rd(); - imm = get_imm_U() << 12; + imm = static_cast(get_imm_U() << 12); this->regs->setValue(rd, imm); this->logger->debug("{} ns. PC: 0x{:x}. LUI: x{:d} <- 0x{:x}", sc_core::sc_time_stamp().value(), @@ -276,7 +314,7 @@ namespace riscv_tlm { unsigned_T new_pc; rd = this->get_rd(); - imm = get_imm_U() << 12; + imm = static_cast(get_imm_U() << 12); new_pc = this->regs->getPC() + imm; this->regs->setValue(rd, new_pc); @@ -290,8 +328,8 @@ namespace riscv_tlm { } bool Exec_JAL() const { - std::int32_t mem_addr; unsigned int rd; + signed_T mem_addr; unsigned_T new_pc, old_pc; rd = this->get_rd(); @@ -305,44 +343,41 @@ namespace riscv_tlm { this->regs->setValue(rd, old_pc); this->logger->debug("{} ns. PC: 0x{:x}. JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + sc_core::sc_time_stamp().value(), old_pc - 4, rd, old_pc, mem_addr, new_pc); return true; } bool Exec_JALR() { - signed_T mem_addr; + signed_T offset; unsigned int rd, rs1; unsigned_T new_pc, old_pc; rd = this->get_rd(); rs1 = this->get_rs1(); - mem_addr = get_imm_I(); - + offset = get_imm_I(); old_pc = this->regs->getPC(); - this->regs->setValue(rd, old_pc + 4); - new_pc = static_cast((this->regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE); + new_pc = static_cast((this->regs->getValue(rs1) + offset) & ~1); + this->regs->setValue(rd, old_pc + 4); if ((new_pc & 0x00000003) != 0) { // not aligned - this->logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x} PC <- 0x{:x}", + this->logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x} PC <- 0x{:x} (0x{:x})", sc_core::sc_time_stamp().value(), - this->regs->getPC(), - rd, old_pc + 4, new_pc); - - this->logger->debug("{} ns. PC: 0x{:x}. JALR : Exception"); + old_pc, + rd, old_pc + 4, new_pc, offset); + this->logger->debug("{} ns. PC: 0x{:x}. JALR : Exception", + sc_core::sc_time_stamp().value(), old_pc); this->RaiseException(EXCEPTION_CAUSE_LOAD_ADDR_MISALIGN, this->m_instr); } else { this->regs->setPC(new_pc); + this->logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x}. PC <- 0x{:x}", + sc_core::sc_time_stamp().value(), + old_pc, rd, old_pc + 4, new_pc); } - this->logger->debug("{} ns. PC: 0x{:x}. JALR: x{:d} <- 0x{:x}. PC <- 0x{:x}", - sc_core::sc_time_stamp().value(), - this->regs->getPC(), - rd, old_pc + 4, new_pc); - return true; } @@ -373,13 +408,13 @@ namespace riscv_tlm { bool Exec_BNE() const { unsigned int rs1, rs2; - signed_T val1, val2; + unsigned_T val1, val2; rs1 = this->get_rs1(); rs2 = this->get_rs2(); - val1 = static_cast(this->regs->getValue(rs1)); - val2 = static_cast(this->regs->getValue(rs2)); + val1 = this->regs->getValue(rs1); + val2 = this->regs->getValue(rs2); if (val1 != val2) { unsigned_T new_pc; @@ -399,15 +434,16 @@ namespace riscv_tlm { bool Exec_BLT() const { unsigned int rs1, rs2; signed_T val1, val2; + unsigned_T new_pc, old_pc; rs1 = this->get_rs1(); rs2 = this->get_rs2(); val1 = static_cast(this->regs->getValue(rs1)); val2 = static_cast(this->regs->getValue(rs2)); + old_pc = static_cast(this->regs->getPC()); if (val1 < val2) { - unsigned_T new_pc; new_pc = static_cast(this->regs->getPC() + get_imm_B()); this->regs->setPC(new_pc); } else { @@ -415,7 +451,7 @@ namespace riscv_tlm { } this->logger->debug("{} ns. PC: 0x{:x}. BLT: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + sc_core::sc_time_stamp().value(), old_pc, rs1, this->regs->getValue(rs1), rs2, this->regs->getValue(rs2), this->regs->getPC()); return true; @@ -449,6 +485,7 @@ namespace riscv_tlm { bool Exec_BLTU() const { unsigned int rs1, rs2; unsigned_T val1, val2; + unsigned_T new_pc, old_pc; rs1 = this->get_rs1(); rs2 = this->get_rs2(); @@ -456,16 +493,17 @@ namespace riscv_tlm { val1 = this->regs->getValue(rs1); val2 = this->regs->getValue(rs2); + old_pc = static_cast(this->regs->getPC()); + if (val1 < val2) { - unsigned_T new_pc; - new_pc = static_cast(this->regs->getPC() + get_imm_B()); + new_pc = static_cast(old_pc + get_imm_B()); this->regs->setPC(new_pc); } else { this->regs->incPC(); } this->logger->debug("{} ns. PC: 0x{:x}. BLTU: x{:d}(0x{:x}) < x{:d}(0x{:x})? -> PC (0x{:x})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + sc_core::sc_time_stamp().value(), old_pc, rs1, this->regs->getValue(rs1), rs2, this->regs->getValue(rs2), this->regs->getPC()); return true; @@ -499,7 +537,7 @@ namespace riscv_tlm { bool Exec_LB() const { unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; + signed_T imm; std::int8_t data; rd = this->get_rd(); @@ -522,15 +560,15 @@ namespace riscv_tlm { bool Exec_LH() const { unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; - int16_t data; + signed_T imm; + std::int16_t data; rd = this->get_rd(); rs1 = this->get_rs1(); imm = get_imm_I(); mem_addr = imm + this->regs->getValue(rs1); - data = static_cast(this->mem_intf->readDataMem(mem_addr, 2)); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 2)); this->perf->dataMemoryRead(); this->regs->setValue(rd, data); @@ -545,17 +583,18 @@ namespace riscv_tlm { bool Exec_LW() const { unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; - std::uint32_t data; + signed_T imm; + std::int32_t data; rd = this->get_rd(); rs1 = this->get_rs1(); imm = get_imm_I(); mem_addr = imm + this->regs->getValue(rs1); - data = this->mem_intf->readDataMem(mem_addr, 4); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + this->perf->dataMemoryRead(); - this->regs->setValue(rd, static_cast(data)); + this->regs->setValue(rd, data); this->logger->debug("{} ns. PC: 0x{:x}. LW: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), @@ -568,7 +607,7 @@ namespace riscv_tlm { bool Exec_LBU() const { unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; + signed_T imm; std::uint8_t data; rd = this->get_rd(); @@ -576,9 +615,10 @@ namespace riscv_tlm { imm = get_imm_I(); mem_addr = imm + this->regs->getValue(rs1); - data = this->mem_intf->readDataMem(mem_addr, 1); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 1)); + this->perf->dataMemoryRead(); - this->regs->setValue(rd, static_cast(data)); + this->regs->setValue(rd, data); this->logger->debug("{} ns. PC: 0x{:x}. LBU: x{:d} + x{:d}(0x{:x}) -> x{:d}", sc_core::sc_time_stamp().value(), @@ -591,17 +631,17 @@ namespace riscv_tlm { bool Exec_LHU() const { unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; - uint16_t data; + signed_T imm; + std::uint16_t data; rd = this->get_rd(); rs1 = this->get_rs1(); imm = get_imm_I(); mem_addr = imm + this->regs->getValue(rs1); - data = this->mem_intf->readDataMem(mem_addr, 2); - this->perf->dataMemoryRead(); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 2)); + this->perf->dataMemoryRead(); this->regs->setValue(rd, data); this->logger->debug("{} ns. PC: 0x{:x}. LHU: x{:d} + x{:d}(0x{:x}) -> x{:d}", @@ -612,10 +652,90 @@ namespace riscv_tlm { return true; } + bool Exec_LWU() const { + unsigned_T mem_addr; + unsigned int rd, rs1; + signed_T imm; + std::uint32_t data; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + imm = get_imm_I(); + + mem_addr = imm + this->regs->getValue(rs1); + data = this->mem_intf->readDataMem(mem_addr, 4); + + this->perf->dataMemoryRead(); + this->regs->setValue(rd, data); + + this->logger->debug("{} ns. PC: 0x{:x}. LWU: x{:d} + x{:d}(0x{:x}) -> x{:d}", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, imm, mem_addr, rd); + + return true; + } + + bool Exec_LD() const { + unsigned_T mem_addr; + unsigned int rd, rs1; + signed_T imm; + signed_T offset; + + std::uint64_t data; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + imm = get_imm_I(); + + offset = this->regs->getValue(rs1); + mem_addr = imm + offset; + + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + std::uint64_t aux = static_cast(this->mem_intf->readDataMem(mem_addr + 4, 4)); + data |= aux << 32; + + this->perf->dataMemoryRead(); + this->regs->setValue(rd, data); + + this->logger->debug("{} ns. PC: 0x{:x}. LD: 0x{:x}({:d}) + {:d}(0x{:x}) -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, offset, imm, mem_addr, rd, data); + return true; + } + + + bool Exec_SD() const { + unsigned_T mem_addr; + unsigned int rs1, rs2; + signed_T imm; + std::uint64_t data; + + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + imm = get_imm_S(); + + mem_addr = imm + this->regs->getValue(rs1); + data = this->regs->getValue(rs2); + + this->logger->debug("{} ns. PC: 0x{:x}. SD: 0x{:x} -> x{:d} + 0x{:x}(@0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs2, rs1, imm, mem_addr); + + this->mem_intf->writeDataMem(mem_addr, data & 0xFFFFFFFF, 4); + this->mem_intf->writeDataMem(mem_addr + 4, data >> 32, 4); + this->perf->dataMemoryWrite(); + + return true; + } + + bool Exec_SB() const { unsigned_T mem_addr; unsigned int rs1, rs2; - std::int32_t imm; + signed_T imm; std::uint32_t data; rs1 = this->get_rs1(); @@ -636,10 +756,11 @@ namespace riscv_tlm { return true; } + bool Exec_SH() const { unsigned_T mem_addr; unsigned int rs1, rs2; - std::int32_t imm; + signed_T imm; std::uint32_t data; rs1 = this->get_rs1(); @@ -660,10 +781,11 @@ namespace riscv_tlm { return true; } + bool Exec_SW() const { unsigned_T mem_addr; unsigned int rs1, rs2; - std::int32_t imm; + signed_T imm; std::uint32_t data; rs1 = this->get_rs1(); @@ -686,17 +808,41 @@ namespace riscv_tlm { bool Exec_ADDI() const { unsigned int rd, rs1; - std::int32_t imm; - signed_T calc; + signed_T imm; + unsigned_T calc; rd = this->get_rd(); rs1 = this->get_rs1(); imm = get_imm_I(); - calc = static_cast(this->regs->getValue(rs1)) + imm; + calc = this->regs->getValue(rs1) + imm; + this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. ADDI: x{:d} + x{:d} -> x{:d}(0x{:x})", + this->logger->debug("{} ns. PC: 0x{:x}. ADDI: x{:d}(0x{:x}) + {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, this->regs->getValue(rs1), imm, rd, calc); + + return true; + } + + bool Exec_ADDIW() const { + unsigned int rd, rs1; + std::int32_t imm; + std::int32_t aux; + std::int64_t calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + imm = get_imm_I(); + + aux = static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF); + aux = static_cast(aux + imm); + calc = static_cast(aux); + + this->regs->setValue(rd, calc); + this->logger->debug("{} ns. PC: 0x{:x}. ADDIW: x{:d} + {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), rs1, imm, rd, calc); @@ -706,7 +852,7 @@ namespace riscv_tlm { bool Exec_SLTI() const { unsigned int rd, rs1; - std::int32_t imm; + signed_T imm; signed_T val1; rd = this->get_rd(); @@ -761,7 +907,7 @@ namespace riscv_tlm { bool Exec_XORI() const { unsigned int rd, rs1; - unsigned_T imm; + signed_T imm; unsigned_T calc; rd = this->get_rd(); @@ -780,7 +926,7 @@ namespace riscv_tlm { bool Exec_ORI() const { unsigned int rd, rs1; - unsigned_T imm; + signed_T imm; unsigned_T calc; rd = this->get_rd(); @@ -799,7 +945,7 @@ namespace riscv_tlm { bool Exec_ANDI() const { unsigned int rd, rs1; - unsigned_T imm; + signed_T imm; unsigned_T calc; rd = this->get_rd(); @@ -817,7 +963,17 @@ namespace riscv_tlm { return true; } - bool Exec_SLLI() { + + bool Exec_SLLI(); + + + bool Exec_SRLI() const; + + + bool Exec_SRAI() const; + + + bool Exec_SLLIW() { unsigned int rd, rs1, rs2; unsigned_T shift; unsigned_T calc; @@ -827,7 +983,8 @@ namespace riscv_tlm { rs2 = get_shamt(); if (rs2 >= 0x20) { - std::cout << "ILEGAL INSTRUCTION, shamt[5] != 0" << "\n"; + std::cout << "ILLEGAL INSTRUCTION, shamt[5] != 0" << "\n"; + sc_core::sc_stop(); this->RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION, this->m_instr); return false; @@ -835,10 +992,10 @@ namespace riscv_tlm { shift = rs2 & 0x1F; - calc = static_cast(this->regs->getValue(rs1)) << shift; + calc = static_cast(static_cast(this->regs->getValue(rs1)) << shift); this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. SLLI: x{:d} << {:d} -> x{:d}(0x{:x})", + this->logger->debug("{} ns. PC: 0x{:x}. SLLIW: x{:d} << {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), rs1, shift, rd, calc); @@ -846,7 +1003,100 @@ namespace riscv_tlm { return true; } - bool Exec_SRLI() const { + + bool Exec_SRLIW() { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = get_shamt(); + + if (rs2 >= 0x20) { + std::cout << "ILLEGAL INSTRUCTION, shamt[5] != 0" << "\n"; + sc_core::sc_stop(); + this->RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION, this->m_instr); + + return false; + } + + shift = rs2 & 0x1F; + + calc = static_cast(static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF) >> shift); + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRLIW: x{:d} << {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + + bool Exec_SRAIW() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + signed_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_shamt_slli(); + + shift = rs2 & 0x1F; + + calc = static_cast(static_cast(this->regs->getValue(rs1)) >> shift); + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRAIW: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + bool Exec_ADDW() const { + unsigned int rd, rs1, rs2; + unsigned_T calc; + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + calc = static_cast((this->regs->getValue(rs1) + this->regs->getValue(rs2)) & 0xFFFFFFFF); + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. ADDW: x{:d} + x{:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, rs2, rd, calc); + + return true; + } + + bool Exec_SUBW() const { + unsigned int rd, rs1, rs2; + unsigned_T calc; + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + calc = static_cast((this->regs->getValue(rs1) - this->regs->getValue(rs2)) & 0xFFFFFFFF); + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SUBW: x{:d} + x{:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, rs2, rd, calc); + + return true; + } + + + bool Exec_SLLW() const { unsigned int rd, rs1, rs2; unsigned_T shift; unsigned_T calc; @@ -855,12 +1105,12 @@ namespace riscv_tlm { rs1 = this->get_rs1(); rs2 = this->get_rs2(); - shift = rs2 & 0x1F; + shift = this->regs->getValue(rs2) & 0x1F; + calc = static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF) << shift; - calc = static_cast(this->regs->getValue(rs1)) >> shift; this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. SRLI: x{:d} >> {:d} -> x{:d}(0x{:x})", + this->logger->debug("{} ns. PC: 0x{:x}. SLLW: x{:d} << x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), rs1, shift, rd, calc); @@ -868,7 +1118,31 @@ namespace riscv_tlm { return true; } - bool Exec_SRAI() const { + + bool Exec_SRLW() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x1F; + calc = static_cast(static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF) >> shift); + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRLW: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + + bool Exec_SRAW() const { unsigned int rd, rs1, rs2; unsigned_T shift; signed_T calc; @@ -877,12 +1151,12 @@ namespace riscv_tlm { rs1 = this->get_rs1(); rs2 = this->get_rs2(); - shift = rs2 & 0x1F; + shift = this->regs->getValue(rs2) & 0x1F; + calc = static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF) >> shift; - calc = static_cast(this->regs->getValue(rs1)) >> shift; this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. SRAI: x{:d} >> {:d} -> x{:d}(0x{:x})", + this->logger->debug("{} ns. PC: 0x{:x}. SRAW: x{:d} >> {:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), rs1, shift, rd, calc); @@ -892,12 +1166,12 @@ namespace riscv_tlm { bool Exec_ADD() const { unsigned int rd, rs1, rs2; - unsigned_T calc; + signed_T calc; rd = this->get_rd(); rs1 = this->get_rs1(); rs2 = this->get_rs2(); - calc = this->regs->getValue(rs1) + this->regs->getValue(rs2); + calc = static_cast(this->regs->getValue(rs1)) + static_cast(this->regs->getValue(rs2)); this->regs->setValue(rd, calc); @@ -911,12 +1185,12 @@ namespace riscv_tlm { bool Exec_SUB() const { unsigned int rd, rs1, rs2; - unsigned_T calc; + signed_T calc; rd = this->get_rd(); rs1 = this->get_rs1(); rs2 = this->get_rs2(); - calc = this->regs->getValue(rs1) - this->regs->getValue(rs2); + calc = static_cast(this->regs->getValue(rs1)) - static_cast(this->regs->getValue(rs2)); this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", @@ -927,27 +1201,8 @@ namespace riscv_tlm { return true; } - bool Exec_SLL() const { - unsigned int rd, rs1, rs2; - unsigned_T shift; - unsigned_T calc; - rd = this->get_rd(); - rs1 = this->get_rs1(); - rs2 = this->get_rs2(); - - shift = this->regs->getValue(rs2) & 0x1F; - - calc = this->regs->getValue(rs1) << shift; - this->regs->setValue(rd, calc); - - this->logger->debug("{} ns. PC: 0x{:x}. SLL: x{:d} << x{:d} -> x{:d}(0x{:x})", - sc_core::sc_time_stamp().value(), - this->regs->getPC(), - rs1, shift, rd, calc); - - return true; - } + bool Exec_SLL() const; bool Exec_SLT() const { unsigned int rd, rs1, rs2; @@ -1024,48 +1279,11 @@ namespace riscv_tlm { return true; } - bool Exec_SRL() const { - unsigned int rd, rs1, rs2; - unsigned_T shift; - unsigned_T calc; - rd = this->get_rd(); - rs1 = this->get_rs1(); - rs2 = this->get_rs2(); + bool Exec_SRL() const; - shift = this->regs->getValue(rs2) & 0x1F; - calc = this->regs->getValue(rs1) >> shift; - this->regs->setValue(rd, calc); - - this->logger->debug("{} ns. PC: 0x{:x}. SRL: x{:d} >> {:d} -> x{:d}(0x{:x})", - sc_core::sc_time_stamp().value(), - this->regs->getPC(), - rs1, shift, rd, calc); - - return true; - } - - bool Exec_SRA() const { - unsigned int rd, rs1, rs2; - unsigned_T shift; - signed_T calc; - - rd = this->get_rd(); - rs1 = this->get_rs1(); - rs2 = this->get_rs2(); - - shift = this->regs->getValue(rs2) & 0x1F; - calc = static_cast(this->regs->getValue(rs1)) >> shift; - this->regs->setValue(rd, calc); - - this->logger->debug("{} ns. PC: 0x{:x}. SRA: x{:d} >> {:d} -> x{:d}(0x{:x})", - sc_core::sc_time_stamp().value(), - this->regs->getPC(), - rs1, shift, rd, calc); - - return true; - } + bool Exec_SRA() const; bool Exec_OR() const { unsigned int rd, rs1, rs2; @@ -1132,6 +1350,7 @@ namespace riscv_tlm { sc_core::sc_stop(); #else this->RaiseException(11, this->m_instr); + sc_core::sc_stop(); #endif return true; } @@ -1153,7 +1372,7 @@ namespace riscv_tlm { bool Exec_CSRRW() const { unsigned int rd, rs1; int csr; - std::uint32_t aux; + unsigned_T aux; rd = this->get_rd(); rs1 = this->get_rs1(); @@ -1162,7 +1381,7 @@ namespace riscv_tlm { /* These operations must be atomical */ if (rd != 0) { aux = this->regs->getCSR(csr); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); } aux = this->regs->getValue(rs1); @@ -1179,14 +1398,15 @@ namespace riscv_tlm { bool Exec_CSRRS() const { unsigned int rd, rs1; int csr; - std::uint32_t bitmask, aux, aux2; + unsigned_T bitmask, aux, aux2; rd = this->get_rd(); rs1 = this->get_rs1(); csr = get_csr(); if (rd == 0) { - this->logger->debug("{} ns. PC: 0x{:x}. CSRRS with rd1 == 0, doing nothing."); + this->logger->debug("{} ns. PC: 0x{:x}. CSRRS with rd1 == 0, doing nothing.", + sc_core::sc_time_stamp().value(), this->regs->getPC()); return false; } @@ -1194,7 +1414,7 @@ namespace riscv_tlm { aux = this->regs->getCSR(csr); bitmask = this->regs->getValue(rs1); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); aux2 = aux | bitmask; this->regs->setCSR(csr, aux2); @@ -1209,14 +1429,15 @@ namespace riscv_tlm { bool Exec_CSRRC() const { unsigned int rd, rs1; int csr; - std::uint32_t bitmask, aux, aux2; + unsigned_T bitmask, aux, aux2; rd = this->get_rd(); rs1 = this->get_rs1(); csr = get_csr(); if (rd == 0) { - this->logger->debug("{} ns. PC: 0x{:x}. CSRRC with rd1 == 0, doing nothing."); + this->logger->debug("{} ns. PC: 0x{:x}. CSRRC with rd1 == 0, doing nothing.", + sc_core::sc_time_stamp().value(), this->regs->getPC()); return true; } @@ -1224,7 +1445,7 @@ namespace riscv_tlm { aux = this->regs->getCSR(csr); bitmask = this->regs->getValue(rs1); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); aux2 = aux & ~bitmask; this->regs->setCSR(csr, aux2); @@ -1239,7 +1460,7 @@ namespace riscv_tlm { bool Exec_CSRRWI() const { unsigned int rd, rs1; int csr; - std::uint32_t aux; + unsigned_T aux; rd = this->get_rd(); rs1 = this->get_rs1(); @@ -1248,7 +1469,7 @@ namespace riscv_tlm { /* These operations must be atomical */ if (rd != 0) { aux = this->regs->getCSR(csr); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); } aux = rs1; this->regs->setCSR(csr, aux); @@ -1263,7 +1484,7 @@ namespace riscv_tlm { bool Exec_CSRRSI() const { unsigned int rd, rs1; int csr; - std::uint32_t bitmask, aux; + unsigned_T bitmask, aux; rd = this->get_rd(); rs1 = this->get_rs1(); @@ -1275,7 +1496,7 @@ namespace riscv_tlm { /* These operations must be atomical */ aux = this->regs->getCSR(csr); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); bitmask = rs1; aux = aux | bitmask; @@ -1291,7 +1512,7 @@ namespace riscv_tlm { bool Exec_CSRRCI() const { unsigned rd, rs1; int csr; - std::uint32_t bitmask, aux; + unsigned_T bitmask, aux; rd = this->get_rd(); rs1 = this->get_rs1(); @@ -1303,7 +1524,7 @@ namespace riscv_tlm { /* These operations must be atomical */ aux = this->regs->getCSR(csr); - this->regs->setValue(rd, static_cast(aux)); + this->regs->setValue(rd, aux); bitmask = rs1; aux = aux & ~bitmask; @@ -1319,7 +1540,7 @@ namespace riscv_tlm { /*********************** Privileged Instructions ******************************/ bool Exec_MRET() const { - std::uint32_t new_pc = 0; + unsigned_T new_pc = 0; new_pc = this->regs->getCSR(CSR_MEPC); this->regs->setPC(new_pc); @@ -1328,7 +1549,7 @@ namespace riscv_tlm { this->regs->getPC(), new_pc); // update mstatus - std::uint32_t csr_temp; + unsigned_T csr_temp; csr_temp = this->regs->getCSR(CSR_MSTATUS); if (csr_temp & MSTATUS_MPIE) { csr_temp |= MSTATUS_MIE; @@ -1340,7 +1561,7 @@ namespace riscv_tlm { } bool Exec_SRET() const { - std::uint32_t new_pc = 0; + unsigned_T new_pc = 0; new_pc = this->regs->getCSR(CSR_SEPC); this->regs->setPC(new_pc); @@ -1425,6 +1646,12 @@ namespace riscv_tlm { case OP_LHU: Exec_LHU(); break; + case OP_LWU: + Exec_LWU(); + break; + case OP_LD: + Exec_LD(); + break; case OP_SB: Exec_SB(); break; @@ -1434,6 +1661,9 @@ namespace riscv_tlm { case OP_SW: Exec_SW(); break; + case OP_SD: + Exec_SD(); + break; case OP_ADDI: Exec_ADDI(); break; @@ -1535,7 +1765,34 @@ namespace riscv_tlm { case OP_SFENCE: Exec_SFENCE(); break; - [[unlikely]] default: + case OP_ADDIW: + Exec_ADDIW(); + break; + case OP_SLLIW: + Exec_SLLIW(); + break; + case OP_SRLIW: + Exec_SRLIW(); + break; + case OP_SRAIW: + Exec_SRAIW(); + break; + case OP_ADDW: + Exec_ADDW(); + break; + case OP_SUBW: + Exec_SUBW(); + break; + case OP_SLLW: + Exec_SLLW(); + break; + case OP_SRLW: + Exec_SRLW(); + break; + case OP_SRAW: + Exec_SRAW(); + break; + [[unlikely]] default: std::cout << "Wrong instruction" << "\n"; inst.dump(); this->NOP(); @@ -1588,6 +1845,10 @@ namespace riscv_tlm { return OP_LBU; case LHU_F: return OP_LHU; + case LWU_F: + return OP_LWU; + case LD_F: + return OP_LD; } return OP_ERROR; case SB: @@ -1598,6 +1859,8 @@ namespace riscv_tlm { return OP_SH; case SW_F: return OP_SW; + case SD_F: + return OP_SD; } return OP_ERROR; case ADDI: @@ -1617,7 +1880,9 @@ namespace riscv_tlm { case SLLI_F: return OP_SLLI; case SRLI_F: - switch (this->get_funct7()) { + // TODO: Why funct7b is not working? + //switch (this->get_funct7b()) { + switch(this->m_instr.to_uint() >> 26) { case SRLI_F7: return OP_SRLI; case SRAI_F7: @@ -1709,6 +1974,64 @@ namespace riscv_tlm { } } break; + case ADDIW: + switch (this->get_funct3()) { + case ADDIW_F: + return OP_ADDIW; + break; + case SLLIW_F: + return OP_SLLIW; + break; + case SRLIW_F: + switch (this->m_instr.to_uint() >> 26) { + case SRLIW_F7: + return OP_SRLIW; + break; + case SRAIW_F7: + return OP_SRAIW; + break; + default: + return OP_ERROR; + } + break; + default: + return OP_ERROR; + } + break; + case ADDW: + switch (this->get_funct3()) { + case ADDW_F: + switch (this->m_instr.to_uint() >> 26) { + case ADDW_F7: + return OP_ADDW; + break; + case SUBW_F7: + return OP_SUBW; + break; + default: + return OP_ERROR; + break; + } + break; + case SLLW: + return OP_SLLW; + break; + case SRLW: + switch (this->m_instr.to_uint() >> 26) { + case SRLW_F7: + return OP_SRLW; + break; + case SRAW_F7: + return OP_SRAW; + break; + default: + return OP_ERROR; + break; + } + default: + return OP_ERROR; + } + default: return OP_ERROR; } diff --git a/inc/C_extension.h b/inc/C_extension.h index 0b02515..331e7d0 100644 --- a/inc/C_extension.h +++ b/inc/C_extension.h @@ -19,13 +19,16 @@ namespace riscv_tlm { OP_C_FLD, OP_C_LW, OP_C_FLW, + OP_C_LD, OP_C_FSD, OP_C_SW, OP_C_FSW, + OP_C_SD, OP_C_NOP, OP_C_ADDI, OP_C_JAL, + OP_C_ADDIW, OP_C_LI, OP_C_ADDI16SP, OP_C_LUI, @@ -33,7 +36,9 @@ namespace riscv_tlm { OP_C_SRAI, OP_C_ANDI, OP_C_SUB, + OP_C_SUBW, OP_C_XOR, + OP_C_ADDW, OP_C_OR, OP_C_AND, OP_C_J, @@ -44,6 +49,7 @@ namespace riscv_tlm { OP_C_FLDSP, OP_C_LWSP, OP_C_FLWSP, + OP_C_LDSP, OP_C_JR, OP_C_MV, OP_C_EBREAK, @@ -52,7 +58,7 @@ namespace riscv_tlm { OP_C_FSDSP, OP_C_SWSP, OP_C_FSWSP, - + OP_C_SDSP, OP_C_ERROR } op_C_Codes; @@ -197,7 +203,7 @@ namespace riscv_tlm { return aux; } - inline void set_imm_S(std::uint32_t value) { + inline void set_imm_S(std::uint32_t value) const { sc_dt::sc_uint<32> aux = value; this->m_instr.range(31, 25) = aux.range(11, 5); @@ -212,7 +218,7 @@ namespace riscv_tlm { return static_cast(this->m_instr.range(31, 12)); } - inline void set_imm_U(std::uint32_t value) { + inline void set_imm_U(std::uint32_t value) const { this->m_instr.range(31, 12) = (value << 12); } @@ -235,7 +241,7 @@ namespace riscv_tlm { return aux; } - inline void set_imm_B(std::uint32_t value) { + inline void set_imm_B(std::uint32_t value) const { sc_dt::sc_uint<32> aux = value; this->m_instr[31] = aux[12]; @@ -268,7 +274,7 @@ namespace riscv_tlm { return aux; } - inline void set_imm_J(std::uint32_t value) { + inline void set_imm_J(std::uint32_t value) const { sc_dt::sc_uint<32> aux = (value << 20); this->m_instr[31] = aux[20]; @@ -277,12 +283,12 @@ namespace riscv_tlm { this->m_instr.range(19, 12) = aux.range(19, 12); } - [[nodiscard]] inline std::int32_t get_imm_L() const { - std::int32_t aux = 0; + [[nodiscard]] inline std::uint32_t get_imm_L() const { + std::uint32_t aux = 0; - aux = static_cast(this->m_instr.range(12, 10) << 3); - aux |= static_cast(this->m_instr[6] << 2); - aux |= static_cast(this->m_instr[5] << 6); + aux = this->m_instr.range(12, 10) << 3; + aux |= this->m_instr[6] << 2; + aux |= this->m_instr[5] << 6; return aux; } @@ -290,14 +296,24 @@ namespace riscv_tlm { [[nodiscard]] inline std::uint32_t get_imm_LWSP() const { std::uint32_t aux = 0; - aux = static_cast(this->m_instr[12] << 5); - aux |= static_cast(this->m_instr.range(6, 4) << 2); - aux |= static_cast(this->m_instr.range(3, 2) << 6); + aux = this->m_instr[12] << 5; + aux |= this->m_instr.range(6, 4) << 2; + aux |= this->m_instr.range(3, 2) << 6; return aux; } - [[nodiscard]] inline std::uint32_t get_imm_ADDI() const { + [[nodiscard]] inline std::uint32_t get_imm_LDSP() const { + std::uint32_t aux = 0; + + aux = static_cast(this->m_instr[12] << 5); + aux |= static_cast(this->m_instr.range(6, 5) << 3); + aux |= static_cast(this->m_instr.range(4, 2) << 6); + + return aux; + } + + [[nodiscard]] inline std::int32_t get_imm_ADDI() const { std::uint32_t aux = 0; aux = static_cast(this->m_instr[12] << 5); @@ -306,7 +322,7 @@ namespace riscv_tlm { if (this->m_instr[12] == 1) { aux |= 0b11111111111111111111111111 << 6; } - return aux; + return static_cast(aux); } [[nodiscard]] inline std::uint32_t get_imm_ADDI4SPN() const { @@ -320,7 +336,7 @@ namespace riscv_tlm { return aux; } - [[nodiscard]] inline std::uint32_t get_imm_ADDI16SP() const { + [[nodiscard]] inline std::int32_t get_imm_ADDI16SP() const { std::uint32_t aux = 0; aux = static_cast(this->m_instr[12] << 9); @@ -344,6 +360,14 @@ namespace riscv_tlm { return aux; } + [[nodiscard]] inline std::uint32_t get_imm_CSDSP() const { + std::uint32_t aux = 0; + aux = static_cast(this->m_instr.range(12, 10) << 3); + aux |= static_cast(this->m_instr.range(9, 7) << 6); + + return aux; + } + [[nodiscard]] inline std::uint32_t get_imm_CB() const { std::uint32_t aux = 0; @@ -363,11 +387,20 @@ namespace riscv_tlm { return aux; } - [[nodiscard]] inline std::uint32_t get_imm_LUI() const { + [[nodiscard]] inline std::uint32_t get_imm_CL() const { std::uint32_t aux = 0; - aux = static_cast(this->m_instr[12] << 17); - aux |= static_cast(this->m_instr.range(6, 2) << 12); + aux = this->m_instr.range(12, 10) << 3; + aux |= this->m_instr.range(6, 5) << 6; + + return aux; + } + + [[nodiscard]] inline std::int32_t get_imm_LUI() const { + std::int32_t aux = 0; + + aux = this->m_instr[12] << 17; + aux |= this->m_instr.range(6, 2) << 12; if (this->m_instr[12] == 1) { aux |= 0b111111111111111 << 17; @@ -400,7 +433,13 @@ namespace riscv_tlm { return OP_C_LW; break; case C_FLW: - return OP_C_FLW; + if (sizeof(signed_T) == 4) { + // RV32 + return OP_C_FLW; + } else { + // RV64 + return OP_C_LD; + } break; case C_FSD: return OP_C_FSD; @@ -409,7 +448,11 @@ namespace riscv_tlm { return OP_C_SW; break; case C_FSW: - return OP_C_FSW; + if (sizeof(signed_T) == 4) { + return OP_C_FSW; + } else { + return OP_C_SD; + } break; [[unlikely]] default: return OP_C_ERROR; @@ -423,7 +466,11 @@ namespace riscv_tlm { return OP_C_ADDI; break; case C_JAL: - return OP_C_JAL; + if (sizeof(signed_T) == 4) { + return OP_C_JAL; + } else { + return OP_C_ADDIW; + } break; case C_LI: return OP_C_LI; @@ -445,10 +492,18 @@ namespace riscv_tlm { case C_2_SUB: switch (this->m_instr.range(6, 5)) { case C_3_SUB: - return OP_C_SUB; + if (this->m_instr[12] == 0) { + return OP_C_SUB; + } else { + return OP_C_SUBW; + } break; case C_3_XOR: - return OP_C_XOR; + if (this->m_instr[12] == 0) { + return OP_C_XOR; + } else { + return OP_C_ADDW; + } break; case C_3_OR: return OP_C_OR; @@ -484,7 +539,11 @@ namespace riscv_tlm { return OP_C_LWSP; break; case C_FLWSP: - return OP_C_FLWSP; + if (sizeof(signed_T) == 4) { + return OP_C_FLWSP; + } else { + return OP_C_LDSP; + } break; case C_JR: if (this->m_instr[12] == 0) { @@ -509,8 +568,11 @@ namespace riscv_tlm { return OP_C_SWSP; break; case C_FWWSP: - [[unlikely]] - return OP_C_FSWSP; + if (sizeof(signed_T) == 4) { + return OP_C_FSWSP; + } else { + return OP_C_SDSP; + } break; default: return OP_C_ERROR; @@ -526,54 +588,54 @@ namespace riscv_tlm { return OP_C_ERROR; } - bool Exec_C_JR() { + // PASS + bool Exec_C_JR() const { std::uint32_t mem_addr; unsigned int rs1; - std::uint32_t new_pc; + unsigned_T new_pc; rs1 = get_rs1(); mem_addr = 0; - new_pc = static_cast( - static_cast((this->regs->getValue(rs1)) + static_cast(mem_addr)) & + new_pc = static_cast( + static_cast((this->regs->getValue(rs1)) + static_cast(mem_addr)) & 0xFFFFFFFE); - this->logger->debug("{} ns. PC: 0x{:x}. C.JR: PC <- 0x{:x}", sc_core::sc_time_stamp().value(), - this->regs->getPC(), new_pc); + this->logger->debug("{} ns. PC: 0x{:x}. C.JR: PC <- 0x{:x}. x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), + this->regs->getPC(), new_pc, rs1, this->regs->getValue(rs1)); this->regs->setPC(new_pc); return true; } - bool Exec_C_MV() { - unsigned int rd, rs1, rs2; - std::uint32_t calc; + bool Exec_C_MV() const { + unsigned int rd, rs2; + unsigned_T calc; rd = this->get_rd(); - rs1 = 0; rs2 = get_rs2(); - calc = this->regs->getValue(rs1) + this->regs->getValue(rs2); - this->regs->setValue(rd, static_cast(calc)); + calc = this->regs->getValue(rs2); + this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. C.MV: x{:d}(0x{:x}) + x{:d}(0x{:x}) -> x{:d}(0x{:x})", + this->logger->debug("{} ns. PC: 0x{:x}. C.MV: x{:d}(0x{:x}) -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), - rs1, this->regs->getValue(rs1), rs2, this->regs->getValue(rs2), rd, calc); + rs2, this->regs->getValue(rs2), rd, calc); return true; } - bool Exec_C_ADD() { + bool Exec_C_ADD() const { unsigned int rd, rs1, rs2; - std::uint32_t calc; + unsigned_T calc; rd = get_rs1(); rs1 = get_rs1(); rs2 = get_rs2(); calc = this->regs->getValue(rs1) + this->regs->getValue(rs2); - this->regs->setValue(rd, static_cast(calc)); + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.ADD: x{:d} + x{} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), @@ -583,20 +645,21 @@ namespace riscv_tlm { return true; } - bool Exec_C_LWSP() { - std::uint32_t mem_addr; + bool Exec_C_LWSP() const { + unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; - std::uint32_t data; + std::uint32_t imm; + unsigned_T data; // lw rd, offset[7:2](x2) rd = this->get_rd(); rs1 = 2; - imm = static_cast(get_imm_LWSP()); + imm = static_cast(get_imm_LWSP()); mem_addr = imm + this->regs->getValue(rs1); - data = this->mem_intf->readDataMem(mem_addr, 4); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + this->perf->dataMemoryRead(); this->regs->setValue(rd, static_cast(data)); @@ -611,19 +674,19 @@ namespace riscv_tlm { bool Exec_C_ADDI4SPN() { unsigned int rd, rs1; - std::int32_t imm; - std::int32_t calc; + signed_T imm; + signed_T calc; rd = get_rdp(); rs1 = 2; - imm = static_cast(get_imm_ADDI4SPN()); + imm = static_cast(get_imm_ADDI4SPN()); if (imm == 0) { this->RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION, this->m_instr); return false; } - calc = static_cast(this->regs->getValue(rs1)) + imm; + calc = static_cast(this->regs->getValue(rs1)) + imm; this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.ADDI4SN: x{:d} + (0x{:x}) + {:d} -> x{:d}(0x{:x})", @@ -633,19 +696,18 @@ namespace riscv_tlm { return true; } - bool Exec_C_ADDI16SP() { - // addi x2, x2, nzimm[9:4] + bool Exec_C_ADDI16SP() const { unsigned int rd; - std::int32_t imm; + signed_T imm; if (this->get_rd() == 2) { int rs1; - std::int32_t calc; + unsigned_T calc; rd = 2; rs1 = 2; - imm = static_cast(get_imm_ADDI16SP()); - calc = static_cast(this->regs->getValue(rs1)) + imm; + imm = get_imm_ADDI16SP(); + calc = this->regs->getValue(rs1) + imm; this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.ADDI16SP: x{:d} + {:d} -> x{:d} (0x{:x})", @@ -654,7 +716,7 @@ namespace riscv_tlm { } else { /* C.LUI OPCODE */ rd = this->get_rd(); - imm = static_cast(get_imm_LUI()); + imm = get_imm_LUI(); this->regs->setValue(rd, imm); this->logger->debug("{} ns. PC: 0x{:x}. C.LUI: x{:d} <- 0x{:x}", sc_core::sc_time_stamp().value(), @@ -665,8 +727,7 @@ namespace riscv_tlm { return true; } - bool Exec_C_SWSP() { - // sw rs2, offset(x2) + bool Exec_C_SWSP() const { std::uint32_t mem_addr; unsigned int rs1, rs2; std::int32_t imm; @@ -689,61 +750,63 @@ namespace riscv_tlm { return true; } - bool Exec_C_BEQZ() { + bool Exec_C_BEQZ() const { unsigned int rs1; - std::uint32_t new_pc; - std::uint32_t val1; + unsigned_T new_pc, old_pc; + unsigned_T val1; rs1 = get_rs1p(); val1 = this->regs->getValue(rs1); + old_pc = this->regs->getPC(); if (val1 == 0) { - new_pc = static_cast(this->regs->getPC()) + get_imm_CB(); + new_pc = static_cast(this->regs->getPC()) + static_cast(get_imm_CB()); this->regs->setPC(new_pc); } else { this->regs->incPCby2(); - new_pc = static_cast(this->regs->getPC()); + new_pc = static_cast(this->regs->getPC()); } this->logger->debug("{} ns. PC: 0x{:x}. C.BEQZ: x{:d}(0x{:x}) == 0? -> PC (0xx{:d})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + sc_core::sc_time_stamp().value(), old_pc, rs1, val1, new_pc); return true; } - bool Exec_C_BNEZ() { + bool Exec_C_BNEZ() const { unsigned int rs1; - std::uint32_t new_pc; - std::uint32_t val1; + unsigned_T new_pc, old_pc; + unsigned_T val1; rs1 = get_rs1p(); val1 = this->regs->getValue(rs1); + old_pc = this->regs->getPC(); if (val1 != 0) { - new_pc = static_cast(this->regs->getPC()) + get_imm_CB(); + new_pc = static_cast(this->regs->getPC()) + static_cast(get_imm_CB()); this->regs->setPC(new_pc); } else { this->regs->incPCby2(); //PC <- PC +2 - new_pc = static_cast(this->regs->getPC()); + new_pc = static_cast(this->regs->getPC()); } - this->logger->debug("{} ns. PC: 0x{:x}. C.BNEZ: x{:d}(0x{:x}) != 0? -> PC (0xx{:d})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + this->logger->debug("{} ns. PC: 0x{:x}. C.BNEZ: x{:d}(0x{:x}) != 0? -> PC (0x{:x})", + sc_core::sc_time_stamp().value(), old_pc, rs1, val1, new_pc); return true; } - bool Exec_C_LI() { + bool Exec_C_LI() const { unsigned int rd, rs1; std::int32_t imm; - std::int32_t calc; + unsigned_T calc; rd = this->get_rd(); rs1 = 0; imm = static_cast(get_imm_ADDI()); - calc = static_cast(this->regs->getValue(rs1)) + imm; + calc = this->regs->getValue(rs1) + imm; this->regs->setValue(rd, calc); @@ -754,19 +817,19 @@ namespace riscv_tlm { return true; } - bool Exec_C_SRLI() { + bool Exec_C_SRLI() const { unsigned int rd, rs1, rs2; std::uint32_t shift; - std::uint32_t calc; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); - rs2 = get_rs2(); + rs2 = get_imm_ADDI(); - shift = rs2 & 0x1F; + shift = rs2; - calc = static_cast(this->regs->getValue(rs1)) >> shift; - this->regs->setValue(rd, static_cast(calc)); + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.SRLI: x{:d} >> {} -> x{:d}", sc_core::sc_time_stamp().value(), this->regs->getPC(), @@ -775,18 +838,18 @@ namespace riscv_tlm { return true; } - bool Exec_C_SRAI() { + bool Exec_C_SRAI() const { unsigned int rd, rs1, rs2; std::uint32_t shift; - std::int32_t calc; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); - rs2 = get_rs2(); + rs2 = get_imm_ADDI(); - shift = rs2 & 0x1F; + shift = rs2; - calc = static_cast(this->regs->getValue(rs1)) >> shift; + calc = static_cast(this->regs->getValue(rs1)) >> shift; this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.SRAI: x{:d} >> {} -> x{:d}(0x{:x})", @@ -797,19 +860,17 @@ namespace riscv_tlm { return true; } - bool Exec_C_SLLI() { - unsigned int rd, rs1, rs2; - std::uint32_t shift; - std::uint32_t calc; + bool Exec_C_SLLI() const { + unsigned int rd, rs1; + unsigned_T shift; + unsigned_T calc; - rd = get_rs1p(); - rs1 = get_rs1p(); - rs2 = get_imm_ADDI(); + rd = get_rs1(); + rs1 = get_rs1(); + shift = get_imm_ADDI(); - shift = rs2 & 0x1F; - - calc = static_cast(this->regs->getValue(rs1)) << shift; - this->regs->setValue(rd, static_cast(calc)); + calc = this->regs->getValue(rs1) << shift; + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.SLLI: x{:d} << {} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), @@ -819,38 +880,36 @@ namespace riscv_tlm { return true; } - bool Exec_C_ANDI() { + bool Exec_C_ANDI() const { unsigned int rd, rs1; - std::uint32_t imm; - std::uint32_t aux; - std::uint32_t calc; + signed_T imm; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); imm = get_imm_ADDI(); - aux = this->regs->getValue(rs1); - calc = aux & imm; - this->regs->setValue(rd, static_cast(calc)); + calc = this->regs->getValue(rs1) & imm; + this->regs->setValue(rd, calc); - this->logger->debug("{} ns. PC: 0x{:x}. C.ANDI: x{:d}(0x{:x}) AND 0x{:x} -> x{:d}", + this->logger->debug("{} ns. PC: 0x{:x}. ANDI: x{:d} C.AND 0x{:x} -> x{:d}", sc_core::sc_time_stamp().value(), this->regs->getPC(), - rs1, aux, imm, rd); + rs1, imm, rd); return true; } - bool Exec_C_SUB() { + bool Exec_C_SUB() const { unsigned int rd, rs1, rs2; - std::uint32_t calc; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); rs2 = get_rs2p(); calc = this->regs->getValue(rs1) - this->regs->getValue(rs2); - this->regs->setValue(rd, static_cast(calc)); + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.SUB: x{:d} - x{:d} -> x{:d}(0x{:x})", sc_core::sc_time_stamp().value(), @@ -860,7 +919,7 @@ namespace riscv_tlm { return true; } - bool Exec_C_XOR() { + bool Exec_C_SUBW() const { unsigned int rd, rs1, rs2; std::uint32_t calc; @@ -868,9 +927,72 @@ namespace riscv_tlm { rs1 = get_rs1p(); rs2 = get_rs2p(); - calc = this->regs->getValue(rs1) ^ this->regs->getValue(rs2); + calc = static_cast((this->regs->getValue(rs1) - this->regs->getValue(rs2)) & 0xFFFFFFFF); this->regs->setValue(rd, static_cast(calc)); + this->logger->debug("{} ns. PC: 0x{:x}. C.SUBW: x{:d} - x{:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, rs2, rd, calc); + + return true; + } + + bool Exec_C_ADDW() const { + unsigned int rd, rs1, rs2; + unsigned_T calc; + + rd = get_rs1p(); + rs1 = get_rs1p(); + rs2 = get_rs2p(); + + calc = static_cast((this->regs->getValue(rs1) + this->regs->getValue(rs2)) & 0xFFFFFFFF); + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. C.ADDW: x{:d} + x{} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, rs2, rd, calc); + + return true; + } + + bool Exec_C_SDSP() const { + unsigned_T mem_addr; + unsigned int rs1, rs2; + signed_T imm; + std::uint64_t data; + + rs1 = 2; + rs2 = get_rs2(); + imm = get_imm_CSDSP(); + + mem_addr = imm + this->regs->getValue(rs1); + data = this->regs->getValue(rs2); + + this->logger->debug("{} ns. PC: 0x{:x}. C.SDSP: 0x{:x} -> x{:d} + 0x{:x}(@0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs2, rs1, imm, mem_addr); + + this->mem_intf->writeDataMem(mem_addr, data & 0xFFFFFFFF, 4); + this->mem_intf->writeDataMem(mem_addr + 4, data >> 32, 4); + this->perf->dataMemoryWrite(); + + return true; + } + + bool Exec_C_XOR() const { + unsigned int rd, rs1, rs2; + unsigned_T calc; + + rd = get_rs1p(); + rs1 = get_rs1p(); + rs2 = get_rs2p(); + + calc = this->regs->getValue(rs1) ^ this->regs->getValue(rs2); + this->regs->setValue(rd, calc); + this->logger->debug("{} ns. PC: 0x{:x}. C.XOR: x{:d} XOR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), this->regs->getPC(), rs1, rs2, rd); @@ -878,16 +1000,16 @@ namespace riscv_tlm { return true; } - bool Exec_C_OR() { + bool Exec_C_OR() const { unsigned int rd, rs1, rs2; - std::uint32_t calc; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); rs2 = get_rs2p(); calc = this->regs->getValue(rs1) | this->regs->getValue(rs2); - this->regs->setValue(rd, static_cast(calc)); + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.OR: x{:d} OR x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), this->regs->getPC(), @@ -896,16 +1018,16 @@ namespace riscv_tlm { return true; } - bool Exec_C_AND() { + bool Exec_C_AND() const { unsigned int rd, rs1, rs2; - std::uint32_t calc; + unsigned_T calc; rd = get_rs1p(); rs1 = get_rs1p(); rs2 = get_rs2p(); calc = this->regs->getValue(rs1) & this->regs->getValue(rs2); - this->regs->setValue(rd, static_cast(calc)); + this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.AND: x{:d} AND x{:d} -> x{:d}", sc_core::sc_time_stamp().value(), this->regs->getPC(), @@ -916,14 +1038,14 @@ namespace riscv_tlm { bool Exec_C_ADDI() const { unsigned int rd, rs1; - std::int32_t imm; - std::int32_t calc; + signed_T imm; + unsigned_T calc; rd = this->get_rd(); rs1 = rd; - imm = static_cast(get_imm_ADDI()); + imm = static_cast(get_imm_ADDI()); - calc = static_cast(this->regs->getValue(rs1)) + imm; + calc = this->regs->getValue(rs1) + imm; this->regs->setValue(rd, calc); this->logger->debug("{} ns. PC: 0x{:x}. C.ADDI: x{:d} + {} -> x{:d}(0x{:x})", @@ -933,7 +1055,29 @@ namespace riscv_tlm { return true; } - bool Exec_C_JALR() { + bool Exec_C_ADDIW() const { + unsigned int rd, rs1; + std::int32_t imm; + std::int32_t aux; + std::int64_t calc; + + rd = this->get_rd(); + rs1 = rd; + imm = get_imm_ADDI(); + + aux = static_cast(this->regs->getValue(rs1) & 0xFFFFFFFF); + aux = static_cast(aux + imm); + calc = static_cast(aux); + + this->regs->setValue(rd, calc); + this->logger->debug("{} ns. PC: 0x{:x}. C.ADDIW: x{:d} + {} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), rs1, imm, rd, calc); + + return true; + } + + bool Exec_C_JALR() const { std::uint32_t mem_addr = 0; unsigned int rd, rs1; std::uint32_t new_pc, old_pc; @@ -942,9 +1086,9 @@ namespace riscv_tlm { rs1 = get_rs1(); old_pc = static_cast(this->regs->getPC()); - this->regs->setValue(rd, old_pc + 2); - new_pc = static_cast((this->regs->getValue(rs1) + mem_addr) & 0xFFFFFFFE); + + this->regs->setValue(rd, old_pc + 2); this->regs->setPC(new_pc); this->logger->debug("{} ns. PC: 0x{:x}. C.JALR: x{:d} <- 0x{:x} PC <- 0xx{:x}", @@ -955,20 +1099,21 @@ namespace riscv_tlm { return true; } - bool Exec_C_LW() { - std::uint32_t mem_addr; + bool Exec_C_LW() const { + unsigned_T mem_addr; unsigned int rd, rs1; - std::int32_t imm; - std::uint32_t data; + unsigned_T imm; + signed_T data; rd = get_rdp(); rs1 = get_rs1p(); imm = get_imm_L(); mem_addr = imm + this->regs->getValue(rs1); - data = this->mem_intf->readDataMem(mem_addr, 4); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + this->perf->dataMemoryRead(); - this->regs->setValue(rd, static_cast(data)); + this->regs->setValue(rd, data); this->logger->debug("{} ns. PC: 0x{:x}. C.LW: x{:d}(0x{:x}) + {:d} (@0x{:x}) -> {:d} (0x{:x})", sc_core::sc_time_stamp().value(), this->regs->getPC(), @@ -977,7 +1122,58 @@ namespace riscv_tlm { return true; } - bool Exec_C_SW() { + bool Exec_C_LD() const { + unsigned_T mem_addr; + unsigned int rd, rs1; + unsigned_T imm; + std::uint64_t data; + + rd = get_rdp(); + rs1 = get_rs1p(); + imm = get_imm_CL(); + + mem_addr = imm + this->regs->getValue(rs1); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + std::uint64_t aux = static_cast(this->mem_intf->readDataMem(mem_addr + 4, 4)); + data |= aux << 32; + + this->perf->dataMemoryRead(); + this->regs->setValue(rd, data); + + this->logger->debug("{} ns. PC: 0x{:x}. C.LD: 0x{:x} + x{:d} (0x{:x}) -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, imm, mem_addr, rd, data); + + return true; + } + + bool Exec_C_SD() const { + unsigned_T mem_addr; + unsigned int rs1, rs2; + signed_T imm; + std::uint64_t data; + + rs1 = get_rs1p(); + rs2 = get_rs2p(); + imm = get_imm_CL(); + + mem_addr = imm + this->regs->getValue(rs1); + data = this->regs->getValue(rs2); + + this->logger->debug("{} ns. PC: 0x{:x}. C.SD: 0x{:x} -> x{:d} + 0x{:x}(@0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs2, rs1, imm, mem_addr); + + this->mem_intf->writeDataMem(mem_addr, data & 0xFFFFFFFF, 4); + this->mem_intf->writeDataMem(mem_addr + 4, data >> 32, 4); + this->perf->dataMemoryWrite(); + + return true; + } + + bool Exec_C_SW() const { std::uint32_t mem_addr; unsigned int rs1, rs2; std::int32_t imm; @@ -1000,7 +1196,67 @@ namespace riscv_tlm { return true; } - bool Exec_C_JAL(int m_rd) { + bool Exec_C_FSW_SD() const { + std::uint32_t mem_addr; + unsigned int rs1, rs2; + std::int32_t imm; + std::uint64_t data; + std::uint32_t aux; + + rs1 = get_rs1p(); + rs2 = get_rs2p(); + imm = get_imm_L(); + + mem_addr = imm + this->regs->getValue(rs1); + data = this->regs->getValue(rs2); + + aux = data >> 32; + this->mem_intf->writeDataMem(mem_addr, aux, 4); + + aux = data & 0x00000000FFFFFFFF; + this->mem_intf->writeDataMem(mem_addr+4, aux, 4); + + this->perf->dataMemoryWrite(); + + this->logger->debug("{} ns. PC: 0x{:x}. C.SD: x{:d}(0x{:x}) -> x{:d} + 0x{:x}(@0x{:x})", + sc_core::sc_time_stamp().value(), this->regs->getPC(), + rs2, data, rs1, imm, mem_addr); + return true; + } + + // Implemented RV64 C.LDSP only (FLWSP is for RV32 with F extension) + bool Exec_C_LDSP() const { + unsigned_T mem_addr; + unsigned int rd, rs1; + unsigned_T imm; + std::uint64_t data; + std::uint64_t aux; + + rd = this->get_rd(); + rs1 = 2; + imm = get_imm_LDSP(); + + if (rd == 0) { + // Error + std::cout << "C.LDSP Error!\n"; + } + + mem_addr = imm + this->regs->getValue(rs1); + data = static_cast(this->mem_intf->readDataMem(mem_addr, 4)); + aux = static_cast(this->mem_intf->readDataMem(mem_addr + 4, 4)); + data |= aux << 32; + + this->perf->dataMemoryRead(); + this->regs->setValue(rd, data); + + this->logger->debug("{} ns. PC: 0x{:x}. C.LDSP: x{:d}(0x{:x}) -> x{:d} + 0x{:x}(@0x{:x})", + sc_core::sc_time_stamp().value(), this->regs->getPC(), + 2, data, rs1, imm, mem_addr); + return true; + } + + + bool Exec_C_JAL(int m_rd) const { std::int32_t mem_addr; unsigned int rd; std::uint32_t new_pc, old_pc; @@ -1016,13 +1272,13 @@ namespace riscv_tlm { this->regs->setValue(rd, old_pc); this->logger->debug("{} ns. PC: 0x{:x}. C.JAL: x{:d} <- 0x{:x}. PC + 0x{:x} -> PC (0x{:x})", - sc_core::sc_time_stamp().value(), this->regs->getPC(), + sc_core::sc_time_stamp().value(), old_pc - 2, rd, old_pc, mem_addr, new_pc); return true; } - bool Exec_C_EBREAK() { + bool Exec_C_EBREAK() const { this->logger->debug("C.EBREAK"); std::cout << "\n" << "C.EBRAK Instruction called, dumping information" @@ -1122,12 +1378,39 @@ namespace riscv_tlm { case OP_C_AND: Exec_C_AND(); break; + case OP_C_FSW: + Exec_C_FSW_SD(); + break; + case OP_C_FLWSP: + //Exec_C_FLWSP_LDSP(); + break; case OP_C_EBREAK: Exec_C_EBREAK(); std::cout << "C_EBREAK" << std::endl; *breakpoint = true; break; - [[unlikely]] default: + case OP_C_LD: + Exec_C_LD(); + break; + case OP_C_SD: + Exec_C_SD(); + break; + case OP_C_ADDIW: + Exec_C_ADDIW(); + break; + case OP_C_ADDW: + Exec_C_ADDW(); + break; + case OP_C_SUBW: + Exec_C_SUBW(); + break; + case OP_C_SDSP: + Exec_C_SDSP(); + break; + case OP_C_LDSP: + Exec_C_LDSP(); + break; + [[unlikely]] default: std::cout << "C instruction not implemented yet" << "\n"; inst.dump(); this->NOP(); diff --git a/inc/extension_base.h b/inc/extension_base.h index f4500a4..d64ac95 100644 --- a/inc/extension_base.h +++ b/inc/extension_base.h @@ -78,6 +78,7 @@ namespace riscv_tlm { bool NOP() { logger->debug("{} ns. PC: 0x{:x}. NOP! new PC 0x{:x} ", sc_core::sc_time_stamp().value(), regs->getPC()); + logger->flush(); sc_core::sc_stop(); return true; } @@ -117,6 +118,10 @@ namespace riscv_tlm { m_instr.range(14, 12) = value; } + // For RV64 SLLI, SRLI & SRAI + virtual unsigned int get_shamt_slli() const { + return m_instr.range(25, 20); + } virtual void dump() const { std::cout << std::hex << "0x" << m_instr << std::dec << std::endl; } diff --git a/src/BASE_ISA.cpp b/src/BASE_ISA.cpp index 2506026..873a2a1 100644 --- a/src/BASE_ISA.cpp +++ b/src/BASE_ISA.cpp @@ -12,7 +12,7 @@ namespace riscv_tlm { ///// RV32 Specialization template<> - int32_t BASE_ISA::get_imm_I() const { + std::int32_t BASE_ISA::get_imm_I() const { std::uint32_t aux = 0; aux = this->m_instr.range(31, 20); @@ -73,9 +73,160 @@ namespace riscv_tlm { return static_cast(aux); } + template<> + std::uint32_t BASE_ISA::get_funct7b() const { + return this->m_instr.range(31, 25); + } + + // SLLI, SRLI and SRAI get different shamt field depending on RV32 or RV64 + template<> + bool BASE_ISA::Exec_SLLI() { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = get_shamt(); + + if (rs2 >= 0x20) { + std::cout << "ILLEGAL INSTRUCTION, shamt[5] != 0" << "\n"; + sc_core::sc_stop(); + this->RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION, this->m_instr); + + return false; + } + + shift = rs2 & 0x1F; + + calc = static_cast(this->regs->getValue(rs1)) << shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SLLI: x{:d} << {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + template<> + bool BASE_ISA::Exec_SRLI() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = rs2 & 0x1F; + + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRLI: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + template<> + bool BASE_ISA::Exec_SRAI() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + signed_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = rs2 & 0x1F; + + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRAI: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + template<> + bool BASE_ISA::Exec_SRL() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x1F; + calc = this->regs->getValue(rs1) >> shift; + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRL: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + template<> + bool BASE_ISA::Exec_SRA() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + signed_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x1F; + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRA: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + template<> + bool BASE_ISA::Exec_SLL() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x1F; + + calc = this->regs->getValue(rs1) << shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SLL: x{:d} << x{:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + ///// RV64 Specialization template<> - int64_t BASE_ISA::get_imm_I() const { + std::int64_t BASE_ISA::get_imm_I() const { std::uint64_t aux = 0; aux = this->m_instr.range(31, 20); @@ -137,4 +288,161 @@ namespace riscv_tlm { return static_cast(aux); } -} \ No newline at end of file + + template<> + std::uint32_t BASE_ISA::get_funct7b() const { + return this->m_instr.range(31, 26); + } + + // PASS + template<> + bool BASE_ISA::Exec_SLLI() { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_shamt_slli(); + + if (rs2 >= 0x40) { + std::cout << "ILLEGAL INSTRUCTION, shamt[5] > 0x40" << "\n"; + sc_core::sc_stop(); + this->RaiseException(EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION, this->m_instr); + + return false; + } + + shift = rs2 & 0x3F; + calc = this->regs->getValue(rs1) << shift; + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SLLI: x{:d} << {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + // PASS + template<> + bool BASE_ISA::Exec_SRLI() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_shamt_slli(); + + shift = rs2 & 0x3F; + + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRLI: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + // PASS + template<> + bool BASE_ISA::Exec_SRAI() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + signed_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_shamt_slli(); + + shift = rs2 & 0x3F; + + calc = static_cast(static_cast(this->regs->getValue(rs1)) >> shift); + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRAI: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + // PASS + template<> + bool BASE_ISA::Exec_SRL() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x3F; + calc = this->regs->getValue(rs1) >> shift; + + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRL: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + // PASS + template<> + bool BASE_ISA::Exec_SRA() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + signed_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x3F; + calc = static_cast(this->regs->getValue(rs1)) >> shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SRA: x{:d} >> {:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } + + // PASS + template<> + bool BASE_ISA::Exec_SLL() const { + unsigned int rd, rs1, rs2; + unsigned_T shift; + unsigned_T calc; + + rd = this->get_rd(); + rs1 = this->get_rs1(); + rs2 = this->get_rs2(); + + shift = this->regs->getValue(rs2) & 0x3F; + + calc = this->regs->getValue(rs1) << shift; + this->regs->setValue(rd, calc); + + this->logger->debug("{} ns. PC: 0x{:x}. SLL: x{:d} << x{:d} -> x{:d}(0x{:x})", + sc_core::sc_time_stamp().value(), + this->regs->getPC(), + rs1, shift, rd, calc); + + return true; + } +} +