arch-riscv: Using Softfloat Library to implements float operation

The Riscv float instruction could not pass riscv-tests. This patch
use Softfloat Library interface to implements float operation. The
riscv-tests float instruction tests now pass.

Jira Issue: https://gem5.atlassian.net/browse/GEM5-373

Change-Id: I2c95af8161a8d3f92c933aa82d797db5adebc574
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39735
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
kai.ren
2021-01-26 10:38:59 +08:00
committed by Kai Ren
parent 3a9d0de609
commit 28564ef315
5 changed files with 343 additions and 759 deletions

43
src/arch/riscv/fp_inst.hh Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 StreamComputing Corp.
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kai Ren
*/
#ifndef __ARCH_RISCV_FP_INST_HH__
#define __ARCH_RISCV_FP_INST_HH__
#define RM_REQUIRED \
uint_fast8_t rm = ROUND_MODE; \
uint_fast8_t frm = xc->readMiscReg(MISCREG_FRM); \
if (rm == 7) \
rm = frm; \
if (rm > 4) \
fault = std::make_shared<IllegalInstFault>("RM fault", machInst);\
softfloat_roundingMode = rm; \
#endif // __ARCH_RISCV_FP_INST_HH__

File diff suppressed because it is too large Load Diff

View File

@@ -44,83 +44,21 @@ def template FloatExecute {{
%(op_decl)s;
%(op_rd)s;
if (fault == NoFault) {
switch (ROUND_MODE) {
case 0x0:
std::fesetround(FE_TONEAREST);
break;
case 0x1:
std::fesetround(FE_TOWARDZERO);
break;
case 0x2:
std::fesetround(FE_DOWNWARD);
break;
case 0x3:
std::fesetround(FE_UPWARD);
break;
case 0x4:
// Round to nearest, ties to max magnitude not implemented
fault = std::make_shared<IllegalFrmFault>(
ROUND_MODE, machInst);
break;
case 0x7: {
uint8_t frm = xc->readMiscReg(MISCREG_FRM);
switch (frm) {
case 0x0:
std::fesetround(FE_TONEAREST);
break;
case 0x1:
std::fesetround(FE_TOWARDZERO);
break;
case 0x2:
std::fesetround(FE_DOWNWARD);
break;
case 0x3:
std::fesetround(FE_UPWARD);
break;
case 0x4:
// Round to nearest, ties to max magnitude not implemented
fault = std::make_shared<IllegalFrmFault>(
ROUND_MODE, machInst);
break;
default:
fault = std::make_shared<IllegalFrmFault>(frm, machInst);
break;
}
break;
}
default:
fault = std::make_shared<IllegalFrmFault>(ROUND_MODE,
machInst);
break;
}
RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
std::feclearexcept(FE_ALL_EXCEPT);
%(code)s;
if (fault == NoFault) {
RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
std::feclearexcept(FE_ALL_EXCEPT);
%(code)s;
if (std::fetestexcept(FE_INEXACT)) {
FFLAGS |= FloatInexact;
}
if (std::fetestexcept(FE_UNDERFLOW)) {
FFLAGS |= FloatUnderflow;
}
if (std::fetestexcept(FE_OVERFLOW)) {
FFLAGS |= FloatOverflow;
}
if (std::fetestexcept(FE_DIVBYZERO)) {
FFLAGS |= FloatDivZero;
}
if (std::fetestexcept(FE_INVALID)) {
FFLAGS |= FloatInvalid;
}
xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
}
if (fault == NoFault) {
%(op_wb)s;
}
FFLAGS |= softfloat_exceptionFlags;
softfloat_exceptionFlags = 0;
xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
}
if (fault == NoFault) {
%(op_wb)s;
}
return fault;
}
}};

View File

@@ -40,6 +40,11 @@ output header {{
#include <tuple>
#include <vector>
/* riscv softfloat library */
#include <internals.h>
#include <softfloat.h>
#include <specialize.h>
#include "arch/riscv/insts/amo.hh"
#include "arch/riscv/insts/compressed.hh"
#include "arch/riscv/insts/mem.hh"
@@ -80,6 +85,7 @@ output exec {{
#include "arch/generic/memhelpers.hh"
#include "arch/riscv/faults.hh"
#include "arch/riscv/fp_inst.hh"
#include "arch/riscv/mmu.hh"
#include "arch/riscv/reg_abi.hh"
#include "arch/riscv/registers.hh"

View File

@@ -3,6 +3,7 @@
* Copyright (c) 2014-2015 Sven Karlsson
* Copyright (c) 2019 Yifei Liu
* Copyright (c) 2020 Barkhausen Institut
* Copyright (c) 2021 StreamComputing Corp
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -45,6 +46,9 @@
#ifndef __ARCH_RISCV_REGISTERS_HH__
#define __ARCH_RISCV_REGISTERS_HH__
#include <softfloat.h>
#include <specialize.h>
#include <map>
#include <string>
#include <vector>
@@ -58,6 +62,35 @@
namespace RiscvISA
{
/* Convenience wrappers to simplify softfloat code sequences */
#define isBoxedF32(r) ((uint32_t)((r.v >> 32) + 1) == 0)
#define unboxF32(r) (isBoxedF32(r) ? (uint32_t)r.v : defaultNaNF32UI)
#define unboxF64(r) (r.v)
typedef int64_t sreg_t;
typedef uint64_t reg_t;
typedef float64_t freg_t;
inline float32_t f32(uint32_t v) { return { v }; }
inline float64_t f64(uint64_t v) { return { v }; }
inline float32_t f32(freg_t r) { return f32(unboxF32(r)); }
inline float64_t f64(freg_t r) { return f64(unboxF64(r)); }
inline freg_t freg(float32_t f) { return {((uint64_t)-1 << 32) | f.v}; }
inline freg_t freg(float64_t f) { return {f}; }
inline freg_t freg(uint_fast16_t f) { return {f}; }
#define F32_SIGN ((uint32_t)1 << 31)
#define F64_SIGN ((uint64_t)1 << 63)
#define fsgnj32(a, b, n, x) \
f32((f32(a).v & ~F32_SIGN) | \
((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN))
#define fsgnj64(a, b, n, x) \
f64((f64(a).v & ~F64_SIGN) | \
((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN))
#define sext32(x) ((sreg_t)(int32_t)(x))
#define zext32(x) ((reg_t)(uint32_t)(x))
#define sext_xlen(x) (((sreg_t)(x) << (64-xlen)) >> (64-xlen))
#define zext_xlen(x) (((reg_t)(x) << (64-xlen)) >> (64-xlen))
// Not applicable to RISC-V
using VecElem = ::DummyVecElem;
using VecReg = ::DummyVecReg;