mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 22:27:21 -04:00
[sw/example/floating_point_test] updated Zfinx verification framework
This commit is contained in:
parent
1f62d253c0
commit
51ea4ff3b8
1 changed files with 95 additions and 59 deletions
|
@ -63,7 +63,7 @@
|
|||
/** UART BAUD rate */
|
||||
#define BAUD_RATE (19200)
|
||||
//** Number of test cases for each instruction */
|
||||
#define NUM_TEST_CASES (50000000)
|
||||
#define NUM_TEST_CASES (1000000)
|
||||
//** Silent mode (only show actual errors when != 0) */
|
||||
#define SILENT_MODE (1)
|
||||
//** Run conversion tests when != 0 */
|
||||
|
@ -82,6 +82,8 @@
|
|||
#define RUN_CLASSIFY_TESTS (1)
|
||||
//** Run unsupported instructions tests when != 0 */
|
||||
#define RUN_UNAVAIL_TESTS (1)
|
||||
//** Run instruction timing tests when != 0 */
|
||||
#define RUN_TIMING_TESTS (1)
|
||||
/**@}*/
|
||||
|
||||
|
||||
|
@ -92,17 +94,6 @@ uint32_t verify_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, u
|
|||
void print_report(uint32_t num_err);
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Custom data type to access floating-point values as native floats and in binary representation
|
||||
**************************************************************************/
|
||||
typedef union
|
||||
{
|
||||
uint32_t binary_value; /**< Access as native float */
|
||||
float float_value; /**< Access in binary representation */
|
||||
} float_emu_t;
|
||||
|
||||
|
||||
|
||||
/**********************************************************************//**
|
||||
* Main function; test all available operations of the NEORV32 'Zfinx' extensions using bit floating-point hardware intrinsics and software-only reference functions (emulation).
|
||||
*
|
||||
|
@ -116,10 +107,10 @@ int main() {
|
|||
uint32_t err_cnt_total = 0;
|
||||
uint32_t test_cnt = 0;
|
||||
uint32_t i = 0;
|
||||
volatile float_emu_t opa;
|
||||
volatile float_emu_t opb;
|
||||
volatile float_emu_t res_hw;
|
||||
volatile float_emu_t res_sw;
|
||||
float_conv_t opa;
|
||||
float_conv_t opb;
|
||||
float_conv_t res_hw;
|
||||
float_conv_t res_sw;
|
||||
|
||||
|
||||
// init primary UART
|
||||
|
@ -160,8 +151,8 @@ int main() {
|
|||
err_cnt = 0;
|
||||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fcvt_swu(opa.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fcvt_swu(opa.binary_value);
|
||||
res_hw.float_value = riscv_intrinsic_fcvt_swu(opa.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fcvt_swu(opa.binary_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -172,8 +163,8 @@ int main() {
|
|||
err_cnt = 0;
|
||||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fcvt_sw(opa.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fcvt_sw(opa.binary_value);
|
||||
res_hw.float_value = riscv_intrinsic_fcvt_sw((int32_t)opa.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fcvt_sw((int32_t)opa.binary_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -184,7 +175,7 @@ int main() {
|
|||
err_cnt = 0;
|
||||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fcvt_wus(opa.binary_value);
|
||||
res_hw.binary_value = riscv_intrinsic_fcvt_wus(opa.float_value);
|
||||
res_sw.binary_value = riscv_emulate_fcvt_wus(opa.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
|
@ -196,8 +187,8 @@ int main() {
|
|||
err_cnt = 0;
|
||||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fcvt_ws(opa.binary_value);
|
||||
res_sw.binary_value = riscv_emulate_fcvt_ws(opa.float_value);
|
||||
res_hw.binary_value = (uint32_t)riscv_intrinsic_fcvt_ws(opa.float_value);
|
||||
res_sw.binary_value = (uint32_t)riscv_emulate_fcvt_ws(opa.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -216,8 +207,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fadds(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fadds(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fadds(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fadds(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -229,8 +220,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fsubs(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fsubs(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fsubs(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fsubs(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -249,8 +240,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fmuls(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fmuls(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fmuls(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fmuls(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -269,8 +260,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fmins(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fmins(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fmins(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fmins(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -282,8 +273,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fmaxs(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fmaxs(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fmaxs(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fmaxs(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -302,7 +293,7 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_feqs(opa.binary_value, opb.binary_value);
|
||||
res_hw.binary_value = riscv_intrinsic_feqs(opa.float_value, opb.float_value);
|
||||
res_sw.binary_value = riscv_emulate_feqs(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
|
@ -315,7 +306,7 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_flts(opa.binary_value, opb.binary_value);
|
||||
res_hw.binary_value = riscv_intrinsic_flts(opa.float_value, opb.float_value);
|
||||
res_sw.binary_value = riscv_emulate_flts(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
|
@ -328,7 +319,7 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fles(opa.binary_value, opb.binary_value);
|
||||
res_hw.binary_value = riscv_intrinsic_fles(opa.float_value, opb.float_value);
|
||||
res_sw.binary_value = riscv_emulate_fles(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
|
@ -348,8 +339,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fsgnjs(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjs(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fsgnjs(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjs(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -361,8 +352,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fsgnjns(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjns(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fsgnjns(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjns(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -374,8 +365,8 @@ int main() {
|
|||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fsgnjxs(opa.binary_value, opb.binary_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjxs(opa.float_value, opb.float_value);
|
||||
res_hw.float_value = riscv_intrinsic_fsgnjxs(opa.float_value, opb.float_value);
|
||||
res_sw.float_value = riscv_emulate_fsgnjxs(opa.float_value, opb.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
print_report(err_cnt);
|
||||
|
@ -393,7 +384,7 @@ int main() {
|
|||
err_cnt = 0;
|
||||
for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
res_hw.binary_value = riscv_intrinsic_fclasss(opa.binary_value);
|
||||
res_hw.binary_value = riscv_intrinsic_fclasss(opa.float_value);
|
||||
res_sw.binary_value = riscv_emulate_fclasss(opa.float_value);
|
||||
err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
|
||||
}
|
||||
|
@ -402,15 +393,17 @@ int main() {
|
|||
test_cnt++;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// UNSUPPORTED Instructions Tests
|
||||
// UNSUPPORTED Instructions Tests - Execution should raise illegal instruction exception
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if (RUN_UNAVAIL_TESTS != 0)
|
||||
neorv32_uart_printf("\n# FDIV.S (division) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FDIV.S (division) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fdivs(0, 0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fdivs(opa.float_value, opb.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -419,9 +412,11 @@ int main() {
|
|||
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
|
||||
}
|
||||
|
||||
neorv32_uart_printf("\n# FSQRT.S (square root) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FSQRT.S (square root) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fsqrts(0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fsqrts(opa.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -430,9 +425,11 @@ int main() {
|
|||
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
|
||||
}
|
||||
|
||||
neorv32_uart_printf("\n# FMADD.S (fused multiply-add) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FMADD.S (fused multiply-add) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fmadds(0, 0, 0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fmadds(opa.float_value, opb.float_value, -opa.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -441,9 +438,11 @@ int main() {
|
|||
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
|
||||
}
|
||||
|
||||
neorv32_uart_printf("\n# FMSUB.S (fused multiply-sub) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FMSUB.S (fused multiply-sub) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fmsubs(0, 0, 0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fmsubs(opa.float_value, opb.float_value, -opa.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -452,9 +451,11 @@ int main() {
|
|||
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
|
||||
}
|
||||
|
||||
neorv32_uart_printf("\n# FNMSUB.S (fused negated multiply-sub) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FNMSUB.S (fused negated multiply-sub) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fnmadds(0, 0, 0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -463,9 +464,11 @@ int main() {
|
|||
neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
|
||||
}
|
||||
|
||||
neorv32_uart_printf("\n# FNMADD.S (fused negated multiply-add) [NOT SUPPORTED!]...\n");
|
||||
neorv32_uart_printf("\n# unsupported FNMADD.S (fused negated multiply-add) [illegal instruction]...\n");
|
||||
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
||||
riscv_intrinsic_fnmadds(0, 0, 0);
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
|
||||
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
||||
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
|
||||
err_cnt_total++;
|
||||
|
@ -476,6 +479,39 @@ int main() {
|
|||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Instruction execution timing test
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if (RUN_TIMING_TESTS != 0)
|
||||
neorv32_uart_printf("\n# Instruction timing test...\n", test_cnt);
|
||||
err_cnt = 0;
|
||||
|
||||
const uint32_t num_runs = 1024;
|
||||
uint32_t time_start, time_hw, time_sw;
|
||||
|
||||
time_hw = 0;
|
||||
time_sw = 0;
|
||||
for (i=0;i<num_runs; i++) {
|
||||
opa.binary_value = get_test_vector();
|
||||
opb.binary_value = get_test_vector();
|
||||
|
||||
time_start = neorv32_cpu_csr_read(CSR_MCYCLE);
|
||||
res_hw.float_value = riscv_intrinsic_fadds(opa.float_value, opb.float_value);
|
||||
time_hw += neorv32_cpu_csr_read(CSR_MCYCLE) - time_start;
|
||||
|
||||
time_start = neorv32_cpu_csr_read(CSR_MCYCLE);
|
||||
res_sw.float_value = riscv_emulate_fadds(opa.float_value, opb.float_value);
|
||||
time_sw += neorv32_cpu_csr_read(CSR_MCYCLE) - time_start;
|
||||
|
||||
if (res_hw.binary_value != res_sw.binary_value) {
|
||||
neorv32_uart_printf("\n%c[1m[error]%c[0m\n", 27, 27);
|
||||
}
|
||||
}
|
||||
neorv32_uart_printf("Average FADD.S execution time INCLUDING calling overhead (%u runs): [SW] = %u cycles vs. [HW] = %u cycles\n", num_runs, time_sw/num_runs, time_hw/num_runs);
|
||||
#endif
|
||||
|
||||
|
||||
// final report
|
||||
if (err_cnt_total != 0) {
|
||||
neorv32_uart_printf("\n%c[1m[ZFINX EXTENSION VERIFICATION FAILED!]%c[0m\n", 27, 27);
|
||||
|
@ -496,7 +532,7 @@ int main() {
|
|||
**************************************************************************/
|
||||
uint32_t get_test_vector(void) {
|
||||
|
||||
float_emu_t tmp;
|
||||
float_conv_t tmp;
|
||||
|
||||
// generate special value "every" ~256th time this function is called
|
||||
if ((xorshift32() & 0xff) == 0xff) {
|
||||
|
@ -519,7 +555,7 @@ uint32_t get_test_vector(void) {
|
|||
|
||||
// subnormal numbers are not supported yet!
|
||||
// flush them to zero
|
||||
tmp.float_value = subnormal_flush(tmp.float_value);
|
||||
//tmp.float_value = subnormal_flush(tmp.float_value);
|
||||
|
||||
return tmp.binary_value;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue