Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ deps = {
'url': Var('chromium_url') + '/chromium/src/third_party/abseil-cpp' + '@' + '5c3e051186c88b1e7ee66750eda59096a51abc73',
},
'third_party/kleidiai/src': {
'url': 'https://gitlab.arm.com/kleidi/kleidiai@v1.25.0',
'url': 'https://github.com/ARM-software/kleidiai.git@v1.29.0',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the Gitlab url.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to GitLab

'condition': 'checkout_kleidiai'
},
'third_party/libc++/src':
Expand Down
6 changes: 3 additions & 3 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ http_archive(
# KleidiAI library, used for ARM microkernels.
http_archive(
name = "KleidiAI",
sha256 = "b147799b94c51f5e57492930bfd9e5294fb7ffe44fee1dbcd3f8048adeedd5e3",
strip_prefix = "kleidiai-b87ef9c94f45f11c81a6b1fdaed1b2b45ea58c0c",
sha256 = "97fa06184bb32a207470cb485742aa4c82e794a862016138f286ea138514d887",
strip_prefix = "kleidiai-13cd35993d8439143aff1e756a862d366acded0d",
urls = [
"https://gitlab.arm.com/kleidi/kleidiai/-/archive/b87ef9c94f45f11c81a6b1fdaed1b2b45ea58c0c/kleidiai-b87ef9c94f45f11c81a6b1fdaed1b2b45ea58c0c.zip",
"https://github.com/ARM-software/kleidiai/archive/13cd35993d8439143aff1e756a862d366acded0d.zip",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the Gitlab url.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to GitLab

],
)
# LINT.ThenChange(cmake/DownloadKleidiAI.cmake)
Expand Down
4 changes: 2 additions & 2 deletions cmake/DownloadKleidiAI.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ ENDIF()
# LINT.IfChange
INCLUDE(ExternalProject)
ExternalProject_Add(kleidiai
URL https://gitlab.arm.com/kleidi/kleidiai/-/archive/b87ef9c94f45f11c81a6b1fdaed1b2b45ea58c0c/kleidiai-b87ef9c94f45f11c81a6b1fdaed1b2b45ea58c0c.zip
URL_HASH SHA256=b147799b94c51f5e57492930bfd9e5294fb7ffe44fee1dbcd3f8048adeedd5e3
URL https://github.com/ARM-software/kleidiai/archive/13cd35993d8439143aff1e756a862d366acded0d.zip

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the Gitlab url.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted to GitLab

URL_HASH SHA256=97fa06184bb32a207470cb485742aa4c82e794a862016138f286ea138514d887
SOURCE_DIR "${CMAKE_BINARY_DIR}/kleidiai-source"
BINARY_DIR "${CMAKE_BINARY_DIR}/kleidiai"
CONFIGURE_COMMAND ""
Expand Down
2 changes: 2 additions & 0 deletions cmake/gen/neonsme2_microkernels.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ SET(PROD_NEONSME2_MICROKERNEL_SRCS
src/pqs8-f32-qc8w-igemm/pqs8-f32-qc8w-igemm-32x32c4-minmax-neonsme2.c
src/pqs8-qc8w-gemm/pqs8-qc8w-gemm-1x32c4-minmax-neonsme2.c
src/pqs8-qc8w-gemm/pqs8-qc8w-gemm-32x32c4-minmax-neonsme2.c
src/qp8-f32-qc2w-gemm/qp8-f32-qc2w-gemm-minmax-1x64c4-neonsme2.c
src/qp8-f32-qc2w-gemm/qp8-f32-qc2w-gemm-minmax-16x64c4-neonsme2.c
src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-1x64c4-neonsme2.c
src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-16x64c4-neonsme2.c
src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x64c4-neonsme2.c
Expand Down
2 changes: 2 additions & 0 deletions gen/neonsme2_microkernels.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ PROD_NEONSME2_MICROKERNEL_SRCS = [
"src/pqs8-f32-qc8w-igemm/pqs8-f32-qc8w-igemm-32x32c4-minmax-neonsme2.c",
"src/pqs8-qc8w-gemm/pqs8-qc8w-gemm-1x32c4-minmax-neonsme2.c",
"src/pqs8-qc8w-gemm/pqs8-qc8w-gemm-32x32c4-minmax-neonsme2.c",
"src/qp8-f32-qc2w-gemm/qp8-f32-qc2w-gemm-minmax-1x64c4-neonsme2.c",
"src/qp8-f32-qc2w-gemm/qp8-f32-qc2w-gemm-minmax-16x64c4-neonsme2.c",
"src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-1x64c4-neonsme2.c",
"src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-16x64c4-neonsme2.c",
"src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x64c4-neonsme2.c",
Expand Down
1 change: 1 addition & 0 deletions scripts/generate-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ tools/generate-gemm-test.py --spec test/qd8-f32-qb4w-gemm-minmax.yaml --output-t
tools/generate-gemm-test.py --spec test/qd8-f32-qc2w-gemm-minmax.yaml --output-test test/qd8-f32-qc2w-gemm-minmax.cc --output-bench bench/qd8-f32-qc2w-gemm.cc &
tools/generate-gemm-test.py --spec test/qd8-f16-qc2w-gemm-minmax.yaml --output-test test/qd8-f16-qc2w-gemm-minmax.cc --output-bench bench/qd8-f16-qc2w-gemm.cc &

tools/generate-gemm-test.py --spec test/qp8-f32-qc2w-gemm-minmax.yaml --output-test test/qp8-f32-qc2w-gemm-minmax.cc &
tools/generate-gemm-test.py --spec test/qp8-f32-qc4w-gemm-minmax.yaml --output-test test/qp8-f32-qc4w-gemm-minmax.cc --output-bench bench/qp8-f32-qc4w-gemm.cc &
tools/generate-gemm-test.py --spec test/qp8-f32-qc8w-gemm-minmax.yaml --output-test test/qp8-f32-qc8w-gemm-minmax.cc --output-bench bench/qp8-f32-qc8w-gemm.cc &
tools/generate-gemm-test.py --spec test/qp8-f32-qb4w-gemm-minmax.yaml --output-test test/qp8-f32-qb4w-gemm-minmax.cc --output-bench bench/qp8-f32-qb4w-gemm.cc &
Expand Down
57 changes: 57 additions & 0 deletions src/configs/gemm-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static struct xnn_gemm_config qd8_f32_qc4w_gemm_config = {0};
static struct xnn_gemm_config qd8_f32_qc2w_gemm_config = {0};
static struct xnn_gemm_config qdu8_f32_qc2w_gemm_config = {0};
static struct xnn_gemm_config qd8_f32_qc8w_gemm_config = {0};
static struct xnn_gemm_config qp8_f32_qc2w_gemm_config = {0};
static struct xnn_gemm_config qp8_f32_qc4w_gemm_config = {0};
static struct xnn_gemm_config qp8_f32_qc8w_gemm_config = {0};
static struct xnn_gemm_config qp8_f32_qb4w_gemm_config = {0};
Expand Down Expand Up @@ -92,6 +93,7 @@ XNN_INIT_ONCE_GUARD(qd8_f32_qc4w_gemm);
XNN_INIT_ONCE_GUARD(qd8_f32_qc2w_gemm);
XNN_INIT_ONCE_GUARD(qdu8_f32_qc2w_gemm);
XNN_INIT_ONCE_GUARD(qd8_f32_qc8w_gemm);
XNN_INIT_ONCE_GUARD(qp8_f32_qc2w_gemm);
XNN_INIT_ONCE_GUARD(qp8_f32_qc4w_gemm);
XNN_INIT_ONCE_GUARD(qp8_f32_qc8w_gemm);
XNN_INIT_ONCE_GUARD(qp8_f32_qb4w_gemm);
Expand Down Expand Up @@ -2886,6 +2888,50 @@ static void init_qd8_f32_qc4w_gemm_config(void) {
assert(qd8_f32_qc4w_gemm_config.mr <= (XNN_EXTRA_QUANTIZATION_PARAMS + 1));
}

static void init_qp8_f32_qc2w_gemm_config(void) {
qp8_f32_qc2w_gemm_config.log2_input_element_size =
XNN_LOG2_SIZEOF_INT8_T;
qp8_f32_qc2w_gemm_config.log2_filter_element_size =
XNN_LOG2_SIZEOF_UINT8_T;
qp8_f32_qc2w_gemm_config.log2_filter_element_bit_size =
XNN_LOG2_BIT_SIZEOF_INT2;
qp8_f32_qc2w_gemm_config.bias_element_size = sizeof(float);
qp8_f32_qc2w_gemm_config.planes = 4;

#if XNN_ARCH_ARM64 && XNN_ENABLE_KLEIDIAI
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
assert(hardware_config != NULL);
if (hardware_config->arch_flags & xnn_arch_arm_sme2) {
#if XNN_ENABLE_ARM_SME2
const size_t mr =
xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2_get_mr();
const size_t nr =
xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2_get_nr();
qp8_f32_qc2w_gemm_config.arch = xnn_arch_arm_sme2;
qp8_f32_qc2w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(1)] =
XNN_INIT_HMP_QP8GEMM_UKERNEL(
xnn_qp8_f32_qc2w_gemm_minmax_ukernel_1x64c4__neonsme2);
qp8_f32_qc2w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(mr)] =
XNN_INIT_HMP_QP8GEMM_UKERNEL(
xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2);
qp8_f32_qc2w_gemm_config.init.f32 =
xnn_init_f32_minmax_scalar_params;
qp8_f32_qc2w_gemm_config.pack_weights_and_biases =
xnn_pack_kai_qs2_weights_and_biases_sme2;
qp8_f32_qc2w_gemm_config.packed_stride_weights_and_biases =
xnn_packed_stride_kai_qs2_weights_and_biases_sme2;
qp8_f32_qc2w_gemm_config.mr = mr;
qp8_f32_qc2w_gemm_config.mr_packed = mr;
qp8_f32_qc2w_gemm_config.nr = nr;
qp8_f32_qc2w_gemm_config.log2_kr = 2;
qp8_f32_qc2w_gemm_config.log2_sr = 0;
#endif // XNN_ENABLE_ARM_SME2
}
assert(qp8_f32_qc2w_gemm_config.mr <= XNN_MAX_MR);
#endif // XNN_ARCH_ARM64 && XNN_ENABLE_KLEIDIAI
}

static void init_qp8_f32_qc4w_gemm_config(void) {
// Common parameters.
qp8_f32_qc4w_gemm_config.log2_input_element_size = XNN_LOG2_SIZEOF_INT8_T;
Expand Down Expand Up @@ -6637,6 +6683,17 @@ const struct xnn_gemm_config* xnn_init_qp8_f32_qc4w_gemm_config() {
return NULL;
}

const struct xnn_gemm_config* xnn_init_qp8_f32_qc2w_gemm_config() {
if (xnn_init_hardware_config() == NULL) {
return NULL;
}
XNN_INIT_ONCE(qp8_f32_qc2w_gemm);
if (qp8_f32_qc2w_gemm_config.minmax.qp8gemm[0].function[0] != NULL) {
return &qp8_f32_qc2w_gemm_config;
}
return NULL;
}

const struct xnn_gemm_config* xnn_init_qp8_f32_qc8w_gemm_config() {
if (xnn_init_hardware_config() == NULL) {
return NULL;
Expand Down
1 change: 1 addition & 0 deletions src/operators/fingerprint_id.h.inc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ XNN_FINGERPRINT_ID(fully_connected_nc, qd8, f32, qc2w)
XNN_FINGERPRINT_ID(fully_connected_nc, qdu8, f32, qc2w)
XNN_FINGERPRINT_ID(fully_connected_nc, qd8, f32, qc4w)
XNN_FINGERPRINT_ID(fully_connected_nc, qdu8, f32, qc4w)
XNN_FINGERPRINT_ID(fully_connected_nc, qp8, f32, qc2w)
XNN_FINGERPRINT_ID(fully_connected_nc, qp8, f32, qc4w)
XNN_FINGERPRINT_ID(fully_connected_nc, qp8, f32, qc8w)
XNN_FINGERPRINT_ID(fully_connected_nc, qp8, f32, qb4w)
Expand Down
125 changes: 125 additions & 0 deletions src/operators/fully-connected-nc.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static enum xnn_operator_type get_operator_type(
XNNPACK_FINGERPRINT_TO_OP_TYPE(qd8, bf16, qb4w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qd8, f32, qc4w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qdu8, f32, qc4w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qp8, f32, qc2w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qp8, f32, qc4w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qp8, f32, qc8w);
XNNPACK_FINGERPRINT_TO_OP_TYPE(qp8, f32, qb4w);
Expand Down Expand Up @@ -592,6 +593,26 @@ static enum xnn_status check_kernel_zero_point_is_8_qu8(
return xnn_status_success;
}

static enum xnn_status check_kernel_zero_points_are_zero(
const struct fc_variant* variant, struct fc_context* context) {
if (context->kernel_zero_points == NULL) {
return xnn_status_success;
}
const float* kernel_zero_points =
(const float*)context->kernel_zero_points;
for (size_t channel = 0; channel < context->output_channels; channel++) {
if (kernel_zero_points[channel] != 0.0f) {
xnn_log_error(
"failed to create %s operator with %.7g kernel zero point in "
"channel %zu: the SME2 QC2W kernel requires zero",
xnn_operator_type_to_string(context->operator_type),
kernel_zero_points[channel], channel);
return xnn_status_unsupported_parameter;
}
}
return xnn_status_success;
}

static enum xnn_status check_block_size(const struct fc_variant* variant,
struct fc_context* context) {
if (context->block_size < XNN_MIN_BLOCKSIZE ||
Expand Down Expand Up @@ -1015,6 +1036,20 @@ static enum xnn_status force_coherent_kernel_scale_values_f32(const struct fc_va
return xnn_status_success;
}

static enum xnn_status force_zero_kernel_zero_points_f32(
const struct fc_variant* variant, struct fc_context* context) {
if (context->kernel_zero_points == NULL) {
return xnn_status_success;
}
// Fingerprint data is owned by this context and is safe to modify.
float* kernel_zero_points =
(float*)(uintptr_t)context->kernel_zero_points;
for (size_t i = 0; i < context->output_channels; ++i) {
kernel_zero_points[i] = 0.0f;
}
return xnn_status_success;
}

static enum xnn_status force_coherent_bias_values_i32(
const struct fc_variant* variant, struct fc_context* context) {
// We cast the `const` away because we know that the data was created for the
Expand Down Expand Up @@ -1142,6 +1177,21 @@ static const struct fc_variant qp8_f32_qc4w_variant = {
.kernel_scale_element_size = sizeof(float),
};

static const struct fc_variant qp8_f32_qc2w_variant = {
.check_output_bounds = check_output_bounds_f32,
.check_kernel_zero_point = check_kernel_zero_points_are_zero,
.check_block_size = UNUSED,
.check_flags = UNUSED,
.setup_gemm_ukernels = setup_gemm_ukernels,
.setup_params = setup_params_f32,
.setup_packing_params = setup_packing_params_qd8_qc2w_izp1,
.setup_packing_functions = setup_packing_functions_from_gemm_config,
.setup_scale_params = setup_scale_params_qs8_qc8w,
.fingerprint_constraints = {force_zero_kernel_zero_points_f32},
.extra_weights_bytes = sizeof(float) * 2,
.kernel_scale_element_size = sizeof(float),
};

static const struct fc_variant qp8_f32_qc8w_variant = {
.check_output_bounds = check_output_bounds_f32,
.check_kernel_zero_point = UNUSED,
Expand Down Expand Up @@ -1472,6 +1522,12 @@ static enum xnn_status setup_variant_and_gemm_config(
context->gemm_config = xnn_init_qdu8_f32_qc4w_gemm_config();
context->fingerprint_id = xnn_fingerprint_id_fully_connected_nc_qdu8_f32_qc4w;
break;
case xnn_operator_type_fully_connected_nc_qp8_f32_qc2w:
*variant = &qp8_f32_qc2w_variant;
context->gemm_config = xnn_init_qp8_f32_qc2w_gemm_config();
context->fingerprint_id =
xnn_fingerprint_id_fully_connected_nc_qp8_f32_qc2w;
break;
case xnn_operator_type_fully_connected_nc_qp8_f32_qc4w:
*variant = &qp8_f32_qc4w_variant;
context->gemm_config = xnn_init_qp8_f32_qc4w_gemm_config();
Expand Down Expand Up @@ -2122,6 +2178,52 @@ enum xnn_status xnn_create_fully_connected_nc_qp8_f32_qc4w(
return create_fully_connected_nc_helper(&context);
}

enum xnn_status xnn_create_fully_connected_nc_qp8_f32_qc2w(
size_t input_channels, size_t output_channels, size_t input_stride,
size_t output_stride, const float* kernel_zero_point,
const float* kernel_scale, const void* kernel, const float* bias,
float output_min, float output_max, uint32_t flags,
xnn_weights_cache_t weights_cache,
xnn_operator_t* fully_connected_op_out) {
if ((flags & XNN_FLAG_TRANSPOSE_WEIGHTS) != 0) {
xnn_log_error(
"failed to create QP8/F32/QC2W operator: the SME2 kernel requires "
"NxK weights");
return xnn_status_unsupported_parameter;
}
if (input_channels % 32 != 0) {
xnn_log_error(
"failed to create QP8/F32/QC2W operator with %zu input channels: "
"the SME2 kernel requires a multiple of 32",
input_channels);
return xnn_status_unsupported_parameter;
}
if (kernel == NULL || kernel_scale == NULL) {
xnn_log_error(
"failed to create QP8/F32/QC2W operator: static weights and "
"per-channel scales are required");
return xnn_status_invalid_parameter;
}
struct fc_context context = {
.input_channels = input_channels,
.output_channels = output_channels,
.input_stride = input_stride,
.output_stride = output_stride,
.kernel_zero_points = kernel_zero_point,
.kernel_scale.f32 = kernel_scale,
.kernel = kernel,
.bias = bias,
.output_min = output_min,
.output_max = output_max,
.flags = flags,
.weights_cache = weights_cache,
.operator_type = xnn_operator_type_fully_connected_nc_qp8_f32_qc2w,
.fully_connected_op_out = fully_connected_op_out,
.should_fingerprint = true,
};
return create_fully_connected_nc_helper(&context);
}

enum xnn_status xnn_create_fully_connected_nc_qp8_f32_qc8w(
size_t input_channels, size_t output_channels, size_t input_stride,
size_t output_stride, const float* kernel_scale, const void* kernel,
Expand Down Expand Up @@ -2922,6 +3024,7 @@ static XNN_NO_SANITIZE_FUNCTION enum xnn_status reshape_fully_connected_nc(
}
break;
case xnn_operator_type_fully_connected_nc_qp8_f32_qb4w:
case xnn_operator_type_fully_connected_nc_qp8_f32_qc2w:
case xnn_operator_type_fully_connected_nc_qp8_f32_qc4w:
case xnn_operator_type_fully_connected_nc_qp8_f32_qc8w:
packed_lh_config = xnn_init_qp8_pack_lh_config();
Expand Down Expand Up @@ -3467,6 +3570,19 @@ enum xnn_status xnn_reshape_fully_connected_nc_qp8_f32_qc4w(
threadpool);
}

enum xnn_status xnn_reshape_fully_connected_nc_qp8_f32_qc2w(
xnn_operator_t fully_connected_op, size_t batch_size,
size_t* workspace_size, pthreadpool_t threadpool) {
return reshape_fully_connected_nc(
fully_connected_op, xnn_operator_type_fully_connected_nc_qp8_f32_qc2w,
batch_size,
/*dynamic_quantization=*/false,
/*log2_output_element_size=*/XNN_LOG2_SIZEOF_FLOAT,
&fully_connected_op->params.f32_minmax,
sizeof(fully_connected_op->params.f32_minmax), workspace_size,
threadpool);
}

enum xnn_status xnn_reshape_fully_connected_nc_qp8_f32_qc8w(
xnn_operator_t fully_connected_op, size_t batch_size,
size_t* workspace_size, pthreadpool_t threadpool) {
Expand Down Expand Up @@ -3821,6 +3937,15 @@ enum xnn_status xnn_setup_fully_connected_nc_qp8_f32_qc4w(
input, output, workspace, /*row_sum=*/NULL, /*quantization_params=*/NULL);
}

enum xnn_status xnn_setup_fully_connected_nc_qp8_f32_qc2w(
xnn_operator_t fully_connected_op, const int8_t* input, float* output,
void* workspace) {
return setup_fully_connected_nc(
fully_connected_op, xnn_operator_type_fully_connected_nc_qp8_f32_qc2w,
input, output, workspace, /*row_sum=*/NULL,
/*quantization_params=*/NULL);
}

enum xnn_status xnn_setup_fully_connected_nc_qp8_f32_qc8w(
xnn_operator_t fully_connected_op, const int8_t* input, float* output,
void* workspace) {
Expand Down
40 changes: 40 additions & 0 deletions src/qp8-f32-qc2w-gemm/qp8-f32-qc2w-gemm-minmax-16x64c4-neonsme2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2026 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.

#include <assert.h>
#include <stddef.h>

#include "src/xnnpack/microparams.h"

#if XNN_ENABLE_KLEIDIAI
#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsu2cxp/kai_matmul_clamp_f32_qai8dxp1vlx4_qsu2cxp4vlx4_1vlx4vl_sme2_mopa.h"

static const int32_t xnn_qc2w_signed_lut[4] = {0, 1, -2, -1};

size_t xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2_get_mr(void) {
return kai_get_mr_matmul_clamp_f32_qai8dxp1vlx4_qsu2cxp4vlx4_1vlx4vl_sme2_mopa();
}

size_t xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2_get_nr(void) {
return kai_get_nr_matmul_clamp_f32_qai8dxp1vlx4_qsu2cxp4vlx4_1vlx4vl_sme2_mopa();
}
#endif // XNN_ENABLE_KLEIDIAI

void xnn_qp8_f32_qc2w_gemm_minmax_ukernel_16x64c4__neonsme2(
size_t m, size_t n, size_t k, const void* lhs_packed,
const void* rhs_packed, float* dst, size_t dst_stride_row,
size_t dst_stride_col, struct xnn_f32_minmax_params* minmax_params) {
#if XNN_ENABLE_KLEIDIAI
kai_run_matmul_clamp_f32_qai8dxp1vlx4_qsu2cxp4vlx4_1vlx4vl_sme2_mopa(
m, n, k, lhs_packed, rhs_packed, dst, dst_stride_row,
/*dst_stride_col=*/sizeof(float), minmax_params->scalar.min,
minmax_params->scalar.max, xnn_qc2w_signed_lut);
#else
assert(
"Calling KleidiAI microkernel wrapper, but XNNPACK was compiled without "
"`XNN_ENABLE_KLEIDIAI`." &&
0);
#endif // XNN_ENABLE_KLEIDIAI
}
Loading