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 <[email protected]>
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
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev