Skip to content
Snippets Groups Projects
Commit 0edf5554 authored by Magali Lemes's avatar Magali Lemes Committed by Maíra Canal
Browse files

drm/amd/display: Introduce KUnit tests to the bw_fixed library


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: default avatarTales Aparecida <tales.aparecida@gmail.com>
Signed-off-by: default avatarTales Aparecida <tales.aparecida@gmail.com>
Signed-off-by: default avatarMagali Lemes <magalilemes00@gmail.com>
Co-developed-by: default avatarMaíra Canal <maira.canal@usp.br>
Signed-off-by: default avatarMaíra Canal <maira.canal@usp.br>
parent 2b593e13
No related tags found
Loading
......@@ -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
......
......@@ -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
......
// 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)
{
__kunit_test_suites_exit(bw_fixed_test_suites);
}
......@@ -13,10 +13,12 @@
*/
void amdgpu_dml_test_init(void)
{
bw_fixed_test_init();
display_mode_lib_test_init();
}
void amdgpu_dml_test_exit(void)
{
display_mode_lib_test_exit();
bw_fixed_test_exit();
}
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment