Add the cpuid library

This commit is contained in:
Jean Pierre Cimalando 2020-04-02 01:28:43 +02:00
parent 026a5aceee
commit 10fa64b2c8
16 changed files with 784 additions and 0 deletions

6
src/external/cpuid/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,6 @@
cmake_minimum_required (VERSION 3.5)
project(sfizz-cpuid)
add_library(sfizz-cpuid STATIC src/cpuid/cpuinfo.cpp src/cpuid/version.cpp)
set_property(TARGET sfizz-cpuid PROPERTY CXX_STANDARD 11)
target_include_directories(sfizz-cpuid PUBLIC src PRIVATE platform/src)

31
src/external/cpuid/LICENSE.rst vendored Normal file
View file

@ -0,0 +1,31 @@
cpuid license
-------------
cpuid is provided under the "BSD (3-clause) License"::
Copyright (c) 2014, Steinwurf ApS
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Steinwurf ApS nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL Steinwurf ApS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

31
src/external/cpuid/platform/LICENSE.rst vendored Normal file
View file

@ -0,0 +1,31 @@
platform license
----------------
platform is provided under the "BSD (3-clause) License"::
Copyright (c) 2014, Steinwurf ApS
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Steinwurf ApS nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL Steinwurf ApS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,159 @@
// Copyright (c) 2014 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
// Here we create a number of defines to make it easy to choose between
// different compilers, operatings systems and CPU architectures.
// Some information about the defines used can be found here:
// http://sourceforge.net/p/predef/wiki/Architectures/
// Detect operating systems
#if defined(__linux__)
#define PLATFORM_LINUX 1
#if defined(__ANDROID__)
#define PLATFORM_ANDROID 1
#endif
#elif defined(_WIN32)
#define PLATFORM_WINDOWS 1
#if defined(WINAPI_FAMILY)
#include <winapifamily.h>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
#define PLATFORM_WINDOWS_PHONE 1
#endif
#endif
#elif defined(__APPLE__)
// Detect iOS before MacOSX (__MACH__ is also defined for iOS)
#if defined(IPHONE)
#define PLATFORM_IOS 1
#elif defined(__MACH__)
#define PLATFORM_MAC 1
#endif
#elif defined(__EMSCRIPTEN__)
#define PLATFORM_EMSCRIPTEN 1
#else
#error "Unable to determine operating system"
#endif
// Detect compilers and CPU architectures
// Note: clang also defines __GNUC__ since it aims to be compatible with GCC.
// Therefore we need to check for __clang__ or __llvm__ first.
#if defined(__clang__) || defined(__llvm__)
#define PLATFORM_CLANG 1
#define PLATFORM_GCC_COMPATIBLE 1
#if defined(__i386__) || defined(__x86_64__)
#define PLATFORM_X86 1
#define PLATFORM_CLANG_X86 1
#define PLATFORM_GCC_COMPATIBLE_X86 1
#elif defined(__arm__) || defined (__arm64__) || defined (__aarch64__)
#define PLATFORM_ARM 1
#define PLATFORM_CLANG_ARM 1
#define PLATFORM_GCC_COMPATIBLE_ARM 1
#elif defined(__mips__)
#define PLATFORM_MIPS 1
#define PLATFORM_CLANG_MIPS 1
#define PLATFORM_GCC_COMPATIBLE_MIPS 1
#elif defined(__asmjs__)
#define PLATFORM_ASMJS 1
#define PLATFORM_CLANG_ASMJS 1
#define PLATFORM_GCC_COMPATIBLE_ASMJS 1
#endif
#elif defined(__GNUC__)
#define PLATFORM_GCC 1
#define PLATFORM_GCC_COMPATIBLE 1
#if defined(__i386__) || defined(__x86_64__)
#define PLATFORM_X86 1
#define PLATFORM_GCC_X86 1
#define PLATFORM_GCC_COMPATIBLE_X86 1
#elif defined(__arm__) || defined (__arm64__) || defined (__aarch64__)
#define PLATFORM_ARM 1
#define PLATFORM_GCC_ARM 1
#define PLATFORM_GCC_COMPATIBLE_ARM 1
#elif defined(__mips__)
#define PLATFORM_MIPS 1
#define PLATFORM_GCC_MIPS 1
#define PLATFORM_GCC_COMPATIBLE_MIPS 1
#endif
#elif defined(_MSC_VER)
#define PLATFORM_MSVC 1
#if defined(_M_IX86) || defined(_M_X64)
#define PLATFORM_X86 1
#define PLATFORM_MSVC_X86 1
#elif defined(_M_ARM) || defined(_M_ARMT)
#define PLATFORM_ARM 1
#define PLATFORM_MSVC_ARM 1
#endif
#else
#error "Unable to determine compiler"
#endif
// Define macros for supported CPU instruction sets
#if defined(PLATFORM_GCC_COMPATIBLE)
#if defined(__MMX__)
#define PLATFORM_MMX 1
#endif
#if defined(__SSE__)
#define PLATFORM_SSE 1
#endif
#if defined(__SSE2__)
#define PLATFORM_SSE2 1
#endif
#if defined(__SSE3__)
#define PLATFORM_SSE3 1
#endif
#if defined(__SSSE3__)
#define PLATFORM_SSSE3 1
#endif
#if defined(__SSE4_1__)
#define PLATFORM_SSE41 1
#endif
#if defined(__SSE4_2__)
#define PLATFORM_SSE42 1
#endif
#if defined(__PCLMUL__)
#define PLATFORM_PCLMUL 1
#endif
#if defined(__AVX__)
#define PLATFORM_AVX 1
#endif
#if defined(__AVX2__)
#define PLATFORM_AVX2 1
#endif
#if defined(__ARM_NEON__) || defined (__ARM_NEON)
#define PLATFORM_NEON 1
#endif
// First, check the PLATFORM_WINDOWS_PHONE define, because
// the X86 instructions sets are not supported on the Windows Phone emulator
#elif defined(PLATFORM_WINDOWS_PHONE)
#if defined(PLATFORM_MSVC_ARM)
// NEON introduced in VS2012
#if (_MSC_VER >= 1700)
#define PLATFORM_NEON 1
#endif
#endif
#elif defined(PLATFORM_MSVC_X86)
// MMX, SSE and SSE2 introduced in VS2003
#if (_MSC_VER >= 1310)
#define PLATFORM_MMX 1
#define PLATFORM_SSE 1
#define PLATFORM_SSE2 1
#endif
// SSE3 introduced in VS2005
#if (_MSC_VER >= 1400)
#define PLATFORM_SSE3 1
#endif
// SSSE3, SSE4.1, SSE4.2, PCLMUL introduced in VS2008
#if (_MSC_VER >= 1500)
#define PLATFORM_SSSE3 1
#define PLATFORM_SSE41 1
#define PLATFORM_SSE42 1
#define PLATFORM_PCLMUL 1
#endif
// AVX and AVX2 introduced in VS2012
#if (_MSC_VER >= 1700)
#define PLATFORM_AVX 1
#define PLATFORM_AVX2 1
#endif
#endif

103
src/external/cpuid/src/cpuid/cpuinfo.cpp vendored Normal file
View file

@ -0,0 +1,103 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#include <platform/config.hpp>
#include "cpuinfo.hpp"
#include "detail/cpuinfo_impl.hpp"
#if defined(PLATFORM_GCC_COMPATIBLE_X86)
#include "detail/init_gcc_x86.hpp"
#elif defined(PLATFORM_MSVC_X86) && !defined(PLATFORM_WINDOWS_PHONE)
#include "detail/init_msvc_x86.hpp"
#elif defined(PLATFORM_MSVC_ARM)
#include "detail/init_msvc_arm.hpp"
#elif defined(PLATFORM_CLANG_ARM) && defined(PLATFORM_IOS)
#include "detail/init_ios_clang_arm.hpp"
#elif defined(PLATFORM_GCC_COMPATIBLE_ARM) && defined(PLATFORM_LINUX)
#include "detail/init_linux_gcc_arm.hpp"
#else
#include "detail/init_unknown.hpp"
#endif
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
cpuinfo::cpuinfo() :
m_impl(new impl)
{
init_cpuinfo(*m_impl);
}
cpuinfo::~cpuinfo()
{
}
// x86 member functions
bool cpuinfo::has_fpu() const
{
return m_impl->m_has_fpu;
}
bool cpuinfo::has_mmx() const
{
return m_impl->m_has_mmx;
}
bool cpuinfo::has_sse() const
{
return m_impl->m_has_sse;
}
bool cpuinfo::has_sse2() const
{
return m_impl->m_has_sse2;
}
bool cpuinfo::has_sse3() const
{
return m_impl->m_has_sse3;
}
bool cpuinfo::has_ssse3() const
{
return m_impl->m_has_ssse3;
}
bool cpuinfo::has_sse4_1() const
{
return m_impl->m_has_sse4_1;
}
bool cpuinfo::has_sse4_2() const
{
return m_impl->m_has_sse4_2;
}
bool cpuinfo::has_pclmulqdq() const
{
return m_impl->m_has_pclmulqdq;
}
bool cpuinfo::has_avx() const
{
return m_impl->m_has_avx;
}
bool cpuinfo::has_avx2() const
{
return m_impl->m_has_avx2;
}
// ARM functions
bool cpuinfo::has_neon() const
{
return m_impl->m_has_neon;
}
}
}

View file

@ -0,0 +1,72 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <memory>
#include "version.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// The cpuinfo object extract information about which, if any, additional
/// instructiions are supported by the CPU.
class cpuinfo
{
public:
/// Constructor for feature detection with default values
cpuinfo();
/// Destructor
~cpuinfo();
/// Has X87 FPU
bool has_fpu() const;
/// Return true if the CPU supports MMX
bool has_mmx() const;
/// Return true if the CPU supports SSE
bool has_sse() const;
/// Return true if the CPU supports SSE2
bool has_sse2() const;
/// Return true if the CPU supports SSE3
bool has_sse3() const;
/// Return true if the CPU supports SSSE3
bool has_ssse3() const;
/// Return true if the CPU supports SSE 4.1
bool has_sse4_1() const;
/// Return true if the CPU supports SSE 4.2
bool has_sse4_2() const;
/// Return true if the CPU supports pclmulqdq
bool has_pclmulqdq() const;
/// Return true if the CPU supports AVX
bool has_avx() const;
/// Return true if the CPU supports AVX2
bool has_avx2() const;
/// ARM member functions
bool has_neon() const;
public:
/// Private implementation
struct impl;
private:
/// Pimpl pointer
std::unique_ptr<impl> m_impl;
};
}
}

View file

@ -0,0 +1,39 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include "../cpuinfo.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
struct cpuinfo::impl
{
impl() :
m_has_fpu(false), m_has_mmx(false), m_has_sse(false), m_has_sse2(false),
m_has_sse3(false), m_has_ssse3(false), m_has_sse4_1(false),
m_has_sse4_2(false), m_has_pclmulqdq(false), m_has_avx(false),
m_has_avx2(false), m_has_neon(false)
{
}
bool m_has_fpu;
bool m_has_mmx;
bool m_has_sse;
bool m_has_sse2;
bool m_has_sse3;
bool m_has_ssse3;
bool m_has_sse4_1;
bool m_has_sse4_2;
bool m_has_pclmulqdq;
bool m_has_avx;
bool m_has_avx2;
bool m_has_neon;
};
}
}

View file

@ -0,0 +1,39 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <cstdint>
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
void extract_x86_flags(cpuinfo::impl& info, uint32_t ecx, uint32_t edx)
{
// Instruction set flags
info.m_has_fpu = (edx & (1 << 0)) != 0;
info.m_has_mmx = (edx & (1 << 23)) != 0;
info.m_has_sse = (edx & (1 << 25)) != 0;
info.m_has_sse2 = (edx & (1 << 26)) != 0;
info.m_has_sse3 = (ecx & (1 << 0)) != 0;
info.m_has_ssse3 = (ecx & (1 << 9)) != 0;
info.m_has_sse4_1 = (ecx & (1 << 19)) != 0;
info.m_has_sse4_2 = (ecx & (1 << 20)) != 0;
info.m_has_pclmulqdq = (ecx & (1 << 1)) != 0;
info.m_has_avx = (ecx & (1 << 28)) != 0;
}
void extract_x86_extended_flags(cpuinfo::impl& info, uint32_t ebx)
{
// Extended instruction set flags
info.m_has_avx2 = (ebx & (1 << 5)) != 0;
}
}
}

View file

@ -0,0 +1,73 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <cstdint>
#include "cpuinfo_impl.hpp"
#include "extract_x86_flags.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
// Reference for this code is Intel's recommendation for detecting AVX2
// on Haswell located here: http://goo.gl/c6IkGX
void run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd)
{
uint32_t ebx = 0, edx = 0;
#if defined(__i386__) && defined(__PIC__)
// If PIC used under 32-bit, EBX cannot be clobbered
// EBX is saved to EDI and later restored
__asm__("movl %%ebx, %%edi;"
"cpuid;"
"xchgl %%ebx, %%edi;"
: "=D"(ebx), "+a"(eax), "+c"(ecx), "=d"(edx));
#else
__asm__("cpuid;" : "+b"(ebx), "+a"(eax), "+c"(ecx), "=d"(edx));
#endif
abcd[0] = eax;
abcd[1] = ebx;
abcd[2] = ecx;
abcd[3] = edx;
}
/// @todo Document
void init_cpuinfo(cpuinfo::impl& info)
{
// Note: We need to capture these 4 registers, otherwise we get
// a segmentation fault on 32-bit Linux
uint32_t output[4];
// The register information per input can be extracted from here:
// http://en.wikipedia.org/wiki/CPUID
// CPUID should be called with EAX=0 first, as this will return the
// maximum supported EAX input value for future calls
run_cpuid(0, 0, output);
uint32_t maximum_index = output[0];
// Set registers for basic flag extraction
// All CPUs should support index=1
if (maximum_index >= 1U)
{
run_cpuid(1, 0, output);
extract_x86_flags(info, output[2], output[3]);
}
// Set registers for extended flags extraction using index=7
// This operation is not supported on older CPUs, so it should be skipped
// to avoid incorrect results
if (maximum_index >= 7U)
{
run_cpuid(7, 0, output);
extract_x86_extended_flags(info, output[1]);
}
}
}
}

View file

@ -0,0 +1,30 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// @todo docs
void init_cpuinfo(cpuinfo::impl& info)
{
// The __ARM_NEON__ macro will be defined by the Apple Clang compiler
// when targeting ARMv7 processors that have NEON.
// The compiler guarantees this capability, so there is no benefit
// in doing a runtime check. More info in this SO answer:
// http://stackoverflow.com/a/1601234
#if defined __ARM_NEON__
info.m_has_neon = true;
#else
info.m_has_neon = false;
#endif
}
}
}

View file

@ -0,0 +1,64 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <cassert>
#include <cstdio>
#include <cstring>
#include <elf.h>
#include <fcntl.h>
#include <linux/auxvec.h>
#include <unistd.h>
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// @todo docs
void init_cpuinfo(cpuinfo::impl& info)
{
#if defined(__aarch64__)
// The Advanced SIMD (NEON) instruction set is required on AArch64
// (64-bit ARM). Note that /proc/cpuinfo will display "asimd" instead of
// "neon" in the Features list on a 64-bit ARM CPU.
info.m_has_neon = true;
#else
// Runtime detection of NEON is necessary on 32-bit ARM CPUs
//
// Follow recommendation from Cortex-A Series Programmer's guide
// in Section 20.1.7 Detecting NEON. The guide is available at
// Steinwurf's Google drive: steinwurf/technical/experimental/cpuid
auto cpufile = open("/proc/self/auxv", O_RDONLY);
assert(cpufile);
Elf32_auxv_t auxv;
if (cpufile >= 0)
{
const auto size_auxv_t = sizeof(Elf32_auxv_t);
while (read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
{
if (auxv.a_type == AT_HWCAP)
{
info.m_has_neon = (auxv.a_un.a_val & 4096) != 0;
break;
}
}
close(cpufile);
}
else
{
info.m_has_neon = false;
}
#endif
}
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
void init_cpuinfo(cpuinfo::impl& info)
{
// Visual Studio 2012 (and above) guarantees the NEON capability when
// compiling for Windows Phone 8 (and above)
#if defined(PLATFORM_WINDOWS_PHONE)
info.m_has_neon = true;
#else
info.m_has_neon = false;
#endif
}
}
}

View file

@ -0,0 +1,52 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <intrin.h>
#include "cpuinfo_impl.hpp"
#include "extract_x86_flags.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// @todo docs
void init_cpuinfo(cpuinfo::impl& info)
{
int registers[4];
/// According to the msvc docs eax, ebx, ecx and edx are
/// stored (in that order) in the array passed to the __cpuid
/// function.
// The register information per input can be extracted from here:
// http://en.wikipedia.org/wiki/CPUID
// CPUID should be called with EAX=0 first, as this will return the
// maximum supported EAX input value for future calls
__cpuid(registers, 0);
uint32_t maximum_eax = registers[0];
// Set registers for basic flag extraction, eax=1
// All CPUs should support index=1
if (maximum_eax >= 1U)
{
__cpuid(registers, 1);
extract_x86_flags(info, registers[2], registers[3]);
}
// Set registers for extended flags extraction, eax=7 and ecx=0
// This operation is not supported on older CPUs, so it should be skipped
// to avoid incorrect results
if (maximum_eax >= 7U)
{
__cpuidex(registers, 7, 0);
extract_x86_extended_flags(info, registers[1]);
}
}
}
}

View file

@ -0,0 +1,20 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// @todo docs
void init_cpuinfo(cpuinfo::impl& info)
{
(void)info;
}
}
}

View file

@ -0,0 +1,18 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#include "version.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
std::string version()
{
return "6.3.1";
}
}
}

View file

@ -0,0 +1,21 @@
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <string>
namespace cpuid
{
/// Here we define the STEINWURF_CPUID_VERSION this should be updated on each
/// release
#define STEINWURF_CPUID_VERSION v6_3_1
inline namespace STEINWURF_CPUID_VERSION
{
/// @return The version of the library as string
std::string version();
}
}