FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

softfloatを使ってISSの浮動小数点命令を実装しよう(1)

softfloatは、浮動小数点をソフトウェアで実現するためのライブラリだ。

Berkeley SoftFloat

今までは整数命令ばかり実装していたけど、MIPS64やRISC-Vも注目を浴びてきたということもあり、浮動小数点の命令も実装していこう。 そのためには、x86の命令を使って実装するのもいいけれど、より制御にしやすいsoftfloatを使っていこう。

softfloatはどのような仕組みになっているのか

浮動小数点の型定義

例えば、単精度浮動小数点の加算のための関数は以下のように実装されている。

  • f32_add.c
float32_t f32_add( float32_t a, float32_t b )
{
    union ui32_f32 uA;
    uint_fast32_t uiA;
    bool signA;

softfloatの浮動小数点の型定義

ここで、float32_tは以下のように定義されている。

typedef struct { uint32_t v; } float32_t;
typedef struct { uint64_t v; } float64_t;
typedef struct { uint64_t v[2]; } float128_t;

基本的に整数型の構造体になっており、これをf32_add内で分解して加算を実行するようになっている。

つまり、ISSでf32_addを呼び出す前に、型を変換する必要があるわけだ。

softfloatを用いた浮動小数点命令の実装

github.com

void InstEnv::MIPS64_INST_ADD_S (Word_t inst_hex)
{
...
    Word_t  rs1_val  = m_env->ReadFReg<Word_t> (rs1_addr);
    Word_t  rs2_val  = m_env->ReadFReg<Word_t> (rs2_addr);

    Word_t res = InstOps::FloatAdd (rs1_val, rs2_val);
    m_env->WriteFReg<Word_t> (rd_addr, res);
}

ReadFRegにより浮動小数レジスタから値を読み出し、FloatAdd()関数を介して浮動小数点加算を実行する。その結果をWriteFRegに返す。 このために、FloatAdd()関数は以下のように実装されている。

Word_t InstOps::FloatAdd (Word_t op1, Word_t op2)
{
    float32_t f_op1, f_op2;
    f_op1.v = op1;
    f_op2.v = op2;

    float32_t f_res = f32_add(f_op1, f_op2);
    Word_t    res   = f_res.v;

    return res;
}

一旦f_op1, f_op2という型に載せ変え、f32_add()を呼び出した上で再度Word_t(=整数型)に変換して戻す。 これにより、浮動小数点の命令をsoftfloatで実現できるようになる訳だ。

softfloatライブラリの構築

softfloatの関数群をコンパイルし、ライブラリを作成しよう。

github.com

下記のようなCMakeLists.txtを作成して、ライブラリを生成した。

add_library (softfloat
  ../SoftFloat-3a/source/extF80_add.c
  ../SoftFloat-3a/source/extF80_div.c
  ../SoftFloat-3a/source/extF80_eq.c
...
)

以下のようにしてMakefileを作成し、コンパイルする。

$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vagrant/swimmer_iss/vendor/softfloat/build
$ make
[  0%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/extF80_add.c.o
[  0%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/extF80_div.c.o
...
[ 99%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/8086-SSE/s_propagateNaNF32UI.c.o
[ 99%] Building C object CMakeFiles/softfloat.dir/home/vagrant/swimmer_iss/vendor/softfloat/SoftFloat-3a/source/8086-SSE/s_propagateNaNF64UI.c.o
[100%] Linking C static library libsoftfloat.a
[100%] Built target softfloat

$ ls -1
CMakeCache.txt
CMakeFiles
cmake_install.cmake
CMakeLists.txt
cpp_source
libsoftfloat.a
Makefile
platform.h

ISSへのsoftfloatへの埋め込み

libsoftfloat.aが作成された。これをISSのリンク時に接続すれば良い。

github.com

add_library (core_mips64
  ../src/mips64_env.cpp
  ../src/env.cpp
  ../src/trace.cpp
  ../src/inst_print.cpp
  ../src/inst_mnemonic.cpp
...
)

target_link_libraries (core_mips64 softfloat)