text: /******************************************************************************
  * Copyright (c) Intel Corporation - All rights reserved.                      *
  * This file is part of the LIBXSMM library.                                   *
  *                                                                             *
  * For information on the license, see the LICENSE file.                       *
  * Further information: https://github.com/hfp/libxsmm/                        *
  * SPDX-License-Identifier: BSD-3-Clause                                       *
  ******************************************************************************/
  /* Alexander Heinecke (Intel Corp.)
  ******************************************************************************/
  #include <libxsmm.h>
  
  
  LIBXSMM_INLINE void print_help(void) {
    printf("\nwrong usage -> exit!\n\n\n");
    printf("Usage (sparse*dense=dense, dense*sparse=dense):\n");
    printf("    sparse, sparse_csr, sparse_csr_reg, sparse_csr_soa\n");
    printf("    filename to append\n");
    printf("    routine name\n");
    printf("    M\n");
    printf("    N\n");
    printf("    K\n");
    printf("    LDA (if < 1 --> A sparse)\n");
    printf("    LDB (if < 1 --> B sparse)\n");
    printf("    LDC\n");
    printf("    alpha: 1\n");
    printf("    beta: 0 or 1\n");
    printf("    0: unaligned A, otherwise aligned (ignored for sparse)\n");
    printf("    0: unaligned C, otherwise aligned (ignored for sparse)\n");
    printf("    ARCH: noarch, wsm, snb, hsw, knl, knm, skx, clx, cpx\n");
    printf("    PREFETCH: nopf (none), pfsigonly, other dense options fall-back to pfsigonly\n");
    printf("    PRECISION: SP, DP\n");
    printf("    matrix input (CSC mtx file)\n");
    printf("\n\n");
    printf("Usage (dense*dense=dense):\n");
    printf("    dense, dense_asm\n");
    printf("    filename to append\n");
    printf("    routine name\n");
    printf("    M\n");
    printf("    N\n");
    printf("    K\n");
    printf("    LDA\n");
    printf("    LDB\n");
    printf("    LDC\n");
    printf("    alpha: -1 or 1\n");
    printf("    beta: 0 or 1\n");
    printf("    0: unaligned A, otherwise aligned\n");
    printf("    0: unaligned C, otherwise aligned\n");
    printf("    ARCH: noarch, wsm, snb, hsw, knl, knm, skx, clx, cpx\n");
    printf("    PREFETCH: nopf (none), pfsigonly, BL2viaC, AL2, curAL2,\n"
           "              AL2_BL2viaC, curAL2_BL2viaC,\n");
    printf("    PRECISION: I16, SP, DP\n");
    printf("\n\n\n\n");
  }
  
  int main(int argc, char* argv []) {
    const libxsmm_gemm_descriptor* l_xgemm_desc = 0;
    int l_flags = LIBXSMM_GEMM_FLAGS('N', 'N');
    libxsmm_gemm_prefetch_type l_prefetch;
    libxsmm_descriptor_blob l_xgemm_blob;
    char* l_type;
    char* l_file_out;
    char* l_matrix_file_in;
    char* l_routine_name;
    char* l_arch;
    char* l_precision;
    int l_m = 0;
    int l_n = 0;
    int l_k = 0;
    int l_lda = 0;
    int l_ldb = 0;
    int l_ldc = 0;
    int l_aligned_a = 0;
    int l_aligned_c = 0;
    double l_alpha = 0;
    double l_beta = 0;
    int l_single_precision = 0;
    int l_is_csr = 0;
  
    /* check argument count for a valid range */
    if (argc != 17 && argc != 18) {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* names of files and routines */
    l_type = argv[1];
    l_file_out = argv[2];
    l_routine_name = argv[3];
  
    /* xgemm sizes */
    l_m = atoi(argv[4]);
    l_n = atoi(argv[5]);
    l_k = atoi(argv[6]);
    l_lda = atoi(argv[7]);
    l_ldb = atoi(argv[8]);
    l_ldc = atoi(argv[9]);
  
    /* condense < 1 to 0 for lda and ldb */
    if ( l_lda < 1 )
      l_lda = 0;
    if ( l_ldb < 1 )
      l_ldb = 0;
  
    /* some sugar */
    l_alpha = atof(argv[10]);
    l_beta = atof(argv[11]);
    l_aligned_a = atoi(argv[12]);
    l_aligned_c = atoi(argv[13]);
  
    l_flags |= (0 != l_aligned_a ? LIBXSMM_GEMM_FLAG_ALIGN_A : 0);
    l_flags |= (0 != l_aligned_c ? LIBXSMM_GEMM_FLAG_ALIGN_C : 0);
  
    /* arch specific stuff */
    l_arch = argv[14];
    l_precision = argv[16];
  
    /* some initial parameters checks */
    /* check for sparse / dense only */
    if ( (strcmp(l_type, "sparse")         != 0) &&
         (strcmp(l_type, "sparse_csr")     != 0) &&
         (strcmp(l_type, "sparse_csr_reg") != 0) &&
         (strcmp(l_type, "sparse_csr_soa") != 0) &&
         (strcmp(l_type, "dense")          != 0) &&
         (strcmp(l_type, "dense_asm")      != 0) ) {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* check for the right number of arguments depending on type */
    if ( ( (strcmp(l_type, "sparse") == 0) && (argc != 18) )         ||
         ( (strcmp(l_type, "sparse_csr") == 0) && (argc != 18) )     ||
         ( (strcmp(l_type, "sparse_csr_reg") == 0) && (argc != 18) ) ||
         ( (strcmp(l_type, "sparse_csr_soa") == 0) && (argc != 18) ) ||
         ( (strcmp(l_type, "dense")  == 0) && (argc != 17) )         ||
         ( (strcmp(l_type, "dense_asm")  == 0) && (argc != 17) ) ) {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* set value of prefetch flag */
    if (strcmp("nopf", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_NONE;
    }
    else if (strcmp("pfsigonly", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_SIGONLY;
    }
    else if (strcmp("BL2viaC", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_BL2_VIA_C;
    }
    else if (strcmp("curAL2", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_AL2_AHEAD;
    }
    else if (strcmp("curAL2_BL2viaC", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_AL2BL2_VIA_C_AHEAD;
    }
    else if (strcmp("AL2", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_AL2;
    }
    else if (strcmp("AL2_BL2viaC", argv[15]) == 0) {
      l_prefetch = LIBXSMM_GEMM_PREFETCH_AL2BL2_VIA_C;
    }
    else {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* check value of arch flag */
    if ( (strcmp(l_arch, "wsm") != 0)    &&
         (strcmp(l_arch, "snb") != 0)    &&
         (strcmp(l_arch, "hsw") != 0)    &&
         (strcmp(l_arch, "knl") != 0)    &&
         (strcmp(l_arch, "knm") != 0)    &&
         (strcmp(l_arch, "skx") != 0)    &&
         (strcmp(l_arch, "clx") != 0)    &&
         (strcmp(l_arch, "cpx") != 0)    &&
         (strcmp(l_arch, "noarch") != 0) ) {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* check and evaluate precision flag */
    if ( strcmp(l_precision, "SP") == 0 ) {
      l_single_precision = 1;
    } else if ( strcmp(l_precision, "DP") == 0 ) {
      l_single_precision = 0;
    } else if ( strcmp(l_precision, "I16") == 0 ) {
      l_single_precision = 2;
    } else {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* check alpha */
    if ((l_alpha < -1 || -1 < l_alpha) && (l_alpha < 1 || 1 < l_alpha)) {
      print_help();
      return EXIT_FAILURE;
    }
  
    /* check beta */
    if ((l_beta < 0 || 0 < l_beta) && (l_beta < 1 || 1 < l_beta)) {
      print_help();
      return EXIT_FAILURE;
    }
  
    switch (l_single_precision) {
      case 0: {
        l_xgemm_desc = libxsmm_gemm_descriptor_dinit(&l_xgemm_blob, LIBXSMM_GEMM_PRECISION_F64,
          l_m, l_n, l_k, l_lda, l_ldb, l_ldc, l_alpha, l_beta, l_flags, l_prefetch);
      } break;
      case 1: {
        l_xgemm_desc = libxsmm_gemm_descriptor_dinit(&l_xgemm_blob, LIBXSMM_GEMM_PRECISION_F32,
          l_m, l_n, l_k, l_lda, l_ldb, l_ldc, l_alpha, l_beta, l_flags, l_prefetch);
      } break;
      case 2: {
        l_xgemm_desc = libxsmm_gemm_descriptor_dinit(&l_xgemm_blob, LIBXSMM_GEMM_PRECISION_I16,
          l_m, l_n, l_k, l_lda, l_ldb, l_ldc, l_alpha, l_beta, l_flags, l_prefetch);
      } break;
      default: {
        print_help();
        return EXIT_FAILURE;
      }
    }
  
    if (NULL == l_xgemm_desc) {
      print_help();
      return EXIT_FAILURE;
    }
  
    if ( strcmp(l_type, "sparse") == 0 || strcmp(l_type, "sparse_csr") == 0 ||
         strcmp(l_type, "sparse_csr_reg") == 0 || strcmp(l_type, "sparse_csr_soa") == 0 ) {
      /* read additional parameter for CSC/CSR description */
      l_matrix_file_in = argv[17];
  
      /* some more restrictive checks are needed in case of sparse */
      if ( (l_alpha < 1) || (1 < l_alpha) ) {
        print_help();
        return EXIT_FAILURE;
      }
  
      if (l_lda < 1 && l_ldb < 1) {
        print_help();
        return EXIT_FAILURE;
      }
  
      if (l_ldc < 1) {
        print_help();
        return EXIT_FAILURE;
      }
  
      if ( l_single_precision > 1 ) {
        print_help();
        return EXIT_FAILURE;
      }
  
      if ( strcmp(l_type, "sparse_csr") == 0 ) {
        l_is_csr = 1;
      }
      if ( strcmp(l_type, "sparse_csr_soa") == 0 ) {
        l_is_csr = 2;
      }
      if ( strcmp(l_type, "sparse_csr_reg") == 0 ) {
        l_is_csr = 3;
      }
  
      libxsmm_generator_spgemm( l_file_out, l_routine_name, l_xgemm_desc, l_arch, l_matrix_file_in, l_is_csr );
    }
  
    if ( (strcmp(l_type, "dense")     == 0) ||
         (strcmp(l_type, "dense_asm") == 0) ) {
      if (l_lda < 1 || l_ldb < 1 || l_ldc < 1) {
        print_help();
        return EXIT_FAILURE;
      }
  
      if ( strcmp(l_type, "dense")  == 0 ) {
        libxsmm_generator_gemm_inlineasm( l_file_out, l_routine_name, l_xgemm_desc, l_arch );
      } else {
        libxsmm_generator_gemm_directasm( l_file_out, l_routine_name, l_xgemm_desc, l_arch );
      }
    }
  
    return EXIT_SUCCESS;
  }
  
  