[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v3 01/15] tests: add fp-test, a floating point t
From: |
Alex Bennée |
Subject: |
Re: [Qemu-devel] [PATCH v3 01/15] tests: add fp-test, a floating point test suite |
Date: |
Wed, 11 Apr 2018 02:20:49 +0100 |
User-agent: |
mu4e 1.1.0; emacs 26.1 |
Emilio G. Cota <address@hidden> writes:
> This will allow us to run correctness tests against our
> FP implementation. The test can be run in two modes (called
> "testers"): host and soft. With the former we check the results
> and FP flags on the host machine against the model.
> With the latter we check QEMU's fpu primitives against the
> model. Note that in soft mode we are not instantiating any
> particular CPU (hence the HW_POISON_H hack to avoid macro poisoning);
> for that we need to run the test in host mode under QEMU.
<snip>
So with the attached patch and my proposed cross build we can now get:
02:15:54 address@hidden:~/l/q/qemu.git] softfloat-fixes-for-2.12-v1 ± find .
-iname "fp-test" | xargs file
./ppc64-linux-user/tests/fp-test: ELF 64-bit LSB executable, 64-bit
PowerPC or cisco 7500, version 1 (GNU/Linux), statically linked, for GNU/Linux
3.2.0, not stripped
./armeb-linux-user/tests/fp-test: ELF 32-bit LSB executable, ARM, EABI5
version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, not stripped
./aarch64-linux-user/tests/fp-test: ELF 64-bit LSB executable, ARM aarch64,
version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, not stripped
./i386-linux-user/tests/fp-test: ELF 32-bit LSB executable, Intel 80386,
version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped
./arm-linux-user/tests/fp-test: ELF 32-bit LSB executable, ARM, EABI5
version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, not stripped
./s390x-linux-user/tests/fp-test: ELF 64-bit MSB executable, IBM S/390,
version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, not stripped
./aarch64_be-linux-user/tests/fp-test: ELF 64-bit LSB executable, ARM aarch64,
version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, not stripped
./tests/fp-test/fp-test: ELF 64-bit LSB shared object, x86-64,
version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
for GNU/Linux 2.6.32, not stripped
But it did mean having to hack about a little, mainly to get rid of
glib.
--8<---------------cut here---------------start------------->8---
>From 04ed0d9f58f34aa51b9a8284514aab6e36a702b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Benn=C3=A9e?= <address@hidden>
Date: Wed, 11 Apr 2018 01:35:52 +0100
Subject: [PATCH] tests/tcg: add fp-test to per-guest tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The fp-test code was originally designed to be able to include
softfloat. However cross-compiling QEMU based code is harder than it
needs to be so hide softfloat stuff behind USE_SOFTFLOAT. We also need
to tweak:
- manually include what we need
- g_assert -> assert()
- use libc hsearch instead of g_hash_table
Signed-off-by: Alex Bennée <address@hidden>
---
tests/fp/fp-test.c | 148 ++++++++++++++++++++++++++++++++++++++++++-----------
tests/tcg/Makefile | 3 ++
2 files changed, 121 insertions(+), 30 deletions(-)
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index 27637c4617..4cee2a918c 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -6,12 +6,72 @@
* License: GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
-#ifndef HW_POISON_H
-#error Must define HW_POISON_H to work around TARGET_* poisoning
-#endif
+
+/* If HW_POISON_H isn't defined then we aren't building against qemu's
+ * softfloat */
+#ifdef HW_POISON_H
#include "qemu/osdep.h"
#include "fpu/softfloat.h"
+#define USE_SOFTFLOAT 1
+
+#else /* else define what QEMU would have given us */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <search.h>
+
+/* See include/fpu/softfloat-types.h */
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+enum {
+ float_round_nearest_even = 0,
+ float_round_down = 1,
+ float_round_up = 2,
+ float_round_to_zero = 3,
+ float_round_ties_away = 4,
+ float_round_to_odd = 5,
+};
+
+enum {
+ float_flag_invalid = 1,
+ float_flag_divbyzero = 4,
+ float_flag_overflow = 8,
+ float_flag_underflow = 16,
+ float_flag_inexact = 32,
+ float_flag_input_denormal = 64,
+ float_flag_output_denormal = 128
+};
+
+/* See include/compiler.h */
+#ifndef likely
+#if __GNUC__ < 3
+#define __builtin_expect(x, n) (x)
+#endif
+
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
#include <fenv.h>
#include <math.h>
@@ -116,16 +176,18 @@ struct tester {
struct whitelist {
char **lines;
size_t n;
- GHashTable *ht;
+ struct hsearch_data ht;
};
static uint64_t test_stats[ERROR_MAX];
static struct whitelist whitelist;
static uint8_t default_exceptions;
static bool die_on_error = true;
+#ifdef USE_SOFTFLOAT
static struct float_status soft_status = {
.float_detect_tininess = float_tininess_before_rounding,
};
+#endif
static inline float u64_to_float(uint64_t v)
{
@@ -285,7 +347,7 @@ static enum error host_tester(struct test_op *t)
float res;
int i;
- g_assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
+ assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
for (i = 0; i < ops[t->op].n_operands; i++) {
/* use the host's QNaN/SNaN patterns */
if (t->operands[i].type == OP_TYPE_QNAN) {
@@ -343,7 +405,7 @@ static enum error host_tester(struct test_op *t)
double res;
int i;
- g_assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
+ assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
for (i = 0; i < ops[t->op].n_operands; i++) {
/* use the host's QNaN/SNaN patterns */
if (t->operands[i].type == OP_TYPE_QNAN) {
@@ -429,6 +491,8 @@ static enum error host_tester(struct test_op *t)
return tester_check(t, res64, result_is_nan, flags);
}
+#ifdef USE_SOFTFLOAT
+
static enum error soft_tester(struct test_op *t)
{
float_status *s = &soft_status;
@@ -445,7 +509,7 @@ static enum error soft_tester(struct test_op *t)
float32 res;
int i;
- g_assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
+ assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
for (i = 0; i < ops[t->op].n_operands; i++) {
*in[i] = t->operands[i].val;
}
@@ -504,7 +568,7 @@ static enum error soft_tester(struct test_op *t)
float64 *in[] = { &a, &b, &c };
int i;
- g_assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
+ assert(ops[t->op].n_operands <= ARRAY_SIZE(in));
for (i = 0; i < ops[t->op].n_operands; i++) {
*in[i] = t->operands[i].val;
}
@@ -585,6 +649,14 @@ static const struct tester valid_testers[] = {
.func = host_tester,
},
};
+#else
+static const struct tester valid_testers[] = {
+ [0] = {
+ .name = "host",
+ .func = host_tester,
+ },
+};
+#endif
static const struct tester *tester = &valid_testers[0];
static int ibm_get_exceptions(const char *p, uint8_t *excp)
@@ -622,7 +694,7 @@ static uint64_t fp_choose(enum precision prec, uint64_t f,
uint64_t d)
case PREC_DOUBLE:
return d;
default:
- g_assert_not_reached();
+ assert(false);
}
}
@@ -756,7 +828,7 @@ ibm_fp_hex(const char *p, enum precision prec, struct
operand *ret)
} else if (prec == PREC_DOUBLE) {
ret->val = double_to_u64(0.0);
} else {
- g_assert_not_reached();
+ assert(false);
}
return 0;
} else if (!strcmp(p, "0x1")) {
@@ -765,7 +837,7 @@ ibm_fp_hex(const char *p, enum precision prec, struct
operand *ret)
} else if (prec == PREC_DOUBLE) {
ret->val = double_to_u64(1.0);
} else {
- g_assert_not_reached();
+ assert(false);
}
return 0;
}
@@ -915,10 +987,13 @@ static const struct input *input_type =
&valid_input_types[INPUT_FMT_IBM];
static bool line_is_whitelisted(const char *line)
{
- if (whitelist.ht == NULL) {
+ ENTRY e, *ep;
+
+ if (whitelist.ht.size == 0) {
return false;
}
- return !!g_hash_table_lookup(whitelist.ht, line);
+ e.key = line;
+ return hsearch_r(e, FIND, &ep, &whitelist.ht)==0;
}
static void test_file(const char *filename)
@@ -958,7 +1033,7 @@ static void test_file(const char *filename)
filename, i);
break;
default:
- g_assert_not_reached();
+ assert(false);
}
fprintf(stderr, "%s", line);
if (die_on_error) {
@@ -1007,23 +1082,32 @@ static void set_tester(const char *optarg)
static void whitelist_add_line(const char *orig_line)
{
- char *line;
+ char *line = strdup(orig_line);
bool inserted;
+ ENTRY e, *ep;
+ int r;
- if (whitelist.ht == NULL) {
- whitelist.ht = g_hash_table_new(g_str_hash, g_str_equal);
+ if (whitelist.ht.size == 0) {
+ if (!hcreate_r(4096, &whitelist.ht)) {
+ fprintf(stderr, "%s: error creating hash table\n", __func__);
+ }
}
- line = g_hash_table_lookup(whitelist.ht, orig_line);
- if (unlikely(line != NULL)) {
+
+ int hsearch_r(ENTRY item, ACTION action, ENTRY **retval,
+ struct hsearch_data *htab);
+
+ e.key = line;
+ r = hsearch_r(e, FIND, &ep, &whitelist.ht);
+ if (unlikely(r)) {
+ free(line);
return;
}
whitelist.n++;
- whitelist.lines = g_realloc_n(whitelist.lines, whitelist.n, sizeof(line));
- line = strdup(orig_line);
+ whitelist.lines = realloc(whitelist.lines, (whitelist.n * sizeof(line)));
whitelist.lines[whitelist.n - 1] = line;
- /* if we pass key == val GLib will not reserve space for the value */
- inserted = g_hash_table_insert(whitelist.ht, line, line);
- g_assert(inserted);
+ e.data = line;
+ inserted = hsearch_r(e, ENTER, &ep, &whitelist.ht);
+ assert(inserted);
}
static void set_whitelist(const char *filename)
@@ -1061,18 +1145,20 @@ static void usage_complete(int argc, char *argv[])
{
fprintf(stderr, "Usage: %s [options] file1 [file2 ...]\n", argv[0]);
fprintf(stderr, "options:\n");
- fprintf(stderr, " -a = Perform tininess detection after rounding "
- "(soft tester only). Default: before\n");
fprintf(stderr, " -n = do not die on error. Default: dies on error\n");
fprintf(stderr, " -e = default exception flags (xiozu). Default: none\n");
fprintf(stderr, " -f = format of the input file(s). Default: %s\n",
valid_input_types[0].name);
fprintf(stderr, " -t = tester. Default: %s\n", valid_testers[0].name);
fprintf(stderr, " -w = path to file with test cases to be whitelisted\n");
+#ifdef USE_SOFTFLOAT
+ fprintf(stderr, " -a = Perform tininess detection after rounding "
+ "(soft tester only). Default: before\n");
fprintf(stderr, " -z = flush inputs to zero (soft tester only). "
"Default: disabled\n");
fprintf(stderr, " -Z = flush output to zero (soft tester only). "
"Default: disabled\n");
+#endif
}
static void parse_opts(int argc, char *argv[])
@@ -1085,9 +1171,6 @@ static void parse_opts(int argc, char *argv[])
return;
}
switch (c) {
- case 'a':
- soft_status.float_detect_tininess = float_tininess_after_rounding;
- break;
case 'e':
set_default_exceptions(optarg);
break;
@@ -1106,15 +1189,20 @@ static void parse_opts(int argc, char *argv[])
case 'w':
set_whitelist(optarg);
break;
+#ifdef USE_SOFTFLOAT
+ case 'a':
+ soft_status.float_detect_tininess = float_tininess_after_rounding;
+ break;
case 'z':
soft_status.flush_inputs_to_zero = 1;
break;
case 'Z':
soft_status.flush_to_zero = 1;
break;
+#endif
}
}
- g_assert_not_reached();
+ assert(false);
}
static uint64_t count_errors(void)
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 2bba0d2a32..9c8011063e 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -24,6 +24,9 @@
VPATH = $(SRC_PATH)/tests/tcg/multiarch
TEST_SRCS = $(wildcard $(SRC_PATH)/tests/tcg/multiarch/*.c)
+VPATH += $(SRC_PATH)/tests/fp
+TEST_SRCS += $(wildcard $(SRC_PATH)/tests/fp/*.c)
+
VPATH += $(SRC_PATH)/tests/tcg/$(ARCH)
TEST_SRCS += $(wildcard $(SRC_PATH)/tests/tcg/$(ARCH)/*.c)
--
2.16.2
--8<---------------cut here---------------end--------------->8---
--
Alex Bennée
- [Qemu-devel] [PATCH v3 00/15] fp-test + hardfloat, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 02/15] softfloat: fix {min, max}nummag for same-abs-value inputs, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 01/15] tests: add fp-test, a floating point test suite, Emilio G. Cota, 2018/04/04
- Re: [Qemu-devel] [PATCH v3 01/15] tests: add fp-test, a floating point test suite,
Alex Bennée <=
- [Qemu-devel] [PATCH v3 04/15] softfloat: add float{32, 64}_is_{de, }normal, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 03/15] fp-test: add muladd variants, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 05/15] target/tricore: use float32_is_denormal, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 07/15] softfloat: rename canonicalize to sf_canonicalize, Emilio G. Cota, 2018/04/04
- [Qemu-devel] [PATCH v3 06/15] tests/fp: add fp-bench, a collection of simple floating point microbenchmarks, Emilio G. Cota, 2018/04/04