// Copyright (c) Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT /** * @file test_concept_diagnostics_sync.cpp * @brief Unit tests to ensure concepts and their diagnostics remain in sync * * This test suite verifies that: * 1. Valid types satisfy their corresponding concepts * 2. Invalid types (missing members) do not satisfy concepts * 3. Diagnostic messages correctly identify missing requirements * 4. Existing test types from conv_algorithm_types.hpp satisfy their concepts */ #include #include #include "ck_tile/builder/conv_algorithm_concepts.hpp" #include "ck_tile/builder/conv_algorithm_diagnostics.hpp" #include "ck_tile/builder/types.hpp" #include "experimental/builder/test/impl/conv_algorithm_types.hpp" namespace ck_tile::builder::test { using ck_tile::builder::ThreadBlockDescriptor; using ck_tile::builder::GridwiseXdlGemmDescriptor; using ck_tile::builder::BlockTransferDescriptor; using ck_tile::builder::ThreadClusterDescriptor; using ck_tile::builder::LdsTransferDescriptor; using ck_tile::builder::EpilogueDescriptor; using ck_tile::builder::AccessOrderDescriptor; using ck_tile::builder::BlockGemmDescriptor; using ck_tile::builder::GridwiseWmmaGemmDescriptor; using ck_tile::builder::TileThreadBlockDescriptor; using ck_tile::builder::TileTransferDescriptor; using ck_tile::builder::TileBlockGemmDescriptor; using ck_tile::builder::TileOptimizationsDescriptor; using ck_tile::builder::DlThreadConfigDescriptor; using ck_tile::builder::DlThreadClusterDescriptor; using ck_tile::builder::DlBlockTransferDescriptor; using ck_tile::builder::DlEpilogueDescriptor; using ck_tile::builder::ConvAlgorithmDescriptor; using ck_tile::builder::SpecifiesThreadBlock; using ck_tile::builder::SpecifiesGridwiseFwdXdlGemm; using ck_tile::builder::SpecifiesGridwiseBwdXdlGemm; using ck_tile::builder::SpecifiesBlockGemm; using ck_tile::builder::SpecifiesFwdConvSpecialization; using ck_tile::builder::SpecifiesBwdWeightConvSpecialization; using ck_tile::builder::SpecifiesGemmSpecialization; using ck_tile::builder::SpecifiesNumPrefetchStages; using ck_tile::builder::SpecifiesLoopScheduler; using ck_tile::builder::SpecifiesTileThreadBlock; using ck_tile::builder::SpecifiesTileTransfer; using ck_tile::builder::SpecifiesTileBlockGemm; using ck_tile::builder::SpecifiesTileOptimizations; using ck_tile::builder::SpecifiesTileConvSpecialization; using ck_tile::builder::SpecifiesDlThreadConfig; using ck_tile::builder::SpecifiesDlThreadCluster; // Helper to check if a string contains a substring bool contains(const std::string& str, const std::string& substr) { return str.find(substr) != std::string::npos; } // ============================================================================= // BASIC DESCRIPTOR CONCEPTS TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, ThreadBlockDescriptor_Valid) { // The ThreadBlock type from conv_algorithm_types.hpp should satisfy the concept static_assert(ThreadBlockDescriptor); } TEST(ConceptDiagnosticsSync, GridwiseXdlGemmDescriptor_Valid) { // The XdlParams type should satisfy the concept static_assert(GridwiseXdlGemmDescriptor); } TEST(ConceptDiagnosticsSync, BlockTransferDescriptor_Valid) { // The BlockTransfer type should satisfy the concept static_assert(BlockTransferDescriptor); } TEST(ConceptDiagnosticsSync, ThreadClusterDescriptor_Valid) { // The ThreadCluster type should satisfy the concept static_assert(ThreadClusterDescriptor); } TEST(ConceptDiagnosticsSync, LdsTransferDescriptor_Valid) { // The LdsTransfer type should satisfy the concept static_assert(LdsTransferDescriptor); } TEST(ConceptDiagnosticsSync, EpilogueDescriptor_Valid) { // The Epilogue type should satisfy the concept static_assert(EpilogueDescriptor); } TEST(ConceptDiagnosticsSync, AccessOrderDescriptor_Valid) { // The AccessOrder type should satisfy the concept static_assert(AccessOrderDescriptor); } TEST(ConceptDiagnosticsSync, BlockGemmDescriptor_Valid) { // The BlockGemm type should satisfy the concept static_assert(BlockGemmDescriptor); } TEST(ConceptDiagnosticsSync, GridwiseWmmaGemmDescriptor_Valid) { // The GridwiseWmmaGemm type should satisfy the concept static_assert(GridwiseWmmaGemmDescriptor); } // ============================================================================= // HIGH-LEVEL "SPECIFIES" CONCEPTS TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, SpecifiesThreadBlock_Valid) { static_assert(SpecifiesThreadBlock); } TEST(ConceptDiagnosticsSync, SpecifiesGridwiseFwdXdlGemm_Valid) { static_assert(SpecifiesGridwiseFwdXdlGemm); } TEST(ConceptDiagnosticsSync, SpecifiesGridwiseBwdXdlGemm_Valid) { static_assert(SpecifiesGridwiseBwdXdlGemm); } TEST(ConceptDiagnosticsSync, SpecifiesBlockGemm_Valid) { static_assert(SpecifiesBlockGemm); } TEST(ConceptDiagnosticsSync, SpecifiesFwdConvSpecialization_Valid) { static_assert(SpecifiesFwdConvSpecialization); } TEST(ConceptDiagnosticsSync, SpecifiesBwdWeightConvSpecialization_Valid) { static_assert(SpecifiesBwdWeightConvSpecialization); } TEST(ConceptDiagnosticsSync, SpecifiesGemmSpecialization_Valid) { static_assert(SpecifiesGemmSpecialization); } TEST(ConceptDiagnosticsSync, SpecifiesNumPrefetchStages_Valid) { static_assert(SpecifiesNumPrefetchStages); } TEST(ConceptDiagnosticsSync, SpecifiesLoopScheduler_Valid) { static_assert(SpecifiesLoopScheduler); } // ============================================================================= // TILE-SPECIFIC CONCEPTS TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, TileThreadBlockDescriptor_Valid) { static_assert(TileThreadBlockDescriptor); } TEST(ConceptDiagnosticsSync, TileTransferDescriptor_Valid) { static_assert(TileTransferDescriptor); } TEST(ConceptDiagnosticsSync, TileBlockGemmDescriptor_Valid) { static_assert(TileBlockGemmDescriptor); } TEST(ConceptDiagnosticsSync, TileOptimizationsDescriptor_Valid) { static_assert(TileOptimizationsDescriptor); } TEST(ConceptDiagnosticsSync, SpecifiesTileThreadBlock_Valid) { static_assert(SpecifiesTileThreadBlock); } TEST(ConceptDiagnosticsSync, SpecifiesTileTransfer_Valid) { static_assert(SpecifiesTileTransfer); } TEST(ConceptDiagnosticsSync, SpecifiesTileBlockGemm_Valid) { static_assert(SpecifiesTileBlockGemm); } TEST(ConceptDiagnosticsSync, SpecifiesTileOptimizations_Valid) { static_assert(SpecifiesTileOptimizations); } TEST(ConceptDiagnosticsSync, SpecifiesTileConvSpecialization_Valid) { static_assert(SpecifiesTileConvSpecialization); } // ============================================================================= // DL-SPECIFIC CONCEPTS TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, DlThreadConfigDescriptor_Valid) { static_assert(DlThreadConfigDescriptor); } TEST(ConceptDiagnosticsSync, DlThreadClusterDescriptor_Valid) { static_assert(DlThreadClusterDescriptor); } TEST(ConceptDiagnosticsSync, DlBlockTransferDescriptor_Valid) { static_assert(DlBlockTransferDescriptor); } TEST(ConceptDiagnosticsSync, DlEpilogueDescriptor_Valid) { static_assert(DlEpilogueDescriptor); } TEST(ConceptDiagnosticsSync, SpecifiesDlThreadConfig_Valid) { static_assert(SpecifiesDlThreadConfig); } TEST(ConceptDiagnosticsSync, SpecifiesDlThreadCluster_Valid) { static_assert(SpecifiesDlThreadCluster); } // ============================================================================= // INVALID TYPE TESTS - Test that concepts correctly reject invalid types // ============================================================================= namespace invalid_types { // Test ThreadBlockDescriptor with missing members struct MissingBlockSize { struct { size_t m, n, k; } tile_size; }; struct MissingTileSizeM { size_t block_size; struct { size_t n, k; } tile_size; }; // Test GridwiseXdlGemmDescriptor with missing members struct MissingMPerXdl { size_t n_per_xdl; size_t m_xdl_per_wave; size_t n_xdl_per_wave; }; // Test BlockTransferDescriptor with missing members struct MissingK0 { size_t m_n; size_t k1; }; // Test LdsTransferDescriptor with missing members struct MissingSrcVectorDim { size_t src_scalar_per_vector; size_t lds_dst_scalar_per_vector; bool is_direct_load; bool lds_padding; }; } // namespace invalid_types TEST(ConceptDiagnosticsSync, ThreadBlockDescriptor_Invalid) { static_assert(!ThreadBlockDescriptor); static_assert(!ThreadBlockDescriptor); } TEST(ConceptDiagnosticsSync, GridwiseXdlGemmDescriptor_Invalid) { static_assert(!GridwiseXdlGemmDescriptor); } TEST(ConceptDiagnosticsSync, BlockTransferDescriptor_Invalid) { static_assert(!BlockTransferDescriptor); } TEST(ConceptDiagnosticsSync, LdsTransferDescriptor_Invalid) { static_assert(!LdsTransferDescriptor); } // ============================================================================= // COMPREHENSIVE ALGORITHM TYPE TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, CompleteAlgorithmTypes) { // Test that complete algorithm types satisfy their concepts static_assert(ConvAlgorithmDescriptor); static_assert(ConvAlgorithmDescriptor); static_assert(ConvAlgorithmDescriptor); static_assert(ConvAlgorithmDescriptor); static_assert(ConvAlgorithmDescriptor); // Test specific requirements for each algorithm type static_assert(SpecifiesThreadBlock); static_assert(SpecifiesGridwiseFwdXdlGemm); static_assert(SpecifiesFwdConvSpecialization); static_assert(SpecifiesNumPrefetchStages); static_assert(SpecifiesTileThreadBlock); static_assert(SpecifiesTileBlockGemm); static_assert(SpecifiesTileOptimizations); } // ============================================================================= // DIAGNOSTIC MESSAGE TESTS // ============================================================================= TEST(ConceptDiagnosticsSync, DiagnosticMessages) { // Test that diagnostics can be called (even if messages may be empty at compile-time) // The key is that the diagnostic functions exist and compile std::string diag1 = ck_tile::builder::diagnostics::detailed_diagnostic_SpecifiesThreadBlock(); std::string diag2 = ck_tile::builder::diagnostics::detailed_diagnostic_SpecifiesGridwiseFwdXdlGemm(); // These may be empty depending on the implementation, but they should compile EXPECT_TRUE(diag1.empty() || contains(diag1, "thread_block") || contains(diag1, "missing")); EXPECT_TRUE(diag2.empty() || contains(diag2, "gridwise_gemm") || contains(diag2, "missing")); } // ============================================================================= // CONCEPT COMPLETENESS TESTS // ============================================================================= /** * @brief Verify that all concepts defined in conv_algorithm_concepts.hpp have tests * * This test serves as documentation of which concepts are tested. If new concepts * are added, this test should be updated to include them. */ TEST(ConceptDiagnosticsSync, ConceptCoverage) { // Basic Descriptor Concepts - verify they all exist and can be instantiated EXPECT_TRUE((ThreadBlockDescriptor)); EXPECT_TRUE((GridwiseXdlGemmDescriptor)); EXPECT_TRUE((BlockGemmDescriptor)); EXPECT_TRUE((GridwiseWmmaGemmDescriptor)); EXPECT_TRUE((BlockTransferDescriptor)); EXPECT_TRUE((ThreadClusterDescriptor)); EXPECT_TRUE((LdsTransferDescriptor)); EXPECT_TRUE((EpilogueDescriptor)); EXPECT_TRUE((AccessOrderDescriptor)); // Tile Descriptor Concepts EXPECT_TRUE((TileThreadBlockDescriptor)); EXPECT_TRUE((TileTransferDescriptor)); EXPECT_TRUE((TileBlockGemmDescriptor)); EXPECT_TRUE((TileOptimizationsDescriptor)); // DL Descriptor Concepts EXPECT_TRUE((DlThreadConfigDescriptor)); EXPECT_TRUE((DlThreadClusterDescriptor)); EXPECT_TRUE((DlBlockTransferDescriptor)); EXPECT_TRUE((DlEpilogueDescriptor)); } } // namespace ck_tile::builder::test int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }