//---------------------------------------------------------------------------- // EgalTech 2015-2019 //---------------------------------------------------------------------------- // File : GetCpuInfo.cpp Data : 27.12.19 Versione : 2.2a1 // Contenuto : Funzioni per informazioni sulla CPU. // // // // Modifiche : 11.03.15 DS Creazione modulo. // 27.12.19 DS Aggiunta lettura supporto AVX e AVX2. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "/EgtDEv/Include/EGnPcInfo.h" #include "/EgtDEv/Include/EGnStringUtils.h" #include #define NOMINMAX #include "Windows.h" using namespace std ; //------------------------------ Costanti ------------------------------------ // Bit indici estensioni della CPU static const int BIT_MMX = 0x00800000 ; static const int BIT_SSE = 0x02000000 ; static const int BIT_SSE2 = 0x04000000 ; static const int BIT_AVX = 0x20000000 ; static const int BIT_AVX2 = 0x00000020 ; static const int BIT_3DNOW = 0x80000000 ; // lunghezza nomi static const int VNAME_LEN = 3*sizeof(int) ; //------------------------------ Strutture ------------------------------------- struct CpuInfo { string sVendorName ; // nome del venditore string sBrandName ; // brand int nFamily ; // family of the processor int nExtModel ; // extended model of processor int nModel ; // model of processor int nStepping ; // processor revision number } ; //------------------------------ Prototipi locali ------------------------------ static int ReadCpuInfo( CpuInfo& Info) ; static bool OsSupport( int nExtra) ; static string GetModelName( const char* szVendorName, int nFamily, int nExtModel, int nModel, int nStepping) ; static string GetExtraString( int nExtra) ; static int GetProcNbr( void) ; //------------------------------------------------------------------------------ bool GetCpuInfo( string& sCpuInfo) { // verifico validità stringa di ritorno if ( &sCpuInfo == nullptr) return false ; // recupero informazioni sulla CPU CpuInfo Info ; int nExtra = ReadCpuInfo( Info) ; // costruisco stringa per estensioni string sExtra = GetExtraString( nExtra) ; // recupero il numero di processori int nProc = GetProcNbr() ; sCpuInfo = "CPU " + Info.sBrandName ; sCpuInfo += " - " + ToString( nProc) + " threads" ; sCpuInfo += " - " + sExtra ; return true ; } //------------------------------------------------------------------------------ // Ritorna nella struttura informazioni sulla CPU. // Valore di ritorno 0 se impossibile usare CPUID, altrimenti extra abilitate. //------------------------------------------------------------------------------ int ReadCpuInfo( CpuInfo& Info) { int CPUInfo[4] ; // lettura info base 0 CPUInfo[0] = 0 ; __cpuid( CPUInfo, 0) ; unsigned Ids = CPUInfo[0] ; if ( Ids == 0) return 0 ; // nome del venditore char CPUString[VNAME_LEN+1] ; *((int*)CPUString) = CPUInfo[1] ; *((int*)(CPUString+sizeof(int))) = CPUInfo[3] ; *((int*)(CPUString+2*sizeof(int))) = CPUInfo[2] ; CPUString[VNAME_LEN] = 0 ; Info.sVendorName = CPUString ; // lettura info base 1 __cpuid( CPUInfo, 1) ; // stepping, model, family, extended model Info.nStepping = CPUInfo[0] & 0xF ; Info.nModel = ( CPUInfo[0] >> 4) & 0xF ; Info.nFamily = ( CPUInfo[0] >> 8) & 0xF ; Info.nExtModel = ( CPUInfo[0] >> 16) & 0xF ; int nExtra = 0 ; if ( ( CPUInfo[3] & BIT_MMX) && OsSupport( BIT_MMX)) nExtra |= BIT_MMX ; if ( ( CPUInfo[3] & BIT_SSE) && OsSupport( BIT_SSE)) nExtra |= BIT_SSE ; if ( (CPUInfo[3] & BIT_SSE2) && OsSupport( BIT_SSE2)) nExtra |= BIT_SSE2 ; if ( (CPUInfo[2] & BIT_AVX)) nExtra |= BIT_AVX ; // lettura info base 7 if ( Ids >= 7) { __cpuid( CPUInfo, 7) ; if ( (CPUInfo[1] & BIT_AVX2)) nExtra |= BIT_AVX2 ; } // lettura info estese 0 __cpuid( CPUInfo, 0x80000000) ; unsigned nExIds = CPUInfo[0] ; // lettura info estese 1 if ( nExIds >= 0x80000001) { __cpuid( CPUInfo, 0x80000001) ; if ( (CPUInfo[3] & BIT_3DNOW) && OsSupport( BIT_3DNOW)) nExtra |= BIT_3DNOW ; } // lettura info estese 2, 3 e 4 if ( nExIds >= 0x80000004) { char CPUBrandString[4 * sizeof(CPUInfo)] ; memset( CPUBrandString, 0, sizeof( CPUBrandString)) ; __cpuid( CPUInfo, 0x80000002) ; memcpy( CPUBrandString, CPUInfo, sizeof(CPUInfo)) ; __cpuid( CPUInfo, 0x80000003) ; memcpy( CPUBrandString + sizeof(CPUInfo), CPUInfo, sizeof(CPUInfo)); __cpuid( CPUInfo, 0x80000004) ; memcpy( CPUBrandString + 2 * sizeof(CPUInfo), CPUInfo, sizeof(CPUInfo)); Info.sBrandName = CPUBrandString ; Trim( Info.sBrandName) ; } else // costruisco stringa per nome modello Info.sBrandName = GetModelName( Info.sVendorName.c_str(), Info.nFamily, Info.nExtModel, Info.nModel, Info.nStepping) ; return nExtra ; } //------------------------------------------------------------------------------ // Verifica se il sistema operativo supporta la prestazione extra passata. //------------------------------------------------------------------------------ bool OsSupport( int nExtra) { #ifndef _WIN64 try { switch ( nExtra) { case BIT_MMX : __asm { pxor mm0, mm0 // executing MMX instruction emms } break ; case BIT_SSE : __asm { xorps xmm0, xmm0 // executing SSE instruction } break ; case BIT_SSE2 : __asm { xorpd xmm0, xmm0 // executing SSE2 instruction } break ; case BIT_3DNOW : __asm { pfrcp mm0, mm0 // executing 3DNow! instruction emms } break ; } } //#pragma warning (suppress: 6320) catch ( ...) { return false ; } #endif return true ; } //------------------------------------------------------------------------------ string GetModelName( const char* szVendorName, int nFamily, int nExtModel, int nModel, int nStepping) { string sModelName ; // se AMD if ( strncmp( "AuthenticAMD", szVendorName, VNAME_LEN) == 0) sModelName = "AMD " ; // se Intel else if ( strncmp( "GenuineIntel", szVendorName, VNAME_LEN) == 0) sModelName = "INTEL " ; // se Cyrix else if ( strncmp( "CyrixInstead", szVendorName, VNAME_LEN) == 0) sModelName = "Cyrix " ; // se Centaur else if ( strncmp( "CentaurHauls", szVendorName, VNAME_LEN) == 0) sModelName = "Centaur " ; // se Transmeta else if ( strncmp( "TransmetaCPU", szVendorName, VNAME_LEN) == 0 || strncmp( "GenuineTMx86", szVendorName, VNAME_LEN) == 0) sModelName = "Transmeta " ; // se VIA else if ( strncmp( "VIA VIA VIA ", szVendorName, VNAME_LEN) == 0) sModelName = "VIA " ; // altrimenti else sModelName = "Unknown " ; // completo la stringa sModelName += "(F" + ToString( nFamily) ; sModelName += "E" + ToString( nExtModel) ; sModelName += "M" + ToString( nModel) ; sModelName += "S" + ToString( nStepping) + ")" ; return sModelName ; } //------------------------------------------------------------------------------ string GetExtraString( int nExtra) { string sExtra ; if ( nExtra & BIT_MMX) sExtra += "MMX+" ; if ( nExtra & BIT_SSE) sExtra += "SSE+" ; if ( nExtra & BIT_SSE2) sExtra += "SSE2+" ; if ( nExtra & BIT_3DNOW) sExtra += "3DNOW!+" ; if ( nExtra & BIT_AVX) sExtra += "AVX+" ; if ( nExtra & BIT_AVX2) sExtra += "AVX2+" ; sExtra.pop_back() ; return sExtra ; } //------------------------------------------------------------------------------ int GetProcNbr( void) { SYSTEM_INFO sInfo ; GetSystemInfo( &sInfo) ; return sInfo.dwNumberOfProcessors ; }