changeset eb58f1bbeac8 in /z/repo/gem5 details: http://repo.gem5.org/gem5?cmd=changeset;node=eb58f1bbeac8 description: riscv: [Patch 3/5] Added RISCV floating point extensions RV64FD
Third of five patches adding RISC-V to GEM5. This patch adds the RV64FD extensions, which include single- and double-precision floating point instructions. Patch 1 introduced RISC-V and implemented the base instruction set, RV64I and patch 2 implemented the integer multiply extension, RV64M. Patch 4 will implement the atomic memory instructions, RV64A, and patch 5 will add support for timing, minor, and detailed CPU models that is missing from the first four patches. [Fixed exception handling in floating-point instructions to conform better to IEEE-754 2008 standard and behavior of the Chisel-generated RISC-V simulator.] [Fixed style errors in decoder.isa.] [Fixed some fuzz caused by modifying a previous patch.] Signed-off by: Alec Roelke Signed-off by: Jason Lowe-Power <ja...@lowepower.com> diffstat: src/arch/riscv/faults.cc | 7 + src/arch/riscv/faults.hh | 20 + src/arch/riscv/isa/bitfields.isa | 10 + src/arch/riscv/isa/decoder.isa | 829 +++++++++++++++++++++++++++++++++ src/arch/riscv/isa/formats/formats.isa | 1 + src/arch/riscv/isa/formats/fp.isa | 136 +++++ src/arch/riscv/isa/includes.isa | 2 + src/arch/riscv/isa/operands.isa | 11 + src/arch/riscv/registers.hh | 2 +- src/arch/riscv/utility.hh | 40 + 10 files changed, 1057 insertions(+), 1 deletions(-) diffs (truncated from 1183 to 300 lines): diff -r d92c26d481b7 -r eb58f1bbeac8 src/arch/riscv/faults.cc --- a/src/arch/riscv/faults.cc Wed Nov 30 17:10:28 2016 -0500 +++ b/src/arch/riscv/faults.cc Wed Nov 30 17:10:28 2016 -0500 @@ -72,6 +72,13 @@ } void +IllegalFrmFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst) +{ + panic("Illegal floating-point rounding mode 0x%x at pc 0x%016llx.", + frm, tc->pcState().pc()); +} + +void BreakpointFault::invoke_se(ThreadContext *tc, const StaticInstPtr &inst) { schedRelBreak(0); diff -r d92c26d481b7 -r eb58f1bbeac8 src/arch/riscv/faults.hh --- a/src/arch/riscv/faults.hh Wed Nov 30 17:10:28 2016 -0500 +++ b/src/arch/riscv/faults.hh Wed Nov 30 17:10:28 2016 -0500 @@ -40,6 +40,12 @@ namespace RiscvISA { +const uint32_t FloatInexact = 1 << 0; +const uint32_t FloatUnderflow = 1 << 1; +const uint32_t FloatOverflow = 1 << 2; +const uint32_t FloatDivZero = 1 << 3; +const uint32_t FloatInvalid = 1 << 4; + enum ExceptionCode { INST_ADDR_MISALIGNED = 0, INST_ACCESS = 1, @@ -124,6 +130,20 @@ invoke_se(ThreadContext *tc, const StaticInstPtr &inst); }; +class IllegalFrmFault: public RiscvFault +{ + private: + const uint8_t frm; + public: + IllegalFrmFault(uint8_t r) + : RiscvFault("Illegal floating-point rounding mode", INST_ILLEGAL, + SOFTWARE), + frm(r) + {} + + void invoke_se(ThreadContext *tc, const StaticInstPtr &inst); +}; + class BreakpointFault : public RiscvFault { public: diff -r d92c26d481b7 -r eb58f1bbeac8 src/arch/riscv/isa/bitfields.isa --- a/src/arch/riscv/isa/bitfields.isa Wed Nov 30 17:10:28 2016 -0500 +++ b/src/arch/riscv/isa/bitfields.isa Wed Nov 30 17:10:28 2016 -0500 @@ -75,3 +75,13 @@ // System def bitfield FUNCT12 <31:20>; def bitfield ZIMM <19:15>; + +// Floating point +def bitfield FD <11:7>; +def bitfield FS1 <19:15>; +def bitfield FS2 <24:20>; +def bitfield FS3 <31:27>; + +def bitfield ROUND_MODE <14:12>; +def bitfield CONV_SGN <24:20>; +def bitfield FUNCT2 <26:25>; diff -r d92c26d481b7 -r eb58f1bbeac8 src/arch/riscv/isa/decoder.isa --- a/src/arch/riscv/isa/decoder.isa Wed Nov 30 17:10:28 2016 -0500 +++ b/src/arch/riscv/isa/decoder.isa Wed Nov 30 17:10:28 2016 -0500 @@ -61,6 +61,17 @@ } } + 0x07: decode FUNCT3 { + format Load { + 0x2: flw({{ + Fd_bits = (uint64_t)Mem_uw; + }}); + 0x3: fld({{ + Fd_bits = Mem; + }}); + } + } + 0x0f: decode FUNCT3 { format IOp { 0x0: fence({{ @@ -144,6 +155,17 @@ } } + 0x27: decode FUNCT3 { + format Store { + 0x2: fsw({{ + Mem_uw = (uint32_t)Fs2_bits; + }}); + 0x3: fsd({{ + Mem_ud = Fs2_bits; + }}); + } + } + 0x33: decode FUNCT3 { format ROp { 0x0: decode FUNCT7 { @@ -347,6 +369,813 @@ } } + format FPR4Op { + 0x43: decode FUNCT2 { + 0x0: fmadd_s({{ + uint32_t temp; + float fs1 = reinterpret_cast<float&>(temp = Fs1_bits); + float fs2 = reinterpret_cast<float&>(temp = Fs2_bits); + float fs3 = reinterpret_cast<float&>(temp = Fs3_bits); + float fd; + + if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) { + if (issignalingnan(fs1) || issignalingnan(fs2) + || issignalingnan(fs3)) { + FFLAGS |= FloatInvalid; + } + fd = std::numeric_limits<float>::quiet_NaN(); + } else if (std::isinf(fs1) || std::isinf(fs2) || + std::isinf(fs3)) { + if (std::signbit(fs1) == std::signbit(fs2) + && !std::isinf(fs3)) { + fd = std::numeric_limits<float>::infinity(); + } else if (std::signbit(fs1) != std::signbit(fs2) + && !std::isinf(fs3)) { + fd = -std::numeric_limits<float>::infinity(); + } else { // Fs3_sf is infinity + fd = fs3; + } + } else { + fd = fs1*fs2 + fs3; + } + Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd); + }}, FloatMultOp); + 0x1: fmadd_d({{ + if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) { + if (issignalingnan(Fs1) || issignalingnan(Fs2) + || issignalingnan(Fs3)) { + FFLAGS |= FloatInvalid; + } + Fd = std::numeric_limits<double>::quiet_NaN(); + } else if (std::isinf(Fs1) || std::isinf(Fs2) || + std::isinf(Fs3)) { + if (std::signbit(Fs1) == std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = std::numeric_limits<double>::infinity(); + } else if (std::signbit(Fs1) != std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = -std::numeric_limits<double>::infinity(); + } else { + Fd = Fs3; + } + } else { + Fd = Fs1*Fs2 + Fs3; + } + }}, FloatMultOp); + } + 0x47: decode FUNCT2 { + 0x0: fmsub_s({{ + uint32_t temp; + float fs1 = reinterpret_cast<float&>(temp = Fs1_bits); + float fs2 = reinterpret_cast<float&>(temp = Fs2_bits); + float fs3 = reinterpret_cast<float&>(temp = Fs3_bits); + float fd; + + if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) { + if (issignalingnan(fs1) || issignalingnan(fs2) + || issignalingnan(fs3)) { + FFLAGS |= FloatInvalid; + } + fd = std::numeric_limits<float>::quiet_NaN(); + } else if (std::isinf(fs1) || std::isinf(fs2) || + std::isinf(fs3)) { + if (std::signbit(fs1) == std::signbit(fs2) + && !std::isinf(fs3)) { + fd = std::numeric_limits<float>::infinity(); + } else if (std::signbit(fs1) != std::signbit(fs2) + && !std::isinf(fs3)) { + fd = -std::numeric_limits<float>::infinity(); + } else { // Fs3_sf is infinity + fd = -fs3; + } + } else { + fd = fs1*fs2 - fs3; + } + Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd); + }}, FloatMultOp); + 0x1: fmsub_d({{ + if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) { + if (issignalingnan(Fs1) || issignalingnan(Fs2) + || issignalingnan(Fs3)) { + FFLAGS |= FloatInvalid; + } + Fd = std::numeric_limits<double>::quiet_NaN(); + } else if (std::isinf(Fs1) || std::isinf(Fs2) || + std::isinf(Fs3)) { + if (std::signbit(Fs1) == std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = std::numeric_limits<double>::infinity(); + } else if (std::signbit(Fs1) != std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = -std::numeric_limits<double>::infinity(); + } else { + Fd = -Fs3; + } + } else { + Fd = Fs1*Fs2 - Fs3; + } + }}, FloatMultOp); + } + 0x4b: decode FUNCT2 { + 0x0: fnmsub_s({{ + uint32_t temp; + float fs1 = reinterpret_cast<float&>(temp = Fs1_bits); + float fs2 = reinterpret_cast<float&>(temp = Fs2_bits); + float fs3 = reinterpret_cast<float&>(temp = Fs3_bits); + float fd; + + if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) { + if (issignalingnan(fs1) || issignalingnan(fs2) + || issignalingnan(fs3)) { + FFLAGS |= FloatInvalid; + } + fd = std::numeric_limits<float>::quiet_NaN(); + } else if (std::isinf(fs1) || std::isinf(fs2) || + std::isinf(fs3)) { + if (std::signbit(fs1) == std::signbit(fs2) + && !std::isinf(fs3)) { + fd = -std::numeric_limits<float>::infinity(); + } else if (std::signbit(fs1) != std::signbit(fs2) + && !std::isinf(fs3)) { + fd = std::numeric_limits<float>::infinity(); + } else { // Fs3_sf is infinity + fd = fs3; + } + } else { + fd = -(fs1*fs2 - fs3); + } + Fd_bits = (uint64_t)reinterpret_cast<uint32_t&>(fd); + }}, FloatMultOp); + 0x1: fnmsub_d({{ + if (std::isnan(Fs1) || std::isnan(Fs2) || std::isnan(Fs3)) { + if (issignalingnan(Fs1) || issignalingnan(Fs2) + || issignalingnan(Fs3)) { + FFLAGS |= FloatInvalid; + } + Fd = std::numeric_limits<double>::quiet_NaN(); + } else if (std::isinf(Fs1) || std::isinf(Fs2) + || std::isinf(Fs3)) { + if (std::signbit(Fs1) == std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = -std::numeric_limits<double>::infinity(); + } else if (std::signbit(Fs1) != std::signbit(Fs2) + && !std::isinf(Fs3)) { + Fd = std::numeric_limits<double>::infinity(); + } else { + Fd = Fs3; + } + } else { + Fd = -(Fs1*Fs2 - Fs3); + } + }}, FloatMultOp); + } + 0x4f: decode FUNCT2 { + 0x0: fnmadd_s({{ + uint32_t temp; + float fs1 = reinterpret_cast<float&>(temp = Fs1_bits); + float fs2 = reinterpret_cast<float&>(temp = Fs2_bits); + float fs3 = reinterpret_cast<float&>(temp = Fs3_bits); + float fd; + + if (std::isnan(fs1) || std::isnan(fs2) || std::isnan(fs3)) { + if (issignalingnan(fs1) || issignalingnan(fs2) + || issignalingnan(fs3)) { + FFLAGS |= FloatInvalid; + } + fd = std::numeric_limits<float>::quiet_NaN(); + } else if (std::isinf(fs1) || std::isinf(fs2) || + std::isinf(fs3)) { + if (std::signbit(fs1) == std::signbit(fs2) + && !std::isinf(fs3)) { + fd = -std::numeric_limits<float>::infinity(); + } else if (std::signbit(fs1) != std::signbit(fs2) + && !std::isinf(fs3)) { + fd = std::numeric_limits<float>::infinity(); + } else { // Fs3_sf is infinity + fd = -fs3; + } + } else { _______________________________________________ gem5-dev mailing list gem5-dev@gem5.org http://m5sim.org/mailman/listinfo/gem5-dev