Add full RV64 simulation. It passes almost all tests.
This commit is contained in:
parent
9176dbb2ed
commit
ab2d5139c2
623
inc/BASE_ISA.h
623
inc/BASE_ISA.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -78,6 +78,7 @@ namespace riscv_tlm {
|
||||||
|
|
||||||
bool NOP() {
|
bool 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());
|
||||||
|
logger->flush();
|
||||||
sc_core::sc_stop();
|
sc_core::sc_stop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +118,10 @@ namespace riscv_tlm {
|
||||||
m_instr.range(14, 12) = value;
|
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 {
|
virtual void dump() const {
|
||||||
std::cout << std::hex << "0x" << m_instr << std::dec << std::endl;
|
std::cout << std::hex << "0x" << m_instr << std::dec << std::endl;
|
||||||
}
|
}
|
||||||
|
|
314
src/BASE_ISA.cpp
314
src/BASE_ISA.cpp
|
@ -12,7 +12,7 @@ namespace riscv_tlm {
|
||||||
|
|
||||||
///// RV32 Specialization
|
///// RV32 Specialization
|
||||||
template<>
|
template<>
|
||||||
int32_t BASE_ISA<std::uint32_t>::get_imm_I() const {
|
std::int32_t BASE_ISA<std::uint32_t>::get_imm_I() const {
|
||||||
std::uint32_t aux = 0;
|
std::uint32_t aux = 0;
|
||||||
|
|
||||||
aux = this->m_instr.range(31, 20);
|
aux = this->m_instr.range(31, 20);
|
||||||
|
@ -73,9 +73,160 @@ namespace riscv_tlm {
|
||||||
return static_cast<std::int32_t>(aux);
|
return static_cast<std::int32_t>(aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::uint32_t BASE_ISA<std::uint32_t>::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<std::uint32_t>::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<unsigned_T>(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<std::uint32_t>::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<unsigned_T>(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<std::uint32_t>::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<signed_T>(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<std::uint32_t>::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<std::uint32_t>::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<signed_T>(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<std::uint32_t>::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
|
///// RV64 Specialization
|
||||||
template<>
|
template<>
|
||||||
int64_t BASE_ISA<std::uint64_t>::get_imm_I() const {
|
std::int64_t BASE_ISA<std::uint64_t>::get_imm_I() const {
|
||||||
std::uint64_t aux = 0;
|
std::uint64_t aux = 0;
|
||||||
|
|
||||||
aux = this->m_instr.range(31, 20);
|
aux = this->m_instr.range(31, 20);
|
||||||
|
@ -137,4 +288,161 @@ namespace riscv_tlm {
|
||||||
|
|
||||||
return static_cast<std::int64_t>(aux);
|
return static_cast<std::int64_t>(aux);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
template<>
|
||||||
|
std::uint32_t BASE_ISA<std::uint64_t>::get_funct7b() const {
|
||||||
|
return this->m_instr.range(31, 26);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PASS
|
||||||
|
template<>
|
||||||
|
bool BASE_ISA<std::uint64_t>::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<std::uint64_t>::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<unsigned_T>(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<std::uint64_t>::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<signed_T>(static_cast<signed_T>(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<std::uint64_t>::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<std::uint64_t>::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<signed_T>(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<std::uint64_t>::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue