AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Level 2 Cache

Offene Frage von "HomerGER"
Ein Thema von HomerGER · begonnen am 17. Apr 2004 · letzter Beitrag vom 12. Jun 2008
Antwort Antwort
Seite 2 von 4     12 34      
tommie-lie
(Gast)

n/a Beiträge
 
#1

Re: Level 2 Cache

  Alt 18. Apr 2004, 19:32
Zitat von HomerGER:
hast du auch denn source ?
Da das Programm nicht von mir ist und zusammen mit dem Link, den ich gefunden habe, kein weiterer für die Quellcodes angegeben war, leider nicht.
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.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: Level 2 Cache

  Alt 19. Apr 2004, 16:42
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:
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.
MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von HomerGER
HomerGER

Registriert seit: 8. Jun 2003
390 Beiträge
 
Delphi 7 Professional
 
#3

Re: Level 2 Cache

  Alt 19. Apr 2004, 20:24
wow
  Mit Zitat antworten Zitat
Benutzerbild von dizzy
dizzy

Registriert seit: 26. Nov 2003
Ort: Lünen
1.932 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Level 2 Cache

  Alt 19. Apr 2004, 20:48
alter Falter...
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#5

Re: Level 2 Cache

  Alt 20. Apr 2004, 20:35
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
  Mit Zitat antworten Zitat
Benutzerbild von phlux
phlux

Registriert seit: 4. Nov 2002
Ort: Witten
1.335 Beiträge
 
Delphi 6 Personal
 
#6

Re: Level 2 Cache

  Alt 20. Apr 2004, 21:02
Athlon XP 2000+ oder so 0MB l2 Cache, ka ob das dingen überhaupt l2cache hat oder nicht
Christian "phlux" Arndt
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: Level 2 Cache

  Alt 20. Apr 2004, 21:16
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
  Mit Zitat antworten Zitat
Benutzerbild von phlux
phlux

Registriert seit: 4. Nov 2002
Ort: Witten
1.335 Beiträge
 
Delphi 6 Personal
 
#8

Re: Level 2 Cache

  Alt 20. Apr 2004, 22:16
256 KB musst wohl das if statement überarbeiten, würds gerne selbst machen aber rachmaninoff ist hier

phlux
Christian "phlux" Arndt
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: Level 2 Cache

  Alt 20. Apr 2004, 22:32
Moin!

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:
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.
Ich habe den Code gleich mal ein wenig kommentiert, damit kommt vielleicht ein wenig Klarheit auf über das was ich da überhaupt mache...

MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: München
6.537 Beiträge
 
#10

Re: Level 2 Cache

  Alt 21. Apr 2004, 04:32
Zitat von Muetze1:
Delphi-Quellcode:
 If ( KBSize < 1000 ) Then
      Result := IntToStr(KBSize) + ' KB
    Else
      Result := IntToStr(KBSize Div 1024) + ' MB';
Ich will ja nicht deinen schönen Code ruinieren, aber eines gibt es noch zu sagen. Wenn du die Größe in MB angibst, so solltest du überprüfen, ob die Größe auch größer als 1024 KB ist, und nicht 1000. Hier beim L2 macht das nicht viel Unterschied, da sowieso schöne 2erpotenzen herhalten, aber trotzdem...der Code wäre perfekt wenn du das noch ausbessern würdest.
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz