new file mode 100644
@@ -0,0 +1,88 @@
+#
+# Copyright OpenEmbedded Contributors
+#
+# SPDX-License-Identifier: MIT
+#
+
+from unittest.case import TestCase
+from oe.tune import RISCV_PROFILES, riscv_isa_to_tune, riscv_implied, riscv_pkgarch
+
+def features(isa):
+ return set(riscv_isa_to_tune(isa).split())
+
+class TestRiscvIsaToTune(TestCase):
+ def test_abbreviation(self):
+ self.assertEqual(riscv_isa_to_tune('rv64gc'), 'rv 64 i m a f d c zicsr zifencei')
+ self.assertEqual(riscv_isa_to_tune('rv32gcv'), 'rv 32 i m a f d c v zicsr zifencei')
+
+ def test_explicit(self):
+ self.assertEqual(riscv_isa_to_tune('rv32imac_zicsr_zifencei'), 'rv 32 i m a c zicsr zifencei')
+ self.assertEqual(riscv_isa_to_tune('RV64IMAFD_Zicsr'), 'rv 64 i m a f d zicsr')
+
+ def test_profile(self):
+ for name, isa in RISCV_PROFILES.items():
+ self.assertEqual(riscv_isa_to_tune(name), riscv_isa_to_tune(isa))
+
+ def test_not_riscv(self):
+ self.assertEqual(riscv_isa_to_tune('x86_64'), 'x86_64')
+
+class TestRiscvImplied(TestCase):
+ def test_implied(self):
+ self.assertEqual(riscv_implied({'m'}), {'zmmul'})
+ self.assertEqual(riscv_implied({'c', 'd'}), {'zca', 'zcd'})
+ self.assertEqual(riscv_implied({'za64rs'}), {'za128rs'})
+ self.assertIn('zve64d', riscv_implied({'v'}))
+ # vector subsets, without v
+ self.assertEqual(riscv_implied({'zve64d', 'zvl128b'}),
+ {'zve32f', 'zve32x', 'zve64f', 'zve64x', 'zvl32b', 'zvl64b'})
+
+ def test_zicsr_kept(self):
+ # Dropping zicsr would rename the existing non-profile package archs
+ self.assertNotIn('zicsr', riscv_implied({'f', 'd'}))
+
+ def test_profiles_nest(self):
+ # Later profiles are supersets of earlier ones, which tune-riscv.inc
+ # relies on for PACKAGE_EXTRA_ARCHS
+ names = ['rva20u64', 'rva22u64', 'rva23u64']
+ for lower, higher in zip(names, names[1:]):
+ h = features(higher)
+ self.assertLessEqual(features(lower), h | riscv_implied(h), '%s is not a subset of %s' % (lower, higher))
+
+class TestRiscvPkgarch(TestCase):
+ def test_no_features(self):
+ self.assertEqual(riscv_pkgarch('', 'riscv64imafdc'), 'riscv64imafdc')
+
+ def test_profiles(self):
+ for name in RISCV_PROFILES:
+ self.assertEqual(riscv_pkgarch(riscv_isa_to_tune(name), 'unused'), name)
+ self.assertEqual(riscv_pkgarch(riscv_isa_to_tune(name) + ' zifencei', 'unused'), name + '_zifencei')
+
+ def test_existing_names_unchanged(self):
+ self.assertEqual(riscv_pkgarch(riscv_isa_to_tune('rv64gc'), 'riscv64imafdc_zicsr_zifencei'),
+ 'riscv64imafdc_zicsr_zifencei')
+ self.assertEqual(riscv_pkgarch(riscv_isa_to_tune('rv32imac_zicsr_zifencei'), 'riscv32imac_zicsr_zifencei'),
+ 'riscv32imac_zicsr_zifencei')
+
+ def test_most_specific_profile(self):
+ # rva23u64 without supm isn't rva23u64, but still contains all of rva22u64
+ f = riscv_isa_to_tune('rva23u64').replace(' supm', '')
+ pkgarch = riscv_pkgarch(f, 'unused')
+ self.assertTrue(pkgarch.startswith('rva22u64_v_'), pkgarch)
+ # implied by v, so left out
+ self.assertNotIn('zve', pkgarch)
+
+ def test_implied_not_listed(self):
+ # b is implied by zba/zbb/zbs, so leaving it out still matches the profile
+ f = riscv_isa_to_tune('rva22u64').replace(' b ', ' ')
+ self.assertEqual(riscv_pkgarch(f, 'unused'), 'rva22u64')
+
+ def test_exact_drops_implied(self):
+ f = riscv_isa_to_tune('rv32imafdcv_zmmul_zaamo_zalrsc_zca_zcd_zve32x_zvl32b_zicsr_zifencei')
+ exact = 'riscv32imafdcv_zicsr_zifencei_zmmul_zaamo_zalrsc_zca_zcd_zve32x_zvl32b'
+ self.assertEqual(riscv_pkgarch(f, exact), 'riscv32imafdcv_zicsr_zifencei')
+
+ def test_exact_keeps_bitmanip(self):
+ # b is never written out in the exact pkgarch, so zba/zbb/zbs must stay
+ f = riscv_isa_to_tune('rv64gc_zba_zbb_zbs')
+ exact = 'riscv64imafdc_zicsr_zifencei_zba_zbb_zbs'
+ self.assertEqual(riscv_pkgarch(f, exact), exact)
Add a basic suite for meta/lib/oe/tune.py to test: - riscv_isa_to_tune() logic/expansion/parsing - riscv_implied() rules handling - Profile compatibility/nesting (e.g. rva22 is a superset of rva20) - riscv_pkgarch() profile naming/matching, including zifencei - Include testing of vector subsets when 'v' isn't specified, since these are technically valid AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com> --- meta/lib/oeqa/selftest/cases/oelib/tune.py | 88 ++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)