#ifdef __MMA__
#include <altivec.h>
#include "cpu/ppc64/ppc64_gemm_s8x8s32.hpp"
#include "cpu/simple_q10n.hpp"
namespace dnnl {
namespace impl {
namespace cpu {
namespace ppc64 {
dnnl_status_t cblas_gemm_s8x8s32_ppc64(int ATflag, int BTflag,
char const *offsetc, dim_t m, dim_t n, dim_t k, float alpha,
int8_t const *A, dim_t lda, int8_t const *ao, uint8_t const *B,
dim_t ldb, uint8_t const *bo, int *C, float beta, dim_t ldc,
int const *co, int flipB_flag) {
int m_cap, n_cap, k_cap;
m_cap = (m + 3) & (~3);
n_cap = (n + 3) & (~3);
k_cap = (k + 3) & (~3);
if ((*ao != 0) || (*bo != 0)) {
short *Ashort, *AP, *APraw;
short *Bshort, *BP, *BPraw;
int a_size = lda * (ATflag ? m - 1 : k - 1) + (ATflag ? k : m);
int b_size = ldb * (BTflag ? k - 1 : n - 1) + (BTflag ? n : k);
Ashort = (short *)malloc(a_size * sizeof(short), 4096);
Bshort = (short *)malloc(b_size * sizeof(short), 4096);
if (utils::any_null(Ashort, Bshort)) {
free(Ashort);
free(Bshort);
return dnnl_out_of_memory;
}
for (int i = 0; i < a_size; ++i)
Ashort[i] = ((short)A[i]) - (short)*ao;
if (flipB_flag) {
const int8_t *Bflip = (const int8_t *)B;
const int8_t *bo_flip = (const int8_t *)bo;
for (int i = 0; i < b_size; ++i)
Bshort[i] = ((short)(Bflip[i])) - (short)*bo_flip;
} else {
for (int i = 0; i < b_size; ++i)
Bshort[i] = ((short)B[i]) - (short)*bo;
}
APraw = (short *)malloc((m_cap * k_cap + 15) * sizeof(short), 4096);
BPraw = (short *)malloc((k_cap * n_cap + 15) * sizeof(short), 4096);
if (utils::any_null(APraw, BPraw)) {
free(Ashort);
free(Bshort);
free(APraw);
free(BPraw);
return dnnl_out_of_memory;
}
AP = (short *)((((unsigned long)APraw) + 15) & (~15));
BP = (short *)((((unsigned long)BPraw) + 15) & (~15));
if (ATflag)
pack_N16_16bit(k, m, Ashort, lda, AP);
else
pack_T16_16bit(k, m, Ashort, lda, AP);
if (BTflag)
pack_T8_16bit(k, n, Bshort, ldb, BP);
else
pack_N8_16bit(k, n, Bshort, ldb, BP);
gemm_kernel_16bit(m, n, k, (float)alpha, AP, BP, C, beta, ldc);
free(Ashort);
free(Bshort);
free(APraw);
free(BPraw);
} else {
int8_t *AP, *APraw;
uint8_t *BP, *BPraw;
APraw = (int8_t *)malloc((m_cap * k_cap + 3) * sizeof(uint8_t), 4096);
BPraw = (uint8_t *)malloc((k_cap * n_cap + 3) * sizeof(int8_t), 4096);
if (utils::any_null(APraw, BPraw)) {
free(APraw);
free(BPraw);
return dnnl_out_of_memory;
}
AP = (int8_t *)((((unsigned long)APraw) + 3) & (~3));
BP = (uint8_t *)((((unsigned long)BPraw) + 3) & (~3));
if (ATflag)
pack_N16_8bit(k, m, A, lda, AP);
else
pack_T16_8bit(k, m, A, lda, AP);
if (flipB_flag) {
int b_size = ldb * (BTflag ? k - 1 : n - 1) + (BTflag ? n : k);
uint8_t *Bflip = (uint8_t *)malloc(b_size * sizeof(uint8_t), 4096);
if (utils::any_null(Bflip)) {
free(APraw);
free(BPraw);
free(Bflip);
return dnnl_out_of_memory;
}
for (int i = 0; i < b_size; ++i)
Bflip[i] = B[i] ^ 0x80;
if (BTflag)
pack_T8_8bit(k, n, Bflip, ldb, BP);
else
pack_N8_8bit(k, n, Bflip, ldb, BP);
free(Bflip);
} else {
if (BTflag)
pack_T8_8bit(k, n, B, ldb, BP);
else
pack_N8_8bit(k, n, B, ldb, BP);
}
gemm_kernel_8bit(m, n, k, (float)alpha, AP, BP, C, beta, ldc);
if (flipB_flag) {
int *comparray = (int *)malloc(m * sizeof(int), 4096);
if (utils::any_null(comparray)) {
free(APraw);
free(BPraw);
free(comparray);
return dnnl_out_of_memory;
}
for (int i = 0; i < m; ++i)
comparray[i] = 0;
if (ATflag) {
for (int i = 0; i < m; ++i) {
int ca = 0;
const int8_t *at = &A[lda * i];
for (int j = 0; j < k; ++j) {
ca += (int)*at++;
}
comparray[i] = ca;
}
} else {
for (int j = 0; j < k; ++j) {
int *ca = comparray;
const int8_t *at = &A[lda * j];
for (int i = 0; i < m; ++i) {
*ca++ += (int)*at++;
}
}
}
for (int i = 0; i < m; ++i) {
comparray[i] = cpu::q10n::out_round<int32_t>(
cpu::q10n::saturate<int32_t>(
((double)comparray[i]) * alpha * -128.0));
}
for (int j = 0; j < n; ++j) {
int *ca = comparray;
int *ct = &C[ldc * j];
for (int i = 0; i < m; ++i) {
*ct++ += *ca++;
}
}
free(comparray);
}
free(APraw);
free(BPraw);
}
if (*offsetc == 'F' || *offsetc == 'f')
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
C[ldc * i + j] += co[0];
if (*offsetc == 'R' || *offsetc == 'r')
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
C[ldc * i + j] += co[i];
if (*offsetc == 'C' || *offsetc == 'c')
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
C[ldc * i + j] += co[j];
return dnnl_success;
}
} } } }
#endif