![]() |
Re: Level 2 Cache
Zitat:
Aber du könntest vielleicht mal dem Autor 'ne freundliche Mail schicken (siehe About-Fenster), entweder gibt er die die Quellcodes oder er sagt dir, wo er genaue Informationen her hatte. |
Re: Level 2 Cache
Moin!
Ich habe dir mal eine kleine Unit zusammen gestrickt, die gibt dir die Info als String zurück. Bisher wird nur Intel und AMD unterstützt, da ich die Doku zum Cyrix nicht gefunden habe und für Transmeta/VIA, etc fehlen mir diese noch...
Delphi-Quellcode:
MfG
Unit L2Cache;
Interface Function GetL2CacheSize : String; Implementation uses sysutils; Function CheckForCPUID : Boolean; Assembler; Asm push ebx push ecx pushfd // save EFLAGS pop eax // store EFLAGS in EAX mov ebx, eax // save in EBX for later testing xor eax, 00200000h // toggle bit 21 push eax // put to stack popfd // save changed EAX to ELFAGS pushfd // push EFLAGS on stack pop ecx // store EFLAGS in EAX mov Result, False cmp ecx, ebx // see if bit 21 has changed jz @@no_CPUID // if no change, no CPUID mov Result, True // set flag @@no_CPUID: pop ecx pop ebx End; Function GetL2CacheSize : String; Var CPUID_VendorID : Array[0..11] Of Char; MaxStdLevel, MaxExtLevel : LongWord; Function GetIntelCacheInfo : String; Var CallCtr : Byte; Regs : array[0..3] Of LongWord; i : Integer; KBSize : Word; Function CacheInfo(CacheID : Byte): Word; Begin Case CacheID Of $39, $3B, $41, $79 : Result := 128; $3C, $42, $7A, $82 : Result := 256; $43, $7B, $83, $86 : Result := 512; $44, $7C, $84, $87 : Result := 1024; $85, $45 : Result := 2048; Else Result := 0; End; End; Begin Asm push eax push ebx push ecx push edx mov eax, 2 db 00fh, 0a2h mov CallCtr, al mov Regs[0].longword, eax mov Regs[1].longword, ebx mov Regs[2].longword, ecx mov Regs[3].longword, edx pop edx pop ecx pop ebx pop eax End; // CallCtr lass ich mal aussen vor, wird bisher noch nicht benutzt von Intel (also noch nicht > 1) KBSize := 0; If ( Regs[0] And $80000000 ) = 0 Then Begin If ( ( Regs[0] Shr 8 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 8 ) And $ff)); If ( ( Regs[0] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 16 ) And $ff)); If ( ( Regs[0] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 24 ) And $ff)); End; For i := 1 To 3 Do Begin If ( Regs[i] And $80000000 ) = 0 Then Begin If ( ( Regs[i] Shr 8 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 8 ) And $ff)); If ( ( Regs[i] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 16 ) And $ff)); If ( ( Regs[i] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 24 ) And $ff)); End; End; If ( KBSize > 1000 ) Then Result := IntToStr(KBSize) + ' KB' Else Result := IntToStr(KBSize Div 1024) + ' MB'; End; Function GetAMDCacheInfo : String; Var KBSize : Word; Begin Asm push eax push ebx push ecx push edx mov eax, 080000006h db 00fh, 0a2h shr ecx, 16 mov KBSize, cx pop edx pop ecx pop ebx pop eax End; If ( KBSize > 1000 ) Then Result := IntToStr(KBSize) + ' KB' Else Result := IntToStr(KBSize Div 1024) + ' MB'; End; Begin If ( CheckForCPUID ) Then Begin // Get Vendor Asm push eax push ebx push ecx push edx xor eax, eax db 00fh, 0a2h // CPUID mov MaxStdLevel, eax push edi lea edi, CPUID_VendorID cld // bx, dx, cx mov eax, ebx stosd mov eax, edx stosd mov eax, ecx stosd pop edi mov eax, 080000000h db 00fh, 0a2h // CPUID mov MaxExtLevel, eax pop edx pop ecx pop ebx pop eax End; If ( String(CPUID_VendorID) = 'GenuineIntel' ) Then Begin If ( MaxStdLevel >= 2 ) Then Result := GetIntelCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'AuthenticAMD' ) Then Begin If ( MaxExtLevel >= $80000006 ) Then // ab K6-III Result := GetAMDCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'CyrixInstead' ) Then Begin // habe die M2 doku nicht mehr gefunden und zum C2/C3 habe ich noch keine... Result := 'no cache info'; End; // Transmeta und weitere erstmal wegfallen lassen... End Else Result := 'no CPUID support'; End; End. Muetze1 |
Re: Level 2 Cache
wow :thuimb:
|
Re: Level 2 Cache
:shock: alter Falter...
|
Re: Level 2 Cache
Moin!
Eine Rückmeldung wäre nicht schlecht - ich habe nur ein Intel P4 hier - falls noch wer diesen Code mal ausprobiert und schreibt ob's klappt - ein AMD'ler wäre gar nicht mal so schlecht, meine AMD Systeme habe ich alle verscherbelt... Die Unit ist nur mal so schnell hingeschrieben - z.T. aus meinem CPUID Projekt, daher wären die Rückmeldungen recht witzig zu wissen... MfG Muetze1 |
Re: Level 2 Cache
Athlon XP 2000+ oder so 0MB l2 Cache, ka ob das dingen überhaupt l2cache hat oder nicht ;)
|
Re: Level 2 Cache
Moin!
Hmm, sehr komisch. Ich habe nochmal mit der Doku verglichen und den Code durchgeschaut, aber eigentlich sollte alles ok sein. Vor allem wundert es mich, das er MB ausgibt, da dein Athlon entweder 256KB oder 512KB haben kann und daher gar nicht auf MB kommen sollte. Sei mal bitte so nett und nimm mal die IF Anweisung ab Zeile 142 raus und lass es dir mal fest in KB zurückgeben... Wenn das dann auch nix hilft, dann muss ich mir im nächsten Monat nochmal schnell einen XP zusammen bauen... Danke schonmal für die Rückmeldung. MfG Muetze1 |
Re: Level 2 Cache
256 KB ;) musst wohl das if statement überarbeiten, würds gerne selbst machen aber rachmaninoff ist hier ;)
:hi: phlux |
Re: Level 2 Cache
Moin!
:wall: Mensch, manchmal wird man auch betriebsblind... Die If Bedingung ist einfach falsch herum gestellt (Wenn mehr als 1000 KB, dann zeige in KB an, ansonsten in MB)... Ok, ich ändere den Code mal schnell... @other: Falls ihr den Code schon genutzt habt, If Bedingung 2x ändern (ja ja Copy&Paste) oder nochmals neu kopieren und einfügen... /EDIT: Ok, ändern geht nicht mehr in diesem Forum und dafür den Mod belästigen muss nicht sein, daher jetzt der funktionierende Code...
Delphi-Quellcode:
Ich habe den Code gleich mal ein wenig kommentiert, damit kommt vielleicht ein wenig Klarheit auf über das was ich da überhaupt mache...
Unit L2Cache;
Interface Function GetL2CacheSize : String; Implementation uses sysutils; // prüfen, ob die CPU die CPUID Instruktion unterstützt // // Anmerkung: Bei Cyrix M2 CPU's muss man die Instruktion vorher in einem // Cyrix spezifischen Register enablen, sonst ist sie unbekannt // und die EFlags verhalten sich dem entsprechend. In diesem Falle // ist das aber hinfällig, da Cyrix CPU's keine Cache Informationen // über CPUID zurückliefern sondern nur über ihre Configuration // Register auf Port $FE und $FF... Function CheckForCPUID : Boolean; Assembler; Asm push ebx push ecx pushfd // save EFLAGS pop eax // store EFLAGS in EAX mov ebx, eax // save in EBX for later testing xor eax, 00200000h // toggle bit 21 push eax // put to stack popfd // save changed EAX to ELFAGS pushfd // push EFLAGS on stack pop ecx // store EFLAGS in EAX mov Result, False cmp ecx, ebx // see if bit 21 has changed jz @@no_CPUID // if no change, no CPUID mov Result, True // set flag @@no_CPUID: pop ecx pop ebx End; Function GetL2CacheSize : String; Var CPUID_VendorID : Array[0..11] Of Char; // für den Vendor-String MaxStdLevel, // höchstes CPUID Standardlevel MaxExtLevel : LongWord; // höchstes CPUID erweitertes Level // Unterfunktion für Intel CPU's Function GetIntelCacheInfo : String; Var CallCtr : Byte; // gibt an, wie oft CPUID 02h aufgerufen // werden muss, um alle Cache Info's zu // bekommen Regs : array[0..3] Of LongWord; // Speicher für die Register nach CPUID 02h i : Integer; // Zählvariable KBSize : Word; // die Grösse des L2 Caches in KByte // die Intel CPU's geben in mehreren Byte Werten ihre Info's an, und // es kann mehrere ID's für den selben Cache Typ geben, daher hier anhand // der ID die Grösse zurückgeben oder 0, wenn es kein L2 Cache Deskriptor war Function CacheInfo(CacheID : Byte): Word; Begin Case CacheID Of $39, $3B, $41, $79 : Result := 128; $3C, $42, $7A, $82 : Result := 256; $43, $7B, $83, $86 : Result := 512; $44, $7C, $84, $87 : Result := 1024; $85, $45 : Result := 2048; Else Result := 0; End; End; // ok, ans eingemachte für die Intel Cache Info's Begin Asm push eax // register sichern - alle - auch wenn in der Delphi Hilfe push ebx // steht, das man einzelne Register frei verändern darf. push ecx // Diese Aussage trifft nur bei nicht optimierte Codes zu, wenn push edx // die Optimierung an ist (default), dann fällt Delphi dadurch // gerne auf die Schnauze... mov eax, 2 // Funktion laden (hier: 0000.0002h) db 00fh, 0a2h // CPUID mov CallCtr, al // CallCtr merken mov Regs[0].longword, eax // Register sichern zum auswerten mov Regs[1].longword, ebx mov Regs[2].longword, ecx mov Regs[3].longword, edx pop edx // Register wiederherstellen, damit Delphi keine Problem bekommt pop ecx pop ebx pop eax End; // CallCtr lass ich mal aussen vor, wird bisher noch nicht benutzt von Intel // (also noch nicht > 1) // ok, dann zählen wir mal die KBytes zusammen der einzelnen Deskriptoren KBSize := 0; If ( Regs[0] And $80000000 ) = 0 Then // prüfen ob gültige Angabe Begin If ( ( Regs[0] Shr 8 ) And $ff ) > 0 Then // wenn was drinne steht ... Inc(KBSize, CacheInfo(( Regs[0] Shr 8 ) And $ff)); // ... dann auswerten If ( ( Regs[0] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 16 ) And $ff)); If ( ( Regs[0] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 24 ) And $ff)); End; // da in EAX der CallCtr mit drinne steht, wird das hier drüber extra behandelt // und die restlichen können wir in einem Rutsch durchgehen For i := 1 To 3 Do Begin If ( Regs[i] And $80000000 ) = 0 Then Begin If ( ( Regs[i] Shr 8 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 8 ) And $ff)); If ( ( Regs[i] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 16 ) And $ff)); If ( ( Regs[i] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 24 ) And $ff)); End; End; // Ausgabe bilden If ( KBSize < 1024 ) Then // noch im KByte Bereich? Result := IntToStr(KBSize) + ' KB' // ok, dann KByte Else Result := IntToStr(KBSize Div 1024) + ' MB'; // nein, also MByte End; // ok, gleiches für AMD Function GetAMDCacheInfo : String; Var KBSize : Word; Begin // AMD macht es uns einfacher, die haben direkt eine Angabe des L1 und L2 // Cache-Grösse in KByte als Rückgabewert Asm push eax // siehe oben push ebx push ecx push edx mov eax, 080000006h // Funktionsnummer laden (hier: 8000.0006h) db 00fh, 0a2h // CPUID shr ecx, 16 // in Bits 16..31 steht die Grösse in KByte mov KBSize, cx // daher: runterschieben und die 16 Bits merken pop edx pop ecx pop ebx pop eax End; // Ausgabe bilden - same procedure as every cpu... ;-) If ( KBSize < 1024 ) Then Result := IntToStr(KBSize) + ' KB' Else Result := IntToStr(KBSize Div 1024) + ' MB'; End; Begin // ok, hier gehts los If ( CheckForCPUID ) Then // haben wir überhaupt eine Chance, oder anders: Begin // bietet die CPU einen CPUID Befehl? Asm push eax // wieder Register sichern... push ebx push ecx push edx // xor eax, eax setzt eax auf 0 - laut AMD Optimizing Doc ist mov eax, 0 // schneller beim AMD. Laut Intel ist xor eax, eax schneller bei Intel... xor eax, eax // Funktionsnummer laden (hier: 0000.0000h) db 00fh, 0a2h // CPUID // in EAX steht das höchste Standard CPUID Level -> merken mov MaxStdLevel, eax // wir wollen den Vendor String speichern - und das geht am einfachsten // mit den String Befehlen der CPU... push edi // enhanced destination index = Zieladresse // vorher aber erstmal sichern... lea edi, CPUID_VendorID // dann die Adresse der Variablen holen cld // direction flag löschen, wir wollen EDI erhöhen... mov eax, ebx // als erstes muss der Inhalt von EBX gespeichert // werden, und da SToreStringDword immer EAX // schreibt, muss EBX in EAX gepackt werden... stosd // ok, schreiben mov eax, edx // gleiches mit EDX stosd // und hinten ranhängen // (EDI ist jetzt schon auf CPUID_VendorID[4]) mov eax, ecx // gleiches mit ECX stosd pop edi // ok, Inhalt von EDI wiederherstellen // auf erweiterten CPUID testen mov eax, 080000000h // Funktionsnummer laden (hier: 8000.0000h) db 00fh, 0a2h // CPUID mov MaxExtLevel, eax // maximale Funktionsnummer sichern... pop edx // Register wiederherstellen pop ecx pop ebx pop eax End; // nun gehts an die Auswertung und da kocht jeder Hersteller sein eigenes // Süppchen... If ( String(CPUID_VendorID) = 'GenuineIntel' ) Then // Intel Begin If ( MaxStdLevel >= 2 ) Then // wir brauchen min. CPUID 0000.0002h Result := GetIntelCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'AuthenticAMD' ) Then // AMD Begin // wir brauchen min. CPUID 8000.0006h If ( MaxExtLevel >= $80000006 ) Then // ab K6-III Result := GetAMDCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'CyrixInstead' ) Then Begin // tja, die Cyrix'e - keine Cache Info im CPUID, alles per Cyrix // specific Register... Result := 'no cache info'; End; // Transmeta und weitere erstmal wegfallen lassen... End Else Result := 'no CPUID support'; End; End. MfG Muetze1 |
Re: Level 2 Cache
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz