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

Reply via email to