M extension for RV64
This commit is contained in:
parent
56b00aecd8
commit
643b880be3
|
@ -25,7 +25,11 @@ namespace riscv_tlm {
|
|||
OP_M_DIVU,
|
||||
OP_M_REM,
|
||||
OP_M_REMU,
|
||||
|
||||
OP_M_MULW,
|
||||
OP_M_DIVW,
|
||||
OP_M_DIVUW,
|
||||
OP_M_REMW,
|
||||
OP_M_REMUW,
|
||||
OP_M_ERROR
|
||||
} op_M_Codes;
|
||||
|
||||
|
@ -38,6 +42,11 @@ namespace riscv_tlm {
|
|||
M_DIVU = 0b101,
|
||||
M_REM = 0b110,
|
||||
M_REMU = 0b111,
|
||||
M_MULW = 0b000,
|
||||
M_DIVW = 0b100,
|
||||
M_DIVUW = 0b101,
|
||||
M_REMW = 0b110,
|
||||
M_REMUW = 0b111,
|
||||
} M_Codes;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +70,7 @@ namespace riscv_tlm {
|
|||
*/
|
||||
[[nodiscard]] op_M_Codes decode() const {
|
||||
|
||||
if (this->m_instr.range(6,0) == 0b110011) {
|
||||
switch (opcode()) {
|
||||
case M_MUL:
|
||||
return OP_M_MUL;
|
||||
|
@ -90,6 +100,29 @@ namespace riscv_tlm {
|
|||
return OP_M_ERROR;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (opcode()) {
|
||||
case M_MULW:
|
||||
return OP_M_MULW;
|
||||
break;
|
||||
case M_DIVW:
|
||||
return OP_M_DIVW;
|
||||
break;
|
||||
case M_DIVUW:
|
||||
return OP_M_DIVUW;
|
||||
break;
|
||||
case M_REMW:
|
||||
return OP_M_REMW;
|
||||
break;
|
||||
case M_REMUW:
|
||||
return OP_M_REMUW;
|
||||
break;
|
||||
[[unlikely]] default:
|
||||
return OP_M_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return OP_M_ERROR;
|
||||
}
|
||||
|
@ -100,107 +133,42 @@ namespace riscv_tlm {
|
|||
|
||||
void Exec_M_MUL() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t multiplier, multiplicand;
|
||||
signed_T multiplier, multiplicand;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::int32_t>(extension_base<T>::regs->getValue(rs1));
|
||||
multiplicand = static_cast<std::int32_t>(extension_base<T>::regs->getValue(rs2));
|
||||
|
||||
multiplier = static_cast<signed_T>(this->regs->getValue(rs1));
|
||||
multiplicand = static_cast<signed_T>(this->regs->getValue(rs2));
|
||||
result = static_cast<std::int64_t>(multiplier * multiplicand);
|
||||
result = result & 0x00000000FFFFFFFF;
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MUL: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
extension_base<T>::regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
this->regs->setValue(rd, static_cast<signed_T>(result));
|
||||
|
||||
void Exec_M_MULH() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t multiplier, multiplicand;
|
||||
std::int64_t result;
|
||||
std::int32_t ret_value;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
multiplicand = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
|
||||
result = static_cast<std::int64_t>(multiplier) * static_cast<std::int64_t>(multiplicand);
|
||||
|
||||
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
|
||||
this->regs->setValue(rd, ret_value);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULH: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MUL: x{:d}({:d}) * x{:d}({:d}) -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
rs1, rs2, multiplier, multiplicand, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_MULHSU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t multiplier;
|
||||
std::uint32_t multiplicand;
|
||||
std::int64_t result;
|
||||
void Exec_M_MULH() const;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
void Exec_M_MULHSU() const;
|
||||
|
||||
multiplier = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
result = static_cast<std::int64_t>(multiplier * static_cast<std::uint64_t>(multiplicand));
|
||||
result = (result >> 32) & 0x00000000FFFFFFFF;
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHSU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_MULHU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t multiplier, multiplicand;
|
||||
std::uint64_t result;
|
||||
std::int32_t ret_value;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
multiplicand = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
|
||||
result = static_cast<std::uint64_t>(multiplier) * static_cast<std::uint64_t>(multiplicand);
|
||||
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
|
||||
this->regs->setValue(rd, ret_value);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
void Exec_M_MULHU() const;
|
||||
|
||||
void Exec_M_DIV() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t divisor, dividend;
|
||||
signed_T divisor, dividend;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
divisor = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
dividend = this->regs->getValue(rs1);
|
||||
divisor = this->regs->getValue(rs2);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = -1;
|
||||
|
@ -208,10 +176,9 @@ namespace riscv_tlm {
|
|||
result = 0x0000000080000000;
|
||||
} else {
|
||||
result = dividend / divisor;
|
||||
result = result & 0x00000000FFFFFFFF;
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.DIV: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
|
@ -221,7 +188,7 @@ namespace riscv_tlm {
|
|||
|
||||
void Exec_M_DIVU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t divisor, dividend;
|
||||
unsigned_T divisor, dividend;
|
||||
std::uint64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
|
@ -235,10 +202,9 @@ namespace riscv_tlm {
|
|||
result = -1;
|
||||
} else {
|
||||
result = dividend / divisor;
|
||||
result = result & 0x00000000FFFFFFFF;
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.DIVU: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
|
@ -248,15 +214,15 @@ namespace riscv_tlm {
|
|||
|
||||
void Exec_M_REM() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t divisor, dividend;
|
||||
std::int32_t result;
|
||||
signed_T divisor, dividend;
|
||||
signed_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
divisor = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
dividend = this->regs->getValue(rs1);
|
||||
divisor = this->regs->getValue(rs2);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = dividend;
|
||||
|
@ -268,7 +234,7 @@ namespace riscv_tlm {
|
|||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REM: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REM: x{:d} % x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
|
@ -276,15 +242,15 @@ namespace riscv_tlm {
|
|||
|
||||
void Exec_M_REMU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t divisor, dividend;
|
||||
std::uint32_t result;
|
||||
unsigned_T divisor, dividend;
|
||||
unsigned_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
divisor = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
dividend = this->regs->getValue(rs1);
|
||||
divisor = this->regs->getValue(rs2);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = dividend;
|
||||
|
@ -292,14 +258,145 @@ namespace riscv_tlm {
|
|||
result = dividend % divisor;
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REMU: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REMU: x{:d} % x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_MULW() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t multiplier, multiplicand;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::uint32_t>(this->regs->getValue(rs1) & 0x00000000FFFFFFFF);
|
||||
multiplicand = static_cast<std::uint32_t>(this->regs->getValue(rs2) & 0x00000000FFFFFFFF);
|
||||
result = static_cast<std::int32_t>((multiplier * multiplicand) & 0x00000000FFFFFFFF);
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULW: x{:d}({:d}) * x{:d}({:d}) -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, multiplier, multiplicand, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_DIVW() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t divisor, dividend;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::int32_t>(this->regs->getValue(rs1) & 0x00000000FFFFFFFF);
|
||||
divisor = static_cast<std::int32_t>(this->regs->getValue(rs2) & 0x00000000FFFFFFFF);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = -1;
|
||||
} else if ((divisor == -1) && (dividend == static_cast<std::int32_t>(0x80000000))) {
|
||||
result = 0x0000000080000000;
|
||||
} else {
|
||||
result = dividend / divisor;
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.DIVW: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_DIVUW() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t divisor, dividend;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::uint32_t>(this->regs->getValue(rs1) & 0x00000000FFFFFFFF);
|
||||
divisor = static_cast<std::uint32_t>(this->regs->getValue(rs2) & 0x00000000FFFFFFFF);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = -1;
|
||||
} else if ((divisor == 0xFFFFFFFF) && (dividend == static_cast<std::uint32_t>(0x80000000))) {
|
||||
result = 0x0000000080000000;
|
||||
} else {
|
||||
result = static_cast<std::int32_t>(dividend / divisor);
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.DIVUW: x{:d} / x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_REMW() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t divisor, dividend;
|
||||
signed_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::int32_t>(this->regs->getValue(rs1) & 0x00000000FFFFFFFF);
|
||||
divisor = static_cast<std::int32_t>(this->regs->getValue(rs2) & 0x00000000FFFFFFFF);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = dividend;
|
||||
} else if (divisor == -1) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = dividend % divisor;
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REMW: x{:d} % x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
void Exec_M_REMUW() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t divisor, dividend;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
dividend = static_cast<std::uint32_t>(this->regs->getValue(rs1) & 0x00000000FFFFFFFF);
|
||||
divisor = static_cast<std::uint32_t>(this->regs->getValue(rs2) & 0x00000000FFFFFFFF);
|
||||
|
||||
if (divisor == 0) {
|
||||
result = static_cast<std::int32_t>(dividend);
|
||||
} else {
|
||||
result = static_cast<std::int32_t>(dividend % divisor);
|
||||
}
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.REMUW: x{:d}({:d}) % x{:d}({:d}) -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, dividend, rs2, divisor, rd, result);
|
||||
}
|
||||
|
||||
bool process_instruction(Instruction &inst) {
|
||||
this->setInstr(inst.getInstr());
|
||||
|
||||
|
@ -328,6 +425,21 @@ namespace riscv_tlm {
|
|||
case OP_M_REMU:
|
||||
Exec_M_REMU();
|
||||
break;
|
||||
case OP_M_MULW:
|
||||
Exec_M_MULW();
|
||||
break;
|
||||
case OP_M_DIVW:
|
||||
Exec_M_DIVW();
|
||||
break;
|
||||
case OP_M_DIVUW:
|
||||
Exec_M_DIVUW();
|
||||
break;
|
||||
case OP_M_REMW:
|
||||
Exec_M_REMW();
|
||||
break;
|
||||
case OP_M_REMUW:
|
||||
Exec_M_REMUW();
|
||||
break;
|
||||
[[unlikely]] default:
|
||||
std::cout << "M instruction not implemented yet" << "\n";
|
||||
inst.dump();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace riscv_tlm {
|
|||
}
|
||||
|
||||
extension_t Instruction::check_extension() const {
|
||||
if (((m_instr & 0x0000007F) == 0b0110011)
|
||||
if ((((m_instr & 0x0000007F) == 0b0110011) || ((m_instr & 0x0000007F) == 0b0111011))
|
||||
&& (((m_instr & 0x7F000000) >> 25) == 0b0000001)) {
|
||||
return M_EXTENSION;
|
||||
} else if ((m_instr & 0x0000007F) == 0b0101111) {
|
||||
|
|
|
@ -7,4 +7,162 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "M_extension.h"
|
||||
namespace riscv_tlm {
|
||||
// RV32
|
||||
template<>
|
||||
void M_extension<std::uint32_t>::Exec_M_MULH() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
signed_T multiplier, multiplicand;
|
||||
std::int64_t result;
|
||||
signed_T ret_value;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = this->regs->getValue(rs1);
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
|
||||
result = static_cast<std::int64_t>(multiplier) * static_cast<std::int64_t>(multiplicand);
|
||||
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
|
||||
|
||||
this->regs->setValue(rd, ret_value);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULH: x{:d}({:d}) * x{:d}({:d}) -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, multiplier, rs2, multiplicand, rd, result);
|
||||
}
|
||||
|
||||
template<>
|
||||
void M_extension<std::uint32_t>::Exec_M_MULHSU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::int32_t multiplier;
|
||||
std::uint32_t multiplicand;
|
||||
std::int64_t result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
result = static_cast<std::int64_t>(multiplier * static_cast<std::uint64_t>(multiplicand));
|
||||
result = (result >> 32) & 0x00000000FFFFFFFF;
|
||||
this->regs->setValue(rd, static_cast<std::int32_t>(result));
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHSU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
template<>
|
||||
void M_extension<std::uint32_t>::Exec_M_MULHU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
std::uint32_t multiplier, multiplicand;
|
||||
std::uint64_t result;
|
||||
std::int32_t ret_value;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = static_cast<std::int32_t>(this->regs->getValue(rs1));
|
||||
multiplicand = static_cast<std::int32_t>(this->regs->getValue(rs2));
|
||||
|
||||
result = static_cast<std::uint64_t>(multiplier) * static_cast<std::uint64_t>(multiplicand);
|
||||
ret_value = static_cast<std::int32_t>((result >> 32) & 0x00000000FFFFFFFF);
|
||||
this->regs->setValue(rd, ret_value);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
|
||||
// RV64
|
||||
// I need to use SystemC bigint with 128 bits to perform 64 x 64 bits multiplication and keep the high half
|
||||
template<>
|
||||
void M_extension<std::uint64_t>::Exec_M_MULH() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
signed_T multiplier, multiplicand;
|
||||
signed_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = this->regs->getValue(rs1);
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
sc_dt::sc_bigint<128> mul = multiplier;
|
||||
sc_dt::sc_bigint<128> muld = multiplicand;
|
||||
sc_dt::sc_bigint<128> res = mul * muld;
|
||||
result = res.range(127, 64).to_int64();
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULH: x{:d}({:d}) * x{:d}({:d}) -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, multiplier, rs2, multiplicand, rd, result);
|
||||
}
|
||||
|
||||
template<>
|
||||
void M_extension<std::uint64_t>::Exec_M_MULHSU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
signed_T multiplier;
|
||||
unsigned_T multiplicand;
|
||||
signed_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = this->regs->getValue(rs1);
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
sc_dt::sc_bigint<128> mul = multiplier;
|
||||
sc_dt::sc_bigint<128> muld = multiplicand;
|
||||
sc_dt::sc_bigint<128> res = mul * muld;
|
||||
result = res.range(127, 64).to_int64();
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHSU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
template<>
|
||||
void M_extension<std::uint64_t>::Exec_M_MULHU() const {
|
||||
unsigned int rd, rs1, rs2;
|
||||
unsigned_T multiplier, multiplicand;
|
||||
unsigned_T result;
|
||||
|
||||
rd = this->get_rd();
|
||||
rs1 = this->get_rs1();
|
||||
rs2 = this->get_rs2();
|
||||
|
||||
multiplier = this->regs->getValue(rs1);
|
||||
multiplicand = this->regs->getValue(rs2);
|
||||
|
||||
sc_dt::sc_bigint<128> mul = multiplier;
|
||||
sc_dt::sc_bigint<128> muld = multiplicand;
|
||||
sc_dt::sc_bigint<128> res = mul * muld;
|
||||
result = res.range(127, 64).to_uint64();
|
||||
|
||||
this->regs->setValue(rd, result);
|
||||
|
||||
this->logger->debug("{} ns. PC: 0x{:x}. M.MULHU: x{:d} * x{:d} -> x{:d}({:d})",
|
||||
sc_core::sc_time_stamp().value(),
|
||||
this->regs->getPC(),
|
||||
rs1, rs2, rd, result);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue