URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/sw/example/bitmanip_test
- from Rev 65 to Rev 66
- ↔ Reverse comparison
Rev 65 → Rev 66
/README.md
1,12 → 1,12
# NEORV32 Bit-Manipulation `B` Extension (`Zbb` sub-extension) |
# NEORV32 Bit-Manipulation `B` Extension |
|
:warning: The RISC-V bit-manipulation extension is frozen but not yet officially ratified. |
|
:warning: The NEORV32 bit manipulation extensions only supports the `Zbb` sub-extension |
:warning: The NEORV32 bit manipulation extensions `B` only supports the `Zbb` and `Zba` sub-extension |
(basic bit-manipulation operation) yet. |
|
The provided test program `main.c` verifies all currently implemented instruction by checking the results against a pure-software emulation model. |
The emulation functions as well as the available **intrinsics** for the `Zbb` extension are located in `neorv32_b_extension_intrinsics.h`. |
The emulation functions as well as the available **intrinsics** for the sub-extension are located in `neorv32_b_extension_intrinsics.h`. |
|
:information_source: More information regarding the RISC-V bit manipulation extension can be found in the officail GitHub repo: |
[github.com/riscv/riscv-bitmanip](https://github.com/riscv/riscv-bitmanip). |
/main.c
1,5 → 1,5
// ################################################################################################# |
// # << NEORV32 - RISC-V Bit-Manipulation 'Zbb' Extension Test Program >> # |
// # << NEORV32 - RISC-V Bit-Manipulation 'B' Extension Test Program >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
36,7 → 36,7
/**********************************************************************//** |
* @file bitmanip_test/main.c |
* @author Stephan Nolting |
* @brief Test program for the NEORV32 'Zbb' extension using pseudo-random |
* @brief Test program for the NEORV32 'B` extension using pseudo-random |
* data as input; compares results from hardware against pure-sw reference functions. |
**************************************************************************/ |
|
64,7 → 64,7
* Main function; test all available operations of the NEORV32 'Zbb' extensions |
* using bit manipulation intrinsics and software-only reference functions (emulation). |
* |
* @note This program requires the Zbb CPU extension. |
* @note This program requires the bit-manipulation CPU extension. |
* |
* @return Irrelevant. |
**************************************************************************/ |
91,19 → 91,23
#endif |
|
// intro |
neorv32_uart0_printf("NEORV32 'Zbb' Bit-Manipulation Extension Test\n\n"); |
neorv32_uart0_printf("NEORV32 Bit-Manipulation Extension Test (Zba, Zbb)\n\n"); |
|
// check available hardware extensions and compare with compiler flags |
neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch |
|
// check if Zbb extension is implemented at all |
if ((NEORV32_SYSINFO.CPU & (1<<SYSINFO_CPU_ZBB)) == 0) { |
neorv32_uart0_print("Error! <Zbb> extension not synthesized!\n"); |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_B)) == 0) { |
neorv32_uart0_print("Error! <B> extension not synthesized!\n"); |
return 1; |
} |
|
neorv32_uart0_printf("Starting Zbb bit-manipulation extension tests (%i test cases per instruction)...\n", num_tests); |
neorv32_uart0_printf("Starting bit-manipulation extension tests (%i test cases per instruction)...\n\n", num_tests); |
|
neorv32_uart0_printf("-----------------------------------------\n"); |
neorv32_uart0_printf("Zbb - Basic bit-manipulation instructions\n"); |
neorv32_uart0_printf("-----------------------------------------\n"); |
|
// ANDN |
neorv32_uart0_printf("\nANDN:\n"); |
err_cnt = 0; |
326,6 → 330,48
print_report(err_cnt, num_tests); |
|
|
|
neorv32_uart0_printf("\n\n"); |
neorv32_uart0_printf("-----------------------------------------\n"); |
neorv32_uart0_printf("Zba - Address generation instructions\n"); |
neorv32_uart0_printf("-----------------------------------------\n"); |
|
// SH1ADD |
neorv32_uart0_printf("\nSH1ADD:\n"); |
err_cnt = 0; |
for (i=0;i<num_tests; i++) { |
opa = xorshift32(); |
opb = xorshift32(); |
res_sw = riscv_emulate_sh1add(opa, opb); |
res_hw = riscv_intrinsic_sh1add(opa, opb); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
// SH2ADD |
neorv32_uart0_printf("\nSH2ADD:\n"); |
err_cnt = 0; |
for (i=0;i<num_tests; i++) { |
opa = xorshift32(); |
opb = xorshift32(); |
res_sw = riscv_emulate_sh2add(opa, opb); |
res_hw = riscv_intrinsic_sh2add(opa, opb); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
// SH2ADD |
neorv32_uart0_printf("\nSH3ADD:\n"); |
err_cnt = 0; |
for (i=0;i<num_tests; i++) { |
opa = xorshift32(); |
res_sw = riscv_emulate_sh3add(opa, opb); |
res_hw = riscv_intrinsic_sh3add(opa, opb); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
|
neorv32_uart0_printf("\nBit manipulation extension tests done.\n"); |
|
return 0; |
/neorv32_b_extension_intrinsics.h
1,8 → 1,8
// ################################################################################################# |
// # << NEORV32 - Intrinsics + Emulation Functions for the B CPU extensions >> # |
// # << NEORV32 - Intrinsics + Emulation Functions for the CPU B extension >> # |
// # ********************************************************************************************* # |
// # The intrinsics provided by this library allow to use the hardware bit manipulation unit of # |
// # the RISC-V B CPU extension without the need for B support by the compiler. # |
// # the RISC-V B CPU extension without the need for support by the compiler. # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
39,10 → 39,10
/**********************************************************************//** |
* @file bitmanip_test/neorv32_b_extension_intrinsics.h |
* @author Stephan Nolting |
* @brief "Intrinsic" library for the NEORV32 bit manipulation Zbb extension. |
* @brief "Intrinsic" library for the NEORV32 bit manipulation B extension. |
* Also provides emulation functions for all intrinsics (functionality re-built in pure software). |
* |
* @warning This library is just a temporary fall-back until the Zbb extensions are supported by the upstream RISC-V GCC port. |
* @warning This library is just a temporary fall-back until the B extension is supported by the upstream RISC-V GCC port. |
**************************************************************************/ |
|
#ifndef neorv32_b_extension_intrinsics_h |
54,9 → 54,9
// ################################################################################################ |
|
|
// --------------------------------------------- |
// ================================================================================================ |
// Zbb - Base instructions |
// --------------------------------------------- |
// ================================================================================================ |
|
/**********************************************************************//** |
* Intrinsic: Bit manipulation CLZ (count leading zeros) [B.Zbb] |
455,14 → 455,87
} |
|
|
// ================================================================================================ |
// Zbb - Base instructions |
// ================================================================================================ |
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [B.Zba] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a0). |
* @return Operand 2 + (Operand 1 << 1) |
**************************************************************************/ |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh1add(uint32_t rs1, uint32_t rs2) { |
|
register uint32_t result __asm__ ("a0"); |
register uint32_t tmp_a __asm__ ("a0") = rs1; |
register uint32_t tmp_b __asm__ ("a1") = rs2; |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b)); |
|
// sh1add a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b0110011); |
|
return result; |
} |
|
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [B.Zba] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a0). |
* @return Operand 2 + (Operand 1 << 2) |
**************************************************************************/ |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh2add(uint32_t rs1, uint32_t rs2) { |
|
register uint32_t result __asm__ ("a0"); |
register uint32_t tmp_a __asm__ ("a0") = rs1; |
register uint32_t tmp_b __asm__ ("a1") = rs2; |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b)); |
|
// sh2add a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b100, a0, 0b0110011); |
|
return result; |
} |
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH1ADD (add with logical-3-shift) [B.Zba] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 2 (a0). |
* @return Operand 2 + (Operand 1 << 3) |
**************************************************************************/ |
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh3add(uint32_t rs1, uint32_t rs2) { |
|
register uint32_t result __asm__ ("a0"); |
register uint32_t tmp_a __asm__ ("a0") = rs1; |
register uint32_t tmp_b __asm__ ("a1") = rs2; |
|
// dummy instruction to prevent GCC "constprop" optimization |
asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b)); |
|
// sh3add a0, a0, a1 |
CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b110, a0, 0b0110011); |
|
return result; |
} |
|
|
|
// ################################################################################################ |
// Emulation functions |
// ################################################################################################ |
|
|
// --------------------------------------------- |
// ================================================================================================ |
// Zbb - Base instructions |
// --------------------------------------------- |
// ================================================================================================ |
|
|
/**********************************************************************//** |
783,5 → 856,48
} |
|
|
// ================================================================================================ |
// Zba - Address generation instructions |
// ================================================================================================ |
|
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [emulation] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 1 (a0). |
* @return Operand 2 + (Operand 1 << 1) |
**************************************************************************/ |
uint32_t riscv_emulate_sh1add(uint32_t rs1, uint32_t rs2) { |
|
return rs2 + (rs1 << 1); |
} |
|
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [emulation] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 1 (a0). |
* @return Operand 2 + (Operand 1 << 2) |
**************************************************************************/ |
uint32_t riscv_emulate_sh2add(uint32_t rs1, uint32_t rs2) { |
|
return rs2 + (rs1 << 2); |
} |
|
|
/**********************************************************************//** |
* Intrinsic: Address generation instructions SH3ADD (add with logical-3-shift) [emulation] |
* |
* @param[in] rs1 Source operand 1 (a0). |
* @param[in] rs2 Source operand 1 (a0). |
* @return Operand 2 + (Operand 1 << 3) |
**************************************************************************/ |
uint32_t riscv_emulate_sh3add(uint32_t rs1, uint32_t rs2) { |
|
return rs2 + (rs1 << 3); |
} |
|
|
#endif // neorv32_b_extension_intrinsics_h |
|