Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need assistance for Executing my targeted workload on spike RISC-V ISA after adding custom trigonometric Instructions #1747

Open
baul-iisc opened this issue Jul 25, 2024 · 5 comments

Comments

@baul-iisc
Copy link

Hello team,
I have added the trigonometric instructions on riscv-gnu-toolchain. Now I am specifically looking for the steps required/process to compile my workload in Spike and Gem5 with these newly added instructions and then characterize the workload to evaluate the performance impact of these instructions.
I would greatly appreciate it if someone could provide guidance on how to compile code that utilizes these newly added instructions and execute it on Spike pk to characterize the workload.
Thank you in advance for your assistance.

@TommyMurphyTM1234
Copy link
Contributor

I would greatly appreciate it if someone could provide guidance on how to compile code that utilizes these newly added instructions and execute it on Spike pk to characterize the workload.

As I said here:

you can use inline assembly to compile your custom instructions into a RISC-V executable using a RISC-V toolchain that has been extended to support those instructions.

You'll probably need to explain in more detail what exactly you mean by this:

execute it on Spike pk to characterize the workload.

What sort of "characterization" do you mean?

It's also confusing that you mention Spike and Gem5 when your focus seems to be specifically on Spike (I think)?

@ved-rivos
Copy link
Contributor

Here are some examples of unit tests that can be run on spike: https://github.com/riscv-software-src/riscv-tests

@baul-iisc
Copy link
Author

baul-iisc commented Jul 25, 2024

I am aiming to characterize some lists of specialized scientific computing workload that comprises a mix of floating-point computations and numerous trigonometric operations. Currently, these trigonometric operations are implemented using a software library. I am interested in determining whether implementing these operations in hardware provides any execution time benefits. Specifically, I want to assess the percentage improvement in performance.

This information is crucial for deciding whether to proceed with the hardware implementation of trigonometric operations. Given the substantial size and complexity of these algorithms, modifying the code to use inline assembly would be a significant undertaking.

@TommyMurphyTM1234
Copy link
Contributor

Given the substantial size and complexity of these algorithms, modifying the code to use inline assembly would be a significant undertaking.

In that case then you'll probably have to modify the compiler so that it can generate your custom instructions when it detects appropriate intermediate code patterns. This is not a trivial exercise for someone not familiar with compiler toolchain internals. You'll probably need to ask in an appropriate GCC and/or LLVM/Clang (depending on what toolchain you're going to use) forum. There are mailing lists and other discussion forums for these projects that may be relevant to this topic.

@baul-iisc
Copy link
Author

baul-iisc commented Jul 27, 2024

Hello team,
I am trying to add custom trigonometric instructions on spike riscv-gnu-toolchain to execute my workload and do an assesment of performance improvement with this newly added instructions, but when I gave the command sudo make build-sim, it it throwing errors. PLease suggest if there is any mistake in the following process/ or if I am missing something. THse trigonometric instructions I want use similar to the single and double precision fsqrt instruction. The steps I am following is given below, please let me know where i am making any mistake or missing anything:

  1. I added the MASK_ins and MATCH_ins to riscv-gnu-toolchain/riscv-binutils/include/opcode/riscv-opc.h.
    #define MATCH_GCD 0x6027
    #define MASK_GCD 0xfe00707f
    #define MATCH_FACT 0x2b
    #define MASK_FACT 0x7f
    #define MATCH_MOD 0x200006b
    #define MASK_MOD 0xfe00707f
    #define MATCH_FSIN_S 0x59000053
    #define MASK_FSIN_S 0xfff0007f
    #define MATCH_FCOS_S 0x5b000053
    #define MASK_FCOS_S 0xfff0007f
    #define MATCH_FTAN_S 0x5d000053
    #define MASK_FTAN_S 0xfff0007f
    #define MATCH_FSIN_D 0x53000053
    #define MASK_FSIN_D 0xfff0007f
    #define MATCH_FCOS_D 0x55000053
    #define MASK_FCOS_D 0xfff0007f
    #define MATCH_FTAN_D 0x57000053
    #define MASK_FTAN_D 0xfff0007f

#ifdef DECLARE_INSN
DECLARE_INSN(mod, MATCH_MOD, MASK_MOD)
DECLARE_INSN(gcd, MATCH_GCD, MASK_GCD)
DECLARE_INSN(fact, MATCH_FACT, MASK_FACT)
DECLARE_INSN(fsin_s, MATCH_FSIN_S, MASK_FSIN_S)
DECLARE_INSN(fcos_s, MATCH_FCOS_S, MASK_FCOS_S)
DECLARE_INSN(ftan_s, MATCH_FTAN_S, MASK_FTAN_S)
DECLARE_INSN(fsin_d, MATCH_FSIN_D, MASK_FSIN_D)
DECLARE_INSN(fcos_d, MATCH_FCOS_D, MASK_FCOS_D)
DECLARE_INSN(ftan_d, MATCH_FTAN_D, MASK_FTAN_D)

  1. Then, in riscv-gnu-toolchain/riscv-binutils/opcodes/riscv-opc.c I add the following content:

{"mod", 0, INSN_CLASS_I, "d,s,t", MATCH_MOD, MASK_MOD, match_opcode, 0 },
{"gcd", 0, INSN_CLASS_I, "d,s,t", MATCH_GCD, MASK_GCD, match_opcode, 0 },
{"fact", 0, INSN_CLASS_I, "d,a", MATCH_FACT, MASK_FACT, match_opcode, 0 },
// Single-precision floating-point instruction subset
{"fsin.s", 0, INSN_CLASS_F_INX, "D,S", MATCH_FSIN_S|MASK_RM, MASK_FSIN_S|MASK_RM, match_opcode, 0 },
{"fsin.s", 0, INSN_CLASS_F_INX, "D,S,m", MATCH_FSIN_S, MASK_FSIN_S, match_opcode, 0 },
{"fcos.s", 0, INSN_CLASS_F_INX, "D,S", MATCH_FCOS_S|MASK_RM, MASK_FCOS_S|MASK_RM, match_opcode, 0 },
{"fcos.s", 0, INSN_CLASS_F_INX, "D,S,m", MATCH_FCOS_S, MASK_FCOS_S, match_opcode, 0 },
{"ftan.s", 0, INSN_CLASS_F_INX, "D,S", MATCH_FTAN_S|MASK_RM, MASK_FTAN_S|MASK_RM, match_opcode, 0 },
{"ftan.s", 0, INSN_CLASS_F_INX, "D,S,m", MATCH_FTAN_S, MASK_FTAN_S, match_opcode, 0 },

/* Double-precision floating-point instruction subset. */
{"fsin.d", 0, INSN_CLASS_D_INX, "D,S", MATCH_FSIN_D|MASK_RM, MASK_FSIN_D|MASK_RM, match_opcode, 0 },
{"fsin.d", 0, INSN_CLASS_D_INX, "D,S,m", MATCH_FSIN_D, MASK_FSIN_D, match_opcode, 0 },
{"fcos.d", 0, INSN_CLASS_D_INX, "D,S", MATCH_FCOS_D|MASK_RM, MASK_FCOS_D|MASK_RM, match_opcode, 0 },
{"fcos.d", 0, INSN_CLASS_D_INX, "D,S,m", MATCH_FCOS_D, MASK_FCOS_D, match_opcode, 0 },
{"ftan.d", 0, INSN_CLASS_D_INX, "D,S", MATCH_FTAN_D|MASK_RM, MASK_FTAN_D|MASK_RM, match_opcode, 0 },
{"ftan.d", 0, INSN_CLASS_D_INX, "D,S,m", MATCH_FTAN_D, MASK_FTAN_D, match_opcode, 0 },

  1. After that , I recompiled my riscv-gnu-toolchain. with the configuration scripts: ./configure --prefix=$RISCV --host=riscv64-unknown-elf --with-arch=rv64gcv --with-abi=lp64d --with-sim=spike --enable-multilib

  2. and build and intall with the command: sudo make -j$(nproc) && sudo make build-sim

  3. To achieve required functionality, I want to simulate these trigonometric instructions in Spike and gcc.So I firstly add MATCH_ins and MASK_ins in spike/riscv/encoding.h,
    #define MATCH_GCD 0x6027
    #define MASK_GCD 0xfe00707f
    #define MATCH_FACT 0x2b
    #define MASK_FACT 0x7f
    #define MATCH_MOD 0x200006b
    #define MASK_MOD 0xfe00707f
    #define MATCH_FSIN_S 0x59000053
    #define MASK_FSIN_S 0xfff0007f
    #define MATCH_FCOS_S 0x5b000053
    #define MASK_FCOS_S 0xfff0007f
    #define MATCH_FTAN_S 0x5d000053
    #define MASK_FTAN_S 0xfff0007f
    #define MATCH_FSIN_D 0x53000053
    #define MASK_FSIN_D 0xfff0007f
    #define MATCH_FCOS_D 0x55000053
    #define MASK_FCOS_D 0xfff0007f
    #define MATCH_FTAN_D 0x57000053
    #define MASK_FTAN_D 0xfff0007f

  4. then I make the files named fsin_s.h, fsin_d.h, fcos_s.h, fcos_d.h, ftan_s.h, ftan_d.h in spike/riscv/insns, I add the following content:
    //fsin_s.h file with
    require_either_extension('F', EXT_ZFINX);
    require_fp;
    softfloat_roundingMode = RM;
    WRITE_FRD_F(f32_sin(FRS1_F));
    set_fp_exceptions;

//fsin_d.g file with
require_either_extension('D', EXT_ZDINX);
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD_D(f64_sin(FRS1_D));
set_fp_exceptions;

//fcos_s.h file with
require_either_extension('F', EXT_ZFINX);
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD_F(f32_cos(FRS1_F));
set_fp_exceptions;

//fcos_d.h file with
require_either_extension('D', EXT_ZDINX);
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD_D(f64_cos(FRS1_D));
set_fp_exceptions;

//ftan_s.h file with
require_either_extension('F', EXT_ZFINX);
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD_F(f32_tan(FRS1_F));
set_fp_exceptions;

//ftan_d.h file with
require_either_extension('D', EXT_ZDINX);
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD_D(f64_tan(FRS1_D));
set_fp_exceptions;

  1. Then , in spike/riscv/riscv.mk.in file, I added the following:
    riscv_insn_ext_f =
    fsin_s
    fcos_s
    ftan_s
    .
    .
    .

riscv_insn_ext_d =
fsin_d
fcos_d
ftan_d
.
.
.

  1. Then in spike/disasm/disasm.cc file , I added the following:

if (isa->extension_enabled('F')) {
DEFINE_FR1TYPE(fsin_s);
DEFINE_FR1TYPE(fcos_s);
DEFINE_FR1TYPE(ftan_s);
.
.

if (isa->extension_enabled(EXT_ZFINX)) {
DEFINE_R1TYPE(fsin_s);
DEFINE_R1TYPE(fcos_s);
DEFINE_R1TYPE(ftan_s);
.
.
.

if (isa->extension_enabled('D')) {
DEFINE_FR1TYPE(fsin_d);
DEFINE_FR1TYPE(fcos_d);
DEFINE_FR1TYPE(ftan_d);
.
.
.

if (isa->extension_enabled(EXT_ZDINX)) {
DEFINE_R1TYPE(fsin_d);
DEFINE_R1TYPE(fcos_d);
DEFINE_R1TYPE(ftan_d);
.
.
.

  1. Then I added the following in gcc/gcc/config/riscv/riscv.md:

(define_c_enum "unspec"
[
UNSPEC_SIN
UNSPEC_COS
UNSPEC_TAN
// Add other UNSPEC values if needed
])

(define_attr "type"
.....fsin,fcos,ftan,.....

(define_insn "sin2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")]
UNSPEC_SIN))]
"(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
{
return "fsin.\t%0,%1";
}
[(set_attr "type" "fsin")
(set_attr "mode" "")])

(define_insn "cos2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")]
UNSPEC_COS))]
"(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
{
return "fcos.\t%0,%1";
}
[(set_attr "type" "fcos")
(set_attr "mode" "")])

(define_insn "tan2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")]
UNSPEC_TAN))]
"(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
{
return "ftan.\t%0,%1";
}
[(set_attr "type" "ftan")
(set_attr "mode" "")])

  1. Then I have added the following in the gcc/gcc/rtl.def
    /* Trigonometric functions */
    DEF_RTL_EXPR(SIN, "sin", "e", RTX_UNARY)
    DEF_RTL_EXPR(COS, "cos", "e", RTX_UNARY)
    DEF_RTL_EXPR(TAN, "tan", "e", RTX_UNARY)

  2. lastly I added f32_sin.c, f64_sin.c, f32_cos.c, f64_cos.c, f32_tan.c, f64_tan.c to the both directory riscv-gnu-toolchain/pk/softfloat and riscv-gnu-toolchain/spike/softfloat.

  3. then When I tried to build and install the riscv-gnu-toolchain again# then run the config command as follows:
    ./configure --prefix=$RISCV --host=riscv64-unknown-elf --with-arch=rv64gcv --with-abi=lp64d --with-sim=spike --enable-multilib

next run the build and installed command

sudo make -j$(nproc) && sudo make build-sim
But getting the following errors:
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/overlap_list.h: In member function ‘void processor_t::register_base_instructions()’:
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/overlap_list.h:20:22: error: ‘rstsa16_supported’ was not declared in this scope; did you mean ‘xperm16_supported’?
20 | DECLARE_OVERLAP_INSN(rstsa16, EXT_ZPN)
| ^~~~~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/processor.cc:1167:45: note: in definition of macro ‘DECLARE_OVERLAP_INSN’
1167 | #define DECLARE_OVERLAP_INSN(name, ext) { name##_supported = isa->extension_enabled(ext); }
| ^~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/overlap_list.h:21:22: error: ‘rstsa32_supported’ was not declared in this scope; did you mean ‘xperm32_supported’?
21 | DECLARE_OVERLAP_INSN(rstsa32, EXT_ZPN)
| ^~~~~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/processor.cc:1167:45: note: in definition of macro ‘DECLARE_OVERLAP_INSN’
1167 | #define DECLARE_OVERLAP_INSN(name, ext) { name##_supported = isa->extension_enabled(ext); }
| ^~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/overlap_list.h:22:22: error: ‘srli32_u_supported’ was not declared in this scope; did you mean ‘vle32_v_supported’?
22 | DECLARE_OVERLAP_INSN(srli32_u, EXT_ZPN)
| ^~~~~~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/processor.cc:1167:45: note: in definition of macro ‘DECLARE_OVERLAP_INSN’
1167 | #define DECLARE_OVERLAP_INSN(name, ext) { name##_supported = isa->extension_enabled(ext); }
| ^~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/overlap_list.h:23:22: error: ‘umax32_supported’ was not declared in this scope; did you mean ‘maxu_supported’?
23 | DECLARE_OVERLAP_INSN(umax32, EXT_ZPN)
| ^~~~~~
/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/spike/riscv/processor.cc:1167:45: note: in definition of macro ‘DECLARE_OVERLAP_INSN’
1167 | #define DECLARE_OVERLAP_INSN(name, ext) { name##_supported = isa->extension_enabled(ext); }
| ^~~~
At global scope:
cc1plus: warning: unrecognized command line option ‘-Wno-nonportable-include-path’
make[1]: *** [Makefile:347: processor.o] Error 1
make[1]: Leaving directory '/Data/chandra/development/RISCV-SPIKE/RISCV-BUILD/riscv-gnu-toolchain/build-spike'
make: *** [Makefile:901: stamps/build-spike] Error 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants