dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: "Maíra Canal" <maira.canal@usp.br>
To: Harry Wentland <harry.wentland@amd.com>,
	Leo Li <sunpeng.li@amd.com>,
	Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>,
	Alex Deucher <alexander.deucher@amd.com>,
	christian.koenig@amd.com,
	Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>,
	Jun Lei <jun.lei@amd.com>, Nicholas Choi <Nicholas.Choi@amd.com>,
	Harrison Chiu <harrison.chiu@amd.com>,
	Mark Yacoub <markyacoub@chromium.org>,
	Sean Paul <seanpaul@chromium.org>,
	Daniel Vetter <daniel@ffwll.ch>,
	Javier Martinez Canillas <javierm@redhat.com>,
	Isabella Basso <isabbasso@riseup.net>,
	magalilemes00@gmail.com, tales.aparecida@gmail.com,
	mwen@igalia.com, andrealmeid@riseup.net,
	David Gow <davidgow@google.com>,
	Daniel Latypov <dlatypov@google.com>,
	brendanhiggins@google.com
Cc: "Maíra Canal" <maira.canal@usp.br>,
	kunit-dev@googlegroups.com, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: [RFC 3/3] drm/amd/display: Introduce KUnit tests to the bw_fixed library
Date: Tue,  7 Jun 2022 22:07:11 -0300	[thread overview]
Message-ID: <20220608010709.272962-4-maira.canal@usp.br> (raw)
In-Reply-To: <20220608010709.272962-1-maira.canal@usp.br>

From: Magali Lemes <magalilemes00@gmail.com>

The bw_fixed library performs a lot of the mathematical operations
involving fixed-point arithmetic and the conversion of integers to
fixed-point representation.

As fixed-point representation is the base foundation of the DML calcs
operations, this unit tests intend to assure the proper functioning of
the basic mathematical operations of fixed-point arithmetic, such as
multiplication, conversion from fractional to fixed-point number, and more.

Co-developed-by: Tales Aparecida <tales.aparecida@gmail.com>
Signed-off-by: Tales Aparecida <tales.aparecida@gmail.com>
Signed-off-by: Magali Lemes <magalilemes00@gmail.com>
Co-developed-by: Maíra Canal <maira.canal@usp.br>
Signed-off-by: Maíra Canal <maira.canal@usp.br>
---
 .../drm/amd/display/amdgpu_dm/tests/Kconfig   |  12 +
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |   4 +
 .../amdgpu_dm/tests/calcs/bw_fixed_test.c     | 322 ++++++++++++++++++
 .../amd/display/amdgpu_dm/tests/dml_test.c    |   3 +
 .../amd/display/amdgpu_dm/tests/dml_test.h    |   8 +
 5 files changed, 349 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
index bd1d971d4452..540b2f79f971 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Kconfig
@@ -2,6 +2,18 @@
 menu "DML Unit Tests"
 	depends on DRM_AMD_DC && KUNIT=m
 
+config BW_FIXED_KUNIT_TEST
+	bool "Enable unit tests for dml/calcs/bw_fixed" if !DML_KUNIT_TEST
+	default y if DML_KUNIT_TEST
+	help
+		Enables unit tests for the dml/calcs/bw_fixed. Only useful for kernel
+		devs running KUnit.
+
+		For more information on KUnit and unit tests in general please refer to
+		the KUnit documentation in Documentation/dev-tools/kunit/.
+
+		If unsure, say N.
+
 config DISPLAY_MODE_LIB_KUNIT_TEST
 	bool "Enable unit tests for dml/display_mode_lib" if !DML_KUNIT_TEST
 	default y if DML_KUNIT_TEST
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index 53b38e340564..23109e51cf32 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -5,6 +5,10 @@
 
 DML_TESTS = dml_test.o
 
+ifdef CONFIG_BW_FIXED_KUNIT_TEST
+DML_TESTS += calcs/bw_fixed_test.o
+endif
+
 ifdef CONFIG_DISPLAY_MODE_LIB_KUNIT_TEST
 DML_TESTS += display_mode_lib_test.o
 endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c
new file mode 100644
index 000000000000..344c1517745e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/calcs/bw_fixed_test.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: MIT
+/*
+ * KUnit tests for dml/calcs/bw_fixed.h
+ *
+ * Copyright (C) 2022, Magali Lemes <magalilemes00@gmail.com>
+ * Copyright (C) 2022, Maíra Canal <mairacanal@riseup.net>
+ * Copyright (C) 2022, Tales Aparecida <tales.aparecida@gmail.com>
+ */
+
+#include <kunit/test.h>
+#include "../../../dc/inc/bw_fixed.h"
+#include "../dml_test.h"
+
+/**
+ * DOC: Unit tests for AMDGPU DML calcs/bw_fixed.h
+ *
+ * bw_fixed.h performs a lot of the mathematical operations involving
+ * fixed-point arithmetic and the conversion of integers to fixed-point
+ * representation.
+ *
+ * As fixed-point representation is the base foundation of the DML calcs
+ * operations, these tests intend to assure the proper functioning of the
+ * basic mathematical operations of fixed-point arithmetic, such as
+ * multiplication, conversion from fractional to fixed-point number, and more.
+ *
+ */
+
+static void abs_i64_test(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, 0ULL, abs_i64(0LL));
+
+	/* Argument type limits */
+	KUNIT_EXPECT_EQ(test, (uint64_t)MAX_I64, abs_i64(MAX_I64));
+	KUNIT_EXPECT_EQ(test, (uint64_t)MAX_I64 + 1, abs_i64(MIN_I64));
+}
+
+static void bw_int_to_fixed_nonconst_test(struct kunit *test)
+{
+	struct bw_fixed res;
+
+	/* Add BW_FIXED_BITS_PER_FRACTIONAL_PART trailing 0s to binary number */
+	res = bw_int_to_fixed_nonconst(1000);          /* 0x3E8 */
+	KUNIT_EXPECT_EQ(test, 16777216000, res.value); /* 0x3E8000000 */
+
+	res = bw_int_to_fixed_nonconst(-1000);          /* -0x3E8 */
+	KUNIT_EXPECT_EQ(test, -16777216000, res.value); /* -0x3E8000000 */
+
+	res = bw_int_to_fixed_nonconst(0LL);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	/**
+	 * Test corner cases, as the function's argument has to be an int64_t
+	 * between BW_FIXED_MIN_I32 and BW_FIXED_MAX_I32.
+	 */
+	res = bw_int_to_fixed_nonconst(BW_FIXED_MAX_I32 - 1);  /* 0x7FFFFFFFFE */
+	KUNIT_EXPECT_EQ(test, 9223372036821221376, res.value); /* 0x7FFFFFFFFE000000 */
+
+	res = bw_int_to_fixed_nonconst(BW_FIXED_MIN_I32 + 1);   /* -0x7FFFFFFFFF */
+	KUNIT_EXPECT_EQ(test, -9223372036837998592, res.value); /* -0x7FFFFFFFFF000000 */
+}
+
+static void bw_frc_to_fixed_test(struct kunit *test)
+{
+	struct bw_fixed res;
+
+	/* Extreme scenarios */
+
+	/* A fraction of N/N should result in "1.0" */
+	res = bw_frc_to_fixed(MAX_I64, MAX_I64);
+	KUNIT_EXPECT_EQ(test, 1LL << BW_FIXED_BITS_PER_FRACTIONAL_PART, res.value);
+
+	res = bw_frc_to_fixed(1, MAX_I64);
+	KUNIT_EXPECT_EQ(test, 0LL, res.value);
+
+	res = bw_frc_to_fixed(0, MAX_I64);
+	KUNIT_EXPECT_EQ(test, 0LL, res.value);
+
+	/* Turn a repeating decimal to the fixed-point representation */
+
+	/* A repeating decimal that doesn't round up the LSB */
+	res = bw_frc_to_fixed(4, 3);
+	KUNIT_EXPECT_EQ(test, 22369621LL, res.value);     /* 0x1555555 */
+
+	res = bw_frc_to_fixed(-4, 3);
+	KUNIT_EXPECT_EQ(test, -22369621LL, res.value);    /* -0x1555555 */
+
+	res = bw_frc_to_fixed(99999997, 100000000);
+	KUNIT_EXPECT_EQ(test, 16777215LL, res.value);     /* 0x0FFFFFF */
+
+	/* A repeating decimal that rounds up the MSB */
+	res = bw_frc_to_fixed(5, 3);
+	KUNIT_EXPECT_EQ(test, 27962027LL, res.value);     /* 0x1AAAAAB */
+
+	res = bw_frc_to_fixed(-5, 3);
+	KUNIT_EXPECT_EQ(test, -27962027LL, res.value);    /* -0x1AAAAAB */
+
+	res = bw_frc_to_fixed(99999998, 100000000);
+	KUNIT_EXPECT_EQ(test, 1LL << BW_FIXED_BITS_PER_FRACTIONAL_PART, res.value);
+
+	/* Turn a terminating decimal to the fixed-point representation */
+	res = bw_frc_to_fixed(62609, 100);
+	KUNIT_EXPECT_EQ(test, 10504047165LL, res.value);  /* 0X272170A3D */
+
+	res = bw_frc_to_fixed(-62609, 100);
+	KUNIT_EXPECT_EQ(test, -10504047165LL, res.value); /* -0X272170A3D */
+}
+
+static void bw_floor2_test(struct kunit *test)
+{
+	struct bw_fixed arg;
+	struct bw_fixed significance;
+	struct bw_fixed res;
+
+	/* Round 10 down to the nearest multiple of 3 */
+	arg.value = 10;
+	significance.value = 3;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 9, res.value);
+
+	/* Round 10 down to the nearest multiple of 5 */
+	arg.value = 10;
+	significance.value = 5;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 10, res.value);
+
+	/* Round 100 down to the nearest multiple of 7 */
+	arg.value = 100;
+	significance.value = 7;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 98, res.value);
+
+	/* Round an integer down to its nearest multiple should return itself */
+	arg.value = MAX_I64;
+	significance.value = MAX_I64;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MAX_I64, res.value);
+
+	arg.value = MIN_I64;
+	significance.value = MIN_I64;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MIN_I64, res.value);
+
+	/* Value is a multiple of significance, result should be value */
+	arg.value = MAX_I64;
+	significance.value = MIN_I64 + 1;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MAX_I64, res.value);
+
+	/* Round 0 down to the nearest multiple of any number should return 0 */
+	arg.value = 0;
+	significance.value = MAX_I64;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	arg.value = 0;
+	significance.value = MIN_I64;
+	res = bw_floor2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+}
+
+static void bw_ceil2_test(struct kunit *test)
+{
+	struct bw_fixed arg;
+	struct bw_fixed significance;
+	struct bw_fixed res;
+
+	/* Round 10 up to the nearest multiple of 3 */
+	arg.value = 10;
+	significance.value = 3;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 12, res.value);
+
+	/* Round 10 up to the nearest multiple of 5 */
+	arg.value = 10;
+	significance.value = 5;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 10, res.value);
+
+	/* Round 100 up to the nearest multiple of 7 */
+	arg.value = 100;
+	significance.value = 7;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 105, res.value);
+
+	/* Round an integer up to its nearest multiple should return itself */
+	arg.value = MAX_I64;
+	significance.value = MAX_I64;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MAX_I64, res.value);
+
+	arg.value = MIN_I64 + 1;
+	significance.value = MIN_I64 + 1;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MIN_I64 + 1, res.value);
+
+	/* Value is a multiple of significance, result should be value */
+	arg.value = MAX_I64;
+	significance.value = MIN_I64 + 1;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, MAX_I64, res.value);
+
+	/* Round 0 up to the nearest multiple of any number should return 0 */
+	arg.value = 0;
+	significance.value = MAX_I64;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	arg.value = 0;
+	significance.value = MIN_I64;
+	res = bw_ceil2(arg, significance);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+}
+
+static void bw_mul_test(struct kunit *test)
+{
+	struct bw_fixed arg1;
+	struct bw_fixed arg2;
+	struct bw_fixed res;
+	struct bw_fixed ans;
+
+	/* Extreme scenario */
+	arg1.value = MAX_I64;
+	arg2.value = MIN_I64;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, BW_FIXED_MAX_I32 + 1, res.value);
+
+	/* Testing multiplication property: x * 1 = x */
+	arg1.value = 1;
+	arg2.value = MAX_I64;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, BW_FIXED_MAX_I32 + 1, res.value);
+
+	arg1.value = 1;
+	arg2.value = MIN_I64;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, BW_FIXED_MIN_I32, res.value);
+
+	/* Testing multiplication property: x * 0 = 0 */
+	arg1.value = 0;
+	arg2.value = 0;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	arg1.value = 0;
+	arg2.value = MAX_I64;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	arg1.value = 0;
+	arg2.value = MIN_I64;
+	res = bw_mul(arg1, arg2);
+	KUNIT_EXPECT_EQ(test, 0, res.value);
+
+	/* Testing multiplication between integers */
+	res = bw_mul(bw_int_to_fixed(8), bw_int_to_fixed(10));
+	KUNIT_EXPECT_EQ(test, 1342177280LL, res.value); /* 0x50000000 */
+
+	res = bw_mul(bw_int_to_fixed(10), bw_int_to_fixed(5));
+	KUNIT_EXPECT_EQ(test, 838860800LL, res.value); /* 0x32000000 */
+
+	res = bw_mul(bw_int_to_fixed(-10), bw_int_to_fixed(7));
+	KUNIT_EXPECT_EQ(test, -1174405120LL, res.value); /* -0x46000000 */
+
+	/* Testing multiplication between fractions and integers */
+	res = bw_mul(bw_frc_to_fixed(4, 3), bw_int_to_fixed(3));
+	ans = bw_int_to_fixed(4);
+
+	/**
+	 * As bw_frc_to_fixed(4, 3) didn't round up the fixed-point representation,
+	 * the ans must be subtrated by 1.
+	 */
+	KUNIT_EXPECT_EQ(test, ans.value - 1, res.value);
+
+	res = bw_mul(bw_frc_to_fixed(5, 3), bw_int_to_fixed(3));
+	ans = bw_int_to_fixed(5);
+
+	/**
+	 * As bw_frc_to_fixed(5, 3) rounds up the fixed-point representation,
+	 * the ans must be added by 1.
+	 */
+	KUNIT_EXPECT_EQ(test, ans.value + 1, res.value);
+}
+
+static struct kunit_case bw_fixed_test_cases[] = {
+	KUNIT_CASE(abs_i64_test),
+	KUNIT_CASE(bw_int_to_fixed_nonconst_test),
+	KUNIT_CASE(bw_frc_to_fixed_test),
+	KUNIT_CASE(bw_floor2_test),
+	KUNIT_CASE(bw_ceil2_test),
+	KUNIT_CASE(bw_mul_test),
+	{  }
+};
+
+static struct kunit_suite bw_fixed_test_suite = {
+	.name = "dml-calcs-bw-fixed",
+	.test_cases = bw_fixed_test_cases,
+};
+
+static struct kunit_suite *bw_fixed_test_suites[] = { &bw_fixed_test_suite, NULL };
+
+int bw_fixed_test_init(void)
+{
+	pr_info("===> Running calcs/bw_fixed KUnit Tests");
+	pr_info("**********************************************************");
+	pr_info("**   NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE   **");
+	pr_info("**                                                      **");
+	pr_info("** calcs/bw_fixed KUnit Tests are being run. This means **");
+	pr_info("** that this is a TEST kernel and should not be used    **");
+	pr_info("** for production.                                      **");
+	pr_info("**                                                      **");
+	pr_info("** If you see this message and you are not debugging    **");
+	pr_info("** the kernel, report this immediately to your vendor!  **");
+	pr_info("**                                                      **");
+	pr_info("**********************************************************");
+
+	return __kunit_test_suites_init(bw_fixed_test_suites);
+}
+
+void bw_fixed_test_exit(void)
+{
+	return __kunit_test_suites_exit(bw_fixed_test_suites);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.c
index 9a5d47597c10..98ae4e8cd952 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.c
@@ -13,11 +13,14 @@
  */
 int amdgpu_dml_test_init(void)
 {
+	bw_fixed_test_init();
 	display_mode_lib_test_init();
+
 	return 0;
 }
 
 void amdgpu_dml_test_exit(void)
 {
 	display_mode_lib_test_exit();
+	bw_fixed_test_exit();
 }
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.h b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.h
index 2786db9d0e87..d8fe38abd9bc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/dml_test.h
@@ -2,6 +2,14 @@
 #ifndef DML_TEST_H_
 #define DML_TEST_H_
 
+#if defined (CONFIG_BW_FIXED_KUNIT_TEST)
+int bw_fixed_test_init(void);
+void bw_fixed_test_exit(void);
+#else
+static inline int bw_fixed_test_init(void) { return 0; }
+static inline void bw_fixed_test_exit(void) { }
+#endif
+
 #if defined (CONFIG_DISPLAY_MODE_LIB_KUNIT_TEST)
 int display_mode_lib_test_init(void);
 void display_mode_lib_test_exit(void);
-- 
2.36.1


  parent reply	other threads:[~2022-06-08  1:09 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-08  1:07 [RFC 0/3] drm/amd/display: Introduce KUnit to Display Mode Library Maíra Canal
2022-06-08  1:07 ` [RFC 1/3] drm/amd/display: Introduce KUnit to DML Maíra Canal
2022-06-08  2:36   ` Daniel Latypov
2022-06-15 15:05     ` Maíra Canal
2022-06-08  1:07 ` [RFC 2/3] drm/amd/display: Move bw_fixed macros to header file Maíra Canal
2022-06-08  1:07 ` Maíra Canal [this message]
2022-06-16 14:39 ` [RFC 0/3] drm/amd/display: Introduce KUnit to Display Mode Library David Gow
2022-06-16 22:41   ` Maíra Canal
2022-06-17  7:55     ` David Gow
2022-06-17 20:24       ` Maíra Canal
2022-06-18  9:08         ` David Gow
2022-06-22 22:55           ` Rodrigo Siqueira Jordao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220608010709.272962-4-maira.canal@usp.br \
    --to=maira.canal@usp.br \
    --cc=Dmytro.Laktyushkin@amd.com \
    --cc=Nicholas.Choi@amd.com \
    --cc=Rodrigo.Siqueira@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=andrealmeid@riseup.net \
    --cc=brendanhiggins@google.com \
    --cc=christian.koenig@amd.com \
    --cc=daniel@ffwll.ch \
    --cc=davidgow@google.com \
    --cc=dlatypov@google.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=harrison.chiu@amd.com \
    --cc=harry.wentland@amd.com \
    --cc=isabbasso@riseup.net \
    --cc=javierm@redhat.com \
    --cc=jun.lei@amd.com \
    --cc=kunit-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=magalilemes00@gmail.com \
    --cc=markyacoub@chromium.org \
    --cc=mwen@igalia.com \
    --cc=seanpaul@chromium.org \
    --cc=sunpeng.li@amd.com \
    --cc=tales.aparecida@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).