diff --git a/StgSharp.Native/SIMDID.x86.md b/StgSharp.Native/SIMDID.x86.md
new file mode 100644
index 00000000..31b2f213
--- /dev/null
+++ b/StgSharp.Native/SIMDID.x86.md
@@ -0,0 +1,182 @@
+# SIMDID(x86-64)64-bit 规范(按你给定的固定布局补全)
+
+本文按你指定的 **64-bit SIMDID** 位布局进行补全,重点给出 **AVX512 Feature 区段([31..16])** 的设计,使其既能覆盖 AVX-512 混乱的子集,又能保持分支逻辑尽量精简。
+
+> 约定:bit0 为最低位(LSB)。本文只定义 x86-64 解释器下的语义;Header 的 Root ISA 允许扩展到其他架构。
+
+---
+
+## 1) ASCII 位布局(最终)
+
+```
+SIMDID (64 bits) [63 ........................................................ 0]
++--------------------------+-----------+----------------+----------------+----------------+----------------+
+| [63..40] uArch/Policy | [39..32] | [31..16] | [15..8] | [7..4] | [3..0] |
+| (24 bits, optional) | AMX Future| AVX512 Feature | MainLevel | Manufacture | Root ISA |
++--------------------------+-----------+----------------+----------------+----------------+----------------+
+```
+
+- **[3..0] Root ISA**:根指令集类型(用于选择解释器)
+- **[7..4] Manufacture**:制造商信息(对 x86 来说 Intel/AMD 等)
+- **[15..8] MainLevel**:主 ISA 等级(递增、共享比特语义)
+- **[31..16] AVX512 Feature**:AVX-512 特征/子集/实现形态(重点)
+- **[39..32] AMX Future**:AMX 特征(目前可只放少量位)
+- **[63..40] uArch/Policy**:可选策略/微架构提示(默认 0,不影响功能)
+
+---
+
+## 2) Root ISA([3..0])
+
+建议编码(你列出的架构较多,这里给一个可用的最小集合;不够可继续扩):
+
+| 值 | Root ISA |
+|---:|----------|
+| 0 | Unknown |
+| 1 | x86-64 |
+| 2 | AArch64 |
+| 3 | PPC64LE |
+| 4 | Apple Silicon(如果你想把它当“制造商+ARM”以外的 note,也可放在 Manufacture;但你要求 Root ISA 里有它,那就给它一个值) |
+| 5 | RISC-V |
+| 6 | LoongArch |
+| 7..15 | Reserved |
+
+> 注:从体系结构角度 Apple Silicon 属于 AArch64;但你既然希望在 Root ISA 层面区分,那就这样定义即可(解释器由你决定)。
+
+---
+
+## 3) Manufacture([7..4])
+
+在 **x86-64** 下建议:
+
+| 值 | Manufacture |
+|---:|-------------|
+| 0 | Unknown/Other |
+| 1 | Intel |
+| 2 | AMD |
+| 3 | VIA/Zhaoxin |
+| 4..15 | Reserved |
+
+在其它 Root ISA 下,该 nibble 由各自解释器自行定义(例如 ARM 下可放 Apple/Qualcomm/MediaTek 等)。
+
+---
+
+## 4) MainLevel([15..8],递增)
+
+你要求“共用比特且递增”,也就是说数值越大能力越强(或至少在你的库调度中越靠后)。建议定为:
+
+| 值 | MainLevel |
+|---:|-----------|
+| 0 | NONE |
+| 1 | SSE(完整 SSE 家族:SSE1..SSE4.2) |
+| 2 | AVX2 |
+| 3 | AVX2_FMA |
+| 4 | AVX2_FMA_F16C(从该级开始可处理 16-bit 类型) |
+| 5 | AVX512(需要查询 [31..16]) |
+| 6 | AMX |
+| 7 | AVX10 |
+| 8..255 | Reserved |
+
+> 建议调度:`MainLevel` 是主 switch;只有当 `MainLevel>=AVX512` 才解析 `AVX512 Feature`;当 `MainLevel>=AMX` 才解析 `AMX Future`。
+
+---
+
+## 5) AVX512 Feature([31..16])设计目标(精简版)
+
+目标改为:
+
+1) **基础 AVX512 一次性判定**:用 1 bit 表示“F+CD+VL+DQ+BW”这一捆绑基础包,避免多次子集判断。
+2) **胶水 vs 原生**:用实现字段直接区分 `AVX512-DUAL`(胶水/降频风险)与 `AVX512-NATIVE`(完整 512 位 ALU)。
+3) **小众/AI 扩展单独留位**:VNNI、BF16/FP16 等稀疏出现的扩展单独占位,基础路径不受干扰。
+
+---
+
+## 6) AVX512 Feature 位布局([31..16] = 16 bits,精简)
+
+
+AVX512 Feature (bits 31..16)
+
+| **bit** | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
+|-----------|-----|-----|------|------|------|-------|------|------|-------|-------|----|------|----|----|----|----|
+| **Usage** | R | R | FP16 | BF16 | VNNI | VBMI2 | VBMI | R/AI | Impl1 | Impl0 | R | BASE | R | R | R | R |
+
+
+说明:
+
+- **BASE(bit 20)**:基础 AVX512 一揽子,表示同时具备 `F + CD + VL + DQ + BW`。这是 AVX512 最低可用门槛,探测端若设为 1,应保证上述子集都成立。
+- **AVX512_IMPL([23..22],2-bit)**:实现形态(宽度策略)。
+
+| 值 | 含义 |
+|---:|------|
+| 0 | Unknown(需结合 Manufacture/uArch 决定策略) |
+| 1 | AVX512-DUAL(胶水/降频风险,建议默认 256 宽路径) |
+| 2 | AVX512-NATIVE(完整 512 位 ALU,可走 512 宽路径) |
+| 3 | Reserved |
+
+- **VBMI/VBMI2/VNNI/BF16/FP16([29..26])**:稀疏但常用的小类型/AI 扩展,按需设置。
+- **R/AI(bit 24)**:预留给未来 AI 或其他非密码学的自选扩展。
+- **[31..30]、[21]、[19..16]**:Reserved,按需再分配。
+
+---
+
+## 7) “AVX512BASE” 判定(一次性检查)
+
+- **规则**:`BASE=1` 即视为具备 `F+CD+VL+DQ+BW`,无需逐项再查。探测端必须保持一致性,若无法保证全部子集齐备则应置 0。
+- **运行时分支**:
+ - 若 `MainLevel < AVX512`:直接降级到 AVX2/FMA 路径。
+ - 否则:
+ - 检查 `BASE`;若为 0 则降级到 AVX2/FMA(或视为探测错误)。
+ - 查看 `AVX512_IMPL`:`DUAL` 走 256 宽/降频安全路径,`NATIVE` 走 512 宽路径。
+ - 需要小类型/AI 能力时,按位查看 `VNNI/BF16/FP16/VBMI/VBMI2`。
+
+---
+
+## 8) AMX Future([39..32],8 bits)
+
+你已经留了 1 个字节,建议先只定义 3 个最常见位,其余保留:
+
+| bit(相对 [39..32]) | 名称 | 说明 |
+|---:|------|------|
+| 0 | AMX_TILE | tile 基础 |
+| 1 | AMX_INT8 | INT8 tile |
+| 2 | AMX_BF16 | BF16 tile |
+| 3..7 | Reserved | |
+
+当 `MainLevel < AMX` 时,这个字节可全为 0。
+
+---
+
+## 9) uArch/Policy([63..40],24 bits)
+
+用途:**你不想浪费比特,但又需要解决“Intel 早期/AMD 胶水”这类非 CPUID 纯子集能解决的问题**。
+把它留作可选策略字段,默认 0;你需要时再启用。
+
+建议最小化用法:
+- `0`:未使用
+- `1`:ForceDual(即使 impl unknown 也当 AVX512-DUAL)
+- `2`:ForceNative(即使 impl unknown 也当 AVX512-NATIVE)
+- `3..`:你自己维护的 uArch 枚举(例如 SKX/ICL/SPR/ZEN4/ZEN5…)
+
+> 由于你是单人维护,最现实的策略是:
+> - AMD:探测端直接把 `AVX512_IMPL=DUAL`(无需 uArch)
+> - Intel:仅对你关心的少数型号做 uArch 枚举,否则 unknown 走默认策略
+
+---
+
+## 10) 建议的最简探测端填充规则(x86-64)
+
+1) 先填 `RootISA=x86-64`、`Manufacture=Intel/AMD`
+2) 计算 `MainLevel`(按你递增规则)
+3) 若 `MainLevel >= AVX512`:
+ - 若探测到 `F+CD+VL+DQ+BW` 全部成立,则置 `BASE=1`,否则 `BASE=0`
+ - 填 `AVX512_IMPL`:
+ - AMD:DUAL(按你的定义)
+ - Intel:可按 family/model 或 policy 表决定 DUAL/NATIVE;不确定就 Unknown
+ - 需要 VNNI/BF16/FP16/VBMI/VBMI2 时,按位填写对应扩展
+4) 若 `MainLevel >= AMX`:填 AMX byte
+
+---
+
+## 11) 你需要做的一个选择(高位保留位如何分配)
+
+目前 `[31..24]` 留作扩展/AI:示例定义为 FP16/BF16/VNNI/VBMI2/VBMI + 1 个预留位。
+如果你更需要 IFMA 或其他非密码学扩展,请替换 bit26~29 的定义;`BASE` 与 `Impl` 保持不变即可。
\ No newline at end of file
diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj
index e16d55be..b3f14864 100644
--- a/StgSharp.Native/StgSharp.Native.vcxproj
+++ b/StgSharp.Native/StgSharp.Native.vcxproj
@@ -154,18 +154,19 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
CCode
+
@@ -189,6 +190,9 @@
+
+
+
diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters
index 8754294f..c282bd74 100644
--- a/StgSharp.Native/StgSharp.Native.vcxproj.filters
+++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters
@@ -13,15 +13,18 @@
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+ {fbd74b53-5314-4d9d-a788-07bd1b413f74}
+
源文件
-
+
源文件
-
+
源文件
@@ -39,22 +42,25 @@
源文件
-
+
源文件
-
+
源文件
源文件
-
+
源文件
-
+
源文件
-
+
+ 源文件
+
+
源文件
@@ -104,4 +110,9 @@
资源文件
+
+
+ Document
+
+
\ No newline at end of file
diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h
index a04779a0..c02e43ce 100644
--- a/StgSharp.Native/sn-head/sn_intrinsic.h
+++ b/StgSharp.Native/sn-head/sn_intrinsic.h
@@ -1,4 +1,4 @@
-#ifndef SSC_INTRIN
+#ifndef SSC_INTRIN
#define SSC_INTRIN
#define SSC_INTRIN_HEAD
@@ -22,7 +22,8 @@
(LASTTWO(source - 1) << 6) | (LASTTWO(target - 1) << 4) | (LAST(reset3) << 3) | \
(LAST(reset2) << 2) | (LAST(reset1) << 1) | LAST(reset0)
#define SSE_INSERT_SIMPLE(source, target) SSE_INSERT(source, target, 0, 0, 0, 0)
-#define M256_PERMUTE(s3, s2, s1, s0) (LASTTWO(s3) << 6) | (LASTTWO(s2) << 4) | (LASTTWO(s1) << 2) | (LASTTWO(s0)
+#define M256_PERMUTE(s3, s2, s1, s0) \
+ ((LASTTWO(s3) << 6) | (LASTTWO(s2) << 4) | (LASTTWO(s1) << 2) | (LASTTWO(s0)))
#define BIT_CVRT(pack, index, T) *(T *)(pack->data + index)
#define zero_vec _mm_setzero_ps()
#define zero_vec_256 _mm256_setzero_ps()
@@ -92,8 +93,8 @@ typedef struct matrix_task matrix_task;
#if defined(__cplusplus)
static_assert(sizeof(matrix_task) == 128, "matrix_parallel_task_package size mismatch");
-#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
-_Static_assert(sizeof(MAT_TASK(float)) == 128, "matrix_parallel_task_package size mismatch");
+#elif defined(__STDC_VERSION__)
+ static_assert(sizeof(MAT_TASK(float)) == 128, "matrix_parallel_task_package size mismatch");
#endif
#pragma region matrix buffer operation function type
@@ -197,6 +198,114 @@ typedef void(SN_DECL *VECTORNORMALIZEPROC)(__m128 *source, __m128 *target);
typedef void(SN_DECL *DOTPROC)(void *transpose, __m128 *vector, __m128 *ans);
typedef uint64_t(SN_DECL *FACTORIALROC)(int n);
+#pragma region string
+
+typedef int(SN_DECL *HASH)(byte const *str, int length);
+typedef int(SN_DECL *INDEX_PAIR)(short const *stram, uint32_t target, int length);
+
+#pragma endregion
+
+typedef struct mat_intrinsic {
+ BUF_PROC_LRA buffer_add;
+ BUF_PROC_AS buffer_fill;
+ BUF_PROC_RAS buffer_scalar_mul;
+ BUF_PROC_LRA buffer_sub;
+ KER_PROC_RA buffer_transpose;
+ PANEL_PROC build_panel;
+ PANEL_PROC clear_panel;
+ PNL_PROC_LRA panel_fma;
+ PIVOTPROC pivot;
+ PANEL_PROC store_panel;
+
+} mat_intrinsic;
+
+// Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync.
+typedef struct sn_intrinsic {
+ HASH city_hash_simplify;
+ FACTORIALROC factorial_simd;
+ INDEX_PAIR index_pair;
+ VECTORNORMALIZEPROC vec_f32_normalize_3;
+ mat_intrinsic mat[4];
+} sn_intrinsic;
+
+typedef enum elment_type { F32 = 0, F64 = 1, I32 = 2, I64 = 3 } element_type;
+
+typedef enum most_advanced_instruction {
+#ifdef _MSC_VER
+ SSE = __IA_SUPPORT_SSE42,
+ AVX256 = __IA_SUPPORT_VECTOR256,
+ AVX512 = __IA_SUPPORT_VECTOR512,
+ NEON
+#else
+ SSE,
+ AVX256,
+ AVX512,
+ NEON
+#endif
+} most_advanced_instruction;
+
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
+// -----------------------------------------------------------------------------
+// SIMDID layout helpers (see SIMDID.simd.md)
+// bits [3..0] : Root ISA
+// bits [7..4] : Manufacture (ISA-specific)
+// bits [15..8] : MainLevel (monotonic capability)
+// bits [31..16]: AVX512 Feature
+// bits [39..32]: AMX Feature
+// bits [63..40]: uArch / Policy (optional)
+// -----------------------------------------------------------------------------
+#define SIMDID_SHIFT_ROOT 0
+#define SIMDID_SHIFT_MANU 4
+#define SIMDID_SHIFT_MAIN 8
+#define SIMDID_SHIFT_AVX512 16
+#define SIMDID_SHIFT_AMX 32
+#define SIMDID_SHIFT_UARCH 40
+
+#define SIMDID_MASK_ROOT 0xFULL
+#define SIMDID_MASK_MANU (0xFULL << SIMDID_SHIFT_MANU)
+#define SIMDID_MASK_MAIN (0xFFULL << SIMDID_SHIFT_MAIN)
+#define SIMDID_MASK_AVX512 (0xFFFFULL << SIMDID_SHIFT_AVX512)
+#define SIMDID_MASK_AMX (0xFFULL << SIMDID_SHIFT_AMX)
+#define SIMDID_MASK_UARCH (0xFFFFFFULL << SIMDID_SHIFT_UARCH)
+
+// Root ISA (low nibble)
+#define SIMDID_ROOT_UNKNOWN 0x0
+#define SIMDID_ROOT_X86_64 0x1
+#define SIMDID_ROOT_AARCH64 0x2
+#define SIMDID_ROOT_PPC64LE 0x3
+#define SIMDID_ROOT_APPLESILICON 0x4
+#define SIMDID_ROOT_RISCV64 0x5
+#define SIMDID_ROOT_LOONGARCH 0x6
+
+// Manufacture (x86-64 mapping; other ISAs may reinterpret)
+#define SIMDID_MANU_UNKNOWN 0x0
+#define SIMDID_MANU_INTEL 0x1
+#define SIMDID_MANU_AMD 0x2
+#define SIMDID_MANU_VIA 0x3
+
+// MainLevel (ordinal, shared bits 8..15; not bit-flags)
+#define SIMDID_MAIN_LVL_NONE 0x00u
+#define SIMDID_MAIN_LVL_SSE 0x01u /* SSE1..SSE4.2 */
+#define SIMDID_MAIN_LVL_AVX2 0x02u
+#define SIMDID_MAIN_LVL_AVX2_FMA 0x03u
+#define SIMDID_MAIN_LVL_AVX2_FMA_F16C 0x04u /* 16-bit scalar/vector ready */
+#define SIMDID_MAIN_LVL_AVX512 0x05u
+#define SIMDID_MAIN_LVL_AMX 0x06u
+#define SIMDID_MAIN_LVL_AVX10 0x07u
+
+/* Pre-shifted helpers for convenience when constructing SIMDID */
+#define SIMDID_MAIN_ENC_NONE SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_NONE)
+#define SIMDID_MAIN_ENC_SSE SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_SSE)
+#define SIMDID_MAIN_ENC_AVX2 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2)
+#define SIMDID_MAIN_ENC_AVX2_FMA SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2_FMA)
+#define SIMDID_MAIN_ENC_AVX2_FMA_F16C SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2_FMA_F16C)
+#define SIMDID_MAIN_ENC_AVX512 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX512)
+#define SIMDID_MAIN_ENC_AMX SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AMX)
+#define SIMDID_MAIN_ENC_AVX10 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX10)
+
#pragma region matix function
INTERNAL void f32_normalize(VEC(float) * source, VEC(float) * target);
@@ -281,85 +390,15 @@ INTERNAL void SN_DECL dot_42_avx(MAT_KERNEL(float) const *transpose, __m128 cons
#pragma region string
-typedef int(SN_DECL *HASH)(byte const *str, int length);
-typedef int(SN_DECL *INDEX_PAIR)(short const *stram, uint32_t target, int length);
-
INTERNAL int SN_DECL city_hash_simplify_sse(byte const *str, int length);
-INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int length);
+INTERNAL int SN_DECL index_pair_sse(short const *stram, uint32_t target, int length);
#pragma endregion
-typedef struct mat_intrinsic {
- BUF_PROC_LRA buffer_add;
- BUF_PROC_AS buffer_fill;
- BUF_PROC_RAS buffer_scalar_mul;
- BUF_PROC_LRA buffer_sub;
- KER_PROC_RA buffer_transpose;
- PANEL_PROC build_panel;
- PANEL_PROC clear_panel;
- PNL_PROC_LRA panel_fma;
- PIVOTPROC pivot;
- PANEL_PROC store_panel;
-
-} mat_intrinsic;
-
-// Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync.
-typedef struct sn_intrinsic {
- HASH city_hash_simplify;
- FACTORIALROC factorial_simd;
- INDEX_PAIR index_pair;
- VECTORNORMALIZEPROC vec_f32_normalize_3;
- mat_intrinsic mat[4];
-} sn_intrinsic;
-
-typedef enum elment_type { F32 = 0, F64 = 1, I32 = 2, I64 = 3 } element_type;
-
-typedef enum most_advanced_instruction {
-#ifdef _MSC_VER
- SSE = __IA_SUPPORT_SSE42,
- AVX256 = __IA_SUPPORT_VECTOR256,
- AVX512 = __IA_SUPPORT_VECTOR512,
- NEON
#else
- SSE,
- AVX256,
- AVX512,
- NEON
-#endif
-} most_advanced_instruction;
-#include "sn_target.h"
+typedef enum intrinsic_level { SIMD0 = 0 } intrinsic_level;
-#if SN_IS_ARCH(SN_ARCH_X86_64)
-
-typedef enum intrinsic_level {
- // No SIMD support, will cause error if used in matrix operations
- SIMD0 = 0,
- // SSE4.2 support
- SIMD1 = 1,
- // AVX2 support
- SIMD2 = 2,
- // AVX2 and AVX2-FMA support
- SIMD3 = 3,
- // AVX2-16C support based on SIMD3
- SIMD4 = 4,
- // AVX-512-dual support
- SIMD5 = 5,
- // AVX-512-native support
- SIMD6 = 6,
- // AVX-512 with 8/16-wide support
- SIMD7 = 7,
- // AMX support
- SIMD8 = 8,
- // AVX-10 support
- SIMD9 = 9,
- // future use
- SIMD_MAX = 10
-} intrinsic_level;
-
-#else
-typedef enum intrinsic_level {
-} intrinsic_level;
#endif
#endif
diff --git a/StgSharp.Native/sn-head/sn_target.h b/StgSharp.Native/sn-head/sn_target.h
index 5724ec84..e5d6ea5c 100644
--- a/StgSharp.Native/sn-head/sn_target.h
+++ b/StgSharp.Native/sn-head/sn_target.h
@@ -1,21 +1,20 @@
-#ifndef SN_TARGET
+#ifndef SN_TARGET
#define SN_TARGET
-typedef enum SN_OS_T {
- SN_OS_WINDOWS,
- SN_OS_LINUX,
- SN_OS_MACOS,
- SN_OS_IOS,
- SN_OS_ANDROID,
- SN_OS_UNKNOWN
-} SN_OS_T;
+#include "sn_internal.h"
+#include
-typedef enum SN_ARCH_T {
- SN_ARCH_X86_64,
- SN_ARCH_ARM64,
- SN_ARCH_RISCV64,
- SN_ARCH_PPC64le,
-} SN_ARCH_T;
+#define SN_OS_WINDOWS 0
+#define SN_OS_LINUX 1
+#define SN_OS_MACOS 2
+#define SN_OS_IOS 3
+#define SN_OS_ANDROID 4
+#define SN_OS_UNKNOWN 5
+
+#define SN_ARCH_X86_64 0
+#define SN_ARCH_ARM64 1
+#define SN_ARCH_RISCV64 2
+#define SN_ARCH_PPC64le 3
/*
* Target selection policy:
@@ -38,24 +37,28 @@ typedef enum SN_ARCH_T {
#endif
/* Validate externally supplied values are within known enum constants. */
-#if (SN_OS_TARGET != SN_OS_WINDOWS) && (SN_OS_TARGET != SN_OS_LINUX) && (SN_OS_TARGET != SN_OS_MACOS) && \
- (SN_OS_TARGET != SN_OS_IOS) && (SN_OS_TARGET != SN_OS_ANDROID) && (SN_OS_TARGET != SN_OS_UNKNOWN)
+#if (SN_OS_TARGET != SN_OS_WINDOWS) && (SN_OS_TARGET != SN_OS_LINUX) && \
+ (SN_OS_TARGET != SN_OS_MACOS) && (SN_OS_TARGET != SN_OS_IOS) && \
+ (SN_OS_TARGET != SN_OS_ANDROID) && (SN_OS_TARGET != SN_OS_UNKNOWN)
#error "SN_OS has an invalid value. Use SN_OS_<...> enum constants."
#endif
-#if (SN_ARCH_TARGET != SN_ARCH_X86_64) && (SN_ARCH_TARGET != SN_ARCH_ARM64) && (SN_ARCH_TARGET != SN_ARCH_RISCV64) && \
- (SN_ARCH_TARGET != SN_ARCH_PPC64le)
+#if (SN_ARCH_TARGET != SN_ARCH_X86_64) && (SN_ARCH_TARGET != SN_ARCH_ARM64) && \
+ (SN_ARCH_TARGET != SN_ARCH_RISCV64) && (SN_ARCH_TARGET != SN_ARCH_PPC64le)
#error "SN_ARCH has an invalid value. Use SN_ARCH_<...> enum constants."
#endif
#endif
-#ifndef SN_IS_OS
#define SN_IS_OS(os) ((SN_OS_TARGET) == (os))
-#endif
-#ifndef SN_IS_ARCH
#define SN_IS_ARCH(arch) ((SN_ARCH_TARGET) == (arch))
-#endif
+
+typedef union SIMDID {
+ uint64_t mask;
+ char make_byte[];
+} SIMDID;
+
+SN_API SIMDID SN_DECL sn_get_simd_level();
#endif // SN_TARGET
diff --git a/StgSharp.Native/sn-src/cpuid.c b/StgSharp.Native/sn-src/cpuid.c
new file mode 100644
index 00000000..947d66f3
--- /dev/null
+++ b/StgSharp.Native/sn-src/cpuid.c
@@ -0,0 +1,226 @@
+#include "sn_target.h"
+#include "sn_intrinsic.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
+#ifndef SIMDID_AVX512_BASE
+#define SIMDID_AVX512_FP16 (1U << 29)
+#define SIMDID_AVX512_BF16 (1U << 28)
+#define SIMDID_AVX512_VNNI (1U << 27)
+#define SIMDID_AVX512_VBMI2 (1U << 26)
+#define SIMDID_AVX512_VBMI (1U << 25)
+#define SIMDID_AVX512_AI_RESERVED (1U << 24)
+#define SIMDID_AVX512_BASE (1U << 20)
+#define SIMDID_AVX512_IMPL_SHIFT 22
+#define SIMDID_AVX512_IMPL_MASK (0x3U << SIMDID_AVX512_IMPL_SHIFT)
+#define SIMDID_AVX512_IMPL_UNKNOWN (0x0U << SIMDID_AVX512_IMPL_SHIFT)
+#define SIMDID_AVX512_IMPL_DUAL (0x1U << SIMDID_AVX512_IMPL_SHIFT)
+#define SIMDID_AVX512_IMPL_NATIVE (0x2U << SIMDID_AVX512_IMPL_SHIFT)
+#endif
+
+#ifndef SIMDID_AMX_TILE
+#define SIMDID_AMX_TILE (1ULL << 32)
+#define SIMDID_AMX_INT8 (1ULL << 33)
+#define SIMDID_AMX_BF16 (1ULL << 34)
+#endif
+
+#include
+#include
+#if defined(_MSC_VER)
+#include
+#else
+#include
+#endif
+
+static void get_cpuid(int leaf, int subleaf, int *eax, int *ebx, int *ecx, int *edx)
+{
+#if defined(_MSC_VER)
+ int regs[4];
+ __cpuidex(regs, leaf, subleaf);
+ *eax = regs[0];
+ *ebx = regs[1];
+ *ecx = regs[2];
+ *edx = regs[3];
+#else
+ unsigned int a, b, c, d;
+ __cpuid_count((unsigned int)leaf, (unsigned int)subleaf, a, b, c, d);
+ *eax = (int)a;
+ *ebx = (int)b;
+ *ecx = (int)c;
+ *edx = (int)d;
+#endif
+}
+
+static int xgetbv_has_xmm_ymm(void)
+{
+#if defined(_MSC_VER)
+ unsigned __int64 xcr0 = _xgetbv(0);
+#else
+ unsigned long long xcr0 = __builtin_ia32_xgetbv(0);
+#endif
+ return ((xcr0 & 0x6) == 0x6);
+}
+
+static int xgetbv_has_avx512_state(void)
+{
+ const unsigned long long mask = (1ull << 0) | (1ull << 1) | (1ull << 2) | (1ull << 5) |
+ (1ull << 6);
+#if defined(_MSC_VER)
+ unsigned __int64 xcr0 = _xgetbv(0);
+#else
+ unsigned long long xcr0 = __builtin_ia32_xgetbv(0);
+#endif
+ return ((xcr0 & mask) == mask);
+}
+
+static int is_intel_glue_avx512(int family, int model)
+{
+ return (family == 6) && (model == 0x55); /* SKX/CLX/CPX */
+}
+
+static int is_intel_native_avx512(int family, int model)
+{
+ if (family != 6)
+ return 0;
+ switch (model) {
+ case 0x6A: /* ICX */
+ case 0x6C: /* ICX stepping */
+ case 0x8F: /* SPR/EMR */
+ case 0xCF: /* GNR */
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+SN_API SIMDID SN_DECL sn_get_simd_level()
+{
+ SIMDID simd_id;
+ simd_id.mask = 0;
+
+ int eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ /* Vendor */
+ get_cpuid(0, 0, &eax, &ebx, &ecx, &edx);
+ char vendor[13];
+ ((int *)vendor)[0] = ebx;
+ ((int *)vendor)[1] = edx;
+ ((int *)vendor)[2] = ecx;
+ vendor[12] = '\0';
+ const int is_intel = (strcmp(vendor, "GenuineIntel") == 0);
+ const int is_amd = (strcmp(vendor, "AuthenticAMD") == 0) ||
+ (strcmp(vendor, "HygonGenuine") == 0);
+
+ /* CPUID.1 */
+ get_cpuid(1, 0, &eax, &ebx, &ecx, &edx);
+ int family = ((eax >> 8) & 0xF) + ((eax >> 20) & 0xFF0);
+ int model = ((eax >> 4) & 0xF) | ((eax >> 12) & 0xF0);
+
+ int has_sse42 = (ecx & (1 << 20)) != 0;
+ int has_avx = (ecx & (1 << 28)) != 0;
+ int has_osxsave = (ecx & (1 << 27)) != 0;
+ int has_fma = (ecx & (1 << 12)) != 0;
+
+ uint64_t root = SIMDID_PACK_ROOT(SIMDID_ROOT_X86_64);
+ uint64_t manu = SIMDID_PACK_MANU(is_intel ? SIMDID_MANU_INTEL :
+ is_amd ? SIMDID_MANU_AMD :
+ SIMDID_MANU_UNKNOWN);
+ uint64_t main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_NONE);
+ uint64_t avx512_bits = 0;
+ uint64_t amx_bits = 0;
+
+ /* Baseline main level */
+ if (has_sse42)
+ main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_SSE);
+
+ if (has_avx && has_osxsave && xgetbv_has_xmm_ymm()) {
+ /* CPUID.7.0 */
+ get_cpuid(7, 0, &eax, &ebx, &ecx, &edx);
+ const int has_bmi1 = (ebx & (1 << 3)) != 0;
+ const int has_bmi2 = (ebx & (1 << 8)) != 0;
+ const int has_avx2 = (ebx & (1 << 5)) != 0;
+ const int has_avx512f = (ebx & (1 << 16)) != 0;
+ const int has_avx512dq = (ebx & (1 << 17)) != 0;
+ const int has_avx512bw = (ebx & (1 << 30)) != 0;
+ const int has_avx512vl = (ebx & (1u << 31)) != 0;
+ const int has_avx512_vnni = (ebx & (1 << 11)) != 0;
+ const int has_vbmi = (ecx & (1 << 1)) != 0;
+ const int has_vbmi2 = (ecx & (1 << 6)) != 0;
+
+ /* leaf 7, subleaf 1 for BF16/FP16 */
+ get_cpuid(7, 1, &eax, &ebx, &ecx, &edx);
+ const int has_bf16 = (eax & (1 << 5)) != 0; /* AVX512_BF16 */
+ const int has_fp16 = (eax & (1 << 23)) != 0; /* AVX512_FP16 */
+
+ /* AMX in leaf 7 subleaf 0 EDX bits 24/25/26 */
+ const int has_amx_tile = (edx & (1 << 24)) != 0;
+ const int has_amx_int8 = (edx & (1 << 25)) != 0;
+ const int has_amx_bf16 = (edx & (1 << 26)) != 0;
+
+ if (has_avx2) {
+ if (has_fma) {
+ main_lvl = SIMDID_PACK_MAIN((has_bmi1 && has_bmi2) ?
+ SIMDID_MAIN_LVL_AVX2_FMA_F16C :
+ SIMDID_MAIN_LVL_AVX2_FMA);
+ } else {
+ main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2);
+ }
+ }
+
+ if (has_avx512f && xgetbv_has_avx512_state()) {
+ /* Ensure base subset present */
+ if (has_avx512bw && has_avx512vl && has_avx512dq) {
+ avx512_bits |= SIMDID_AVX512_BASE;
+ }
+ if (has_avx512_vnni)
+ avx512_bits |= SIMDID_AVX512_VNNI;
+ if (has_bf16)
+ avx512_bits |= SIMDID_AVX512_BF16;
+ if (has_fp16)
+ avx512_bits |= SIMDID_AVX512_FP16;
+ if (has_vbmi)
+ avx512_bits |= SIMDID_AVX512_VBMI;
+ if (has_vbmi2)
+ avx512_bits |= SIMDID_AVX512_VBMI2;
+
+ /* impl classification */
+ const int glue = is_amd || is_intel_glue_avx512(family, model);
+ const int native512 = is_intel_native_avx512(family, model);
+ if (glue) {
+ avx512_bits |= SIMDID_AVX512_IMPL_DUAL;
+ } else if (native512) {
+ avx512_bits |= SIMDID_AVX512_IMPL_NATIVE;
+ } else {
+ avx512_bits |= SIMDID_AVX512_IMPL_UNKNOWN;
+ }
+
+ /* main level for AVX512 */
+ main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX512);
+
+ /* AMX promotion if present */
+ if (has_amx_tile) {
+ amx_bits |= SIMDID_AMX_TILE;
+ if (has_amx_int8)
+ amx_bits |= SIMDID_AMX_INT8;
+ if (has_amx_bf16)
+ amx_bits |= SIMDID_AMX_BF16;
+ main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AMX);
+ }
+ }
+ }
+
+ simd_id.mask = root | manu | main_lvl | SIMDID_PACK_AVX512(avx512_bits) |
+ SIMDID_PACK_AMX(amx_bits);
+ return simd_id;
+}
+
+#else
+
+SIMDID sn_get_simd_level()
+{
+ SIMDID simd_id;
+ simd_id.mask = 0;
+ return simd_id; /* non-x86: no SIMD level probing */
+}
+
+#endif
diff --git a/StgSharp.Native/sn-src/k_basicop.c b/StgSharp.Native/sn-src/m.basic.x86.c
similarity index 97%
rename from StgSharp.Native/sn-src/k_basicop.c
rename to StgSharp.Native/sn-src/m.basic.x86.c
index 9240b2fa..ea76418f 100644
--- a/StgSharp.Native/sn-src/k_basicop.c
+++ b/StgSharp.Native/sn-src/m.basic.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_intrinsic.h"
DECLARE_PNL_PROC_ANS(float, sse, clear)
@@ -91,3 +95,5 @@ DECLARE_KER_PROC_RIGHT_ANS(float, 512, transpose)
ans->f32_z[0] = _mm512_permutexvar_ps(transpose_indices, matrix);
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/k_bufop.c b/StgSharp.Native/sn-src/m.bufop.x86.c
similarity index 99%
rename from StgSharp.Native/sn-src/k_bufop.c
rename to StgSharp.Native/sn-src/m.bufop.x86.c
index 452ba474..d143d57f 100644
--- a/StgSharp.Native/sn-src/k_bufop.c
+++ b/StgSharp.Native/sn-src/m.bufop.x86.c
@@ -1,4 +1,4 @@
-#include "sn_target.h"
+#include "sn_target.h"
#if SN_IS_ARCH(SN_ARCH_X86_64)
@@ -320,4 +320,4 @@ DECLARE_BUF_PROC_RIGHT_ANS_SCALAR(double, 512, scalar_mul)
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/StgSharp.Native/sn-src/k_fma.c b/StgSharp.Native/sn-src/m.fma.x86.c
similarity index 99%
rename from StgSharp.Native/sn-src/k_fma.c
rename to StgSharp.Native/sn-src/m.fma.x86.c
index 9da92a74..e38c90a8 100644
--- a/StgSharp.Native/sn-src/k_fma.c
+++ b/StgSharp.Native/sn-src/m.fma.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_intrinsic.h"
#define _FMA_SELECT(i) _MM_SHUFFLE(i, i, i, i)
@@ -379,3 +383,5 @@ DECLARE_PNL_PROC_LEFT_RIGHT_ANS(double, 512, fma)
_mm512_store_pd((double *)&ans->vec[col][0], ccol);
}
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/k_panel.c b/StgSharp.Native/sn-src/m.panel.x86.c
similarity index 99%
rename from StgSharp.Native/sn-src/k_panel.c
rename to StgSharp.Native/sn-src/m.panel.x86.c
index 79c751fe..6e477fc1 100644
--- a/StgSharp.Native/sn-src/k_panel.c
+++ b/StgSharp.Native/sn-src/m.panel.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_matkernel.h"
DECLARE_BUILD_PANEL(avx, float)
@@ -41,7 +45,6 @@ DECLARE_BUILD_PANEL(avx, float)
}
}
-
DECLARE_BUILD_PANEL(512, float)
{
const MAT_KERNEL(float) *const zero = (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
@@ -77,7 +80,6 @@ DECLARE_BUILD_PANEL(512, float)
}
}
-
DECLARE_BUILD_PANEL(512, double)
{
const int Q = 8; /* max(4, lanes) for double with ZMM -> 8 columns */
@@ -295,3 +297,5 @@ DECLARE_STORE_PANEL(512, double)
bot_dst->f64_y[kc_col] = bot256;
}
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/k_pivot.c b/StgSharp.Native/sn-src/m.pivot.x86.c
similarity index 97%
rename from StgSharp.Native/sn-src/k_pivot.c
rename to StgSharp.Native/sn-src/m.pivot.x86.c
index cc6a1733..8d720f35 100644
--- a/StgSharp.Native/sn-src/k_pivot.c
+++ b/StgSharp.Native/sn-src/m.pivot.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_intrinsic.h"
// Hybrid implementation: SIMD for Abs, Scalar for Max
@@ -62,3 +66,5 @@ INTERNAL void SN_DECL pivot_float(MAT_KERNEL(float) const *source, size_t col_be
}
}
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/str_factorial.c b/StgSharp.Native/sn-src/s.factorial.x86.c
similarity index 93%
rename from StgSharp.Native/sn-src/str_factorial.c
rename to StgSharp.Native/sn-src/s.factorial.x86.c
index 450bdbc5..39b7c140 100644
--- a/StgSharp.Native/sn-src/str_factorial.c
+++ b/StgSharp.Native/sn-src/s.factorial.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_internal.h"
#include "sn_intrinsic.h"
@@ -21,3 +25,5 @@ INTERNAL uint64_t SN_DECL factorial_simd_sse(int n)
}
return result;
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/str_hash.c b/StgSharp.Native/sn-src/s.hash.x86.c
similarity index 96%
rename from StgSharp.Native/sn-src/str_hash.c
rename to StgSharp.Native/sn-src/s.hash.x86.c
index 8662dab9..295b192d 100644
--- a/StgSharp.Native/sn-src/str_hash.c
+++ b/StgSharp.Native/sn-src/s.hash.x86.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_intrinsic.h"
#include "StgSharpNative.h"
@@ -43,3 +47,5 @@ INTERNAL int SN_DECL city_hash_simplify_sse(byte const *str, int const length)
hash ^= hash >> 16;
return hash;
}
+
+#endif
diff --git a/StgSharp.Native/sn-src/str_string.c b/StgSharp.Native/sn-src/str_string.c
index 37f208e7..e67d142c 100644
--- a/StgSharp.Native/sn-src/str_string.c
+++ b/StgSharp.Native/sn-src/str_string.c
@@ -1,3 +1,7 @@
+#include "sn_target.h"
+
+#if SN_IS_ARCH(SN_ARCH_X86_64)
+
#include "sn_intrinsic.h"
INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int length)
@@ -46,3 +50,5 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int lengt
}
return -1;
}
+
+#endif