[coreboot] [v2] r4886 - in trunk/coreboot-v2/util: . amdtools amdtools/example_input

svn at coreboot.org svn at coreboot.org
Wed Oct 28 20:41:53 CET 2009


Author: ward
Date: 2009-10-28 20:41:52 +0100 (Wed, 28 Oct 2009)
New Revision: 4886

Added:
   trunk/coreboot-v2/util/amdtools/
   trunk/coreboot-v2/util/amdtools/README
   trunk/coreboot-v2/util/amdtools/example_input/
   trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings
   trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings-20090909h
   trunk/coreboot-v2/util/amdtools/example_input/lspci-cb-48G-667MHz-18.2-20090909e
   trunk/coreboot-v2/util/amdtools/example_input/lspci-prop-48G-667MHz-18.2
   trunk/coreboot-v2/util/amdtools/k8-compare-pci-space.pl
   trunk/coreboot-v2/util/amdtools/k8-interpret-extended-memory-settings.pl
   trunk/coreboot-v2/util/amdtools/k8-read-mem-settings.sh
   trunk/coreboot-v2/util/amdtools/parse-bkdg.pl
Log:

Add an initial version of some tools to compare (extended) K8 memory settings.

This generates (dirty) html with interpreted differences between PCI dumps,
based on the K8 socket F bkdg.

Signed-off-by: Ward Vandewege <ward at gnu.org>
Acked-by: Stepan Reinauer <stepan at coresystems.de>



Added: trunk/coreboot-v2/util/amdtools/README
===================================================================
--- trunk/coreboot-v2/util/amdtools/README	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/README	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,32 @@
+
+
+This is a set of tools to compare (extended) K8 memory settings.
+
+Before you can use them, you need to massage the relevant BKDG sections into
+useable data. Here's how.
+
+First, you need to acquire a copy of the K8 BKDG. Go here:
+
+  Rev F: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
+
+Then make sure pdftotext is installed (it's in the poppler-utils package on Debian/Ubuntu).
+
+Now run the bkdg through pdftotext:
+
+  pdftotext -layout 32559.pdf 32559.txt
+
+Now extract sections 4.5.15 - 4.5.19 from the file, and save it separately, say as bkdg-raw.data.
+
+Finally run the txt file through the parse-bkdg.pl script like so:
+
+  parse-bkdg.pl < bkdg-raw.data > bkdg.data
+
+Now we have the bkdg.data file that is used by the other scripts.
+
+If you want to test the scripts without doing all this work, you can use some
+sample input files from the 'example_input/' directory. 
+
+-- 
+Ward Vandewege, 2009-10-28.
+ward at jhvc.com
+ 

Added: trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings
===================================================================
--- trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,96 @@
+0:18.2 98.l: 80000000
+0:18.2 9C.l: 00111222
+0:18.2 98.l: 80000001
+0:18.2 9C.l: 16171715
+0:18.2 98.l: 80000002
+0:18.2 9C.l: 1716131a
+0:18.2 98.l: 80000003
+0:18.2 9C.l: 00000019
+0:18.2 98.l: 80000004
+0:18.2 9C.l: 002f0000
+0:18.2 98.l: 80000005
+0:18.2 9C.l: 18191918
+0:18.2 98.l: 80000006
+0:18.2 9C.l: 16161917
+0:18.2 98.l: 80000007
+0:18.2 9C.l: 00000017
+0:18.2 98.l: 80000020
+0:18.2 9C.l: 00111222
+0:18.2 98.l: 80000021
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000022
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000023
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000024
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000025
+0:18.2 9C.l: 2f2f2f2f
+0:18.2 98.l: 80000026
+0:18.2 9C.l: 2f2f2f2f
+0:18.2 98.l: 80000027
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000010
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000013
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000016
+0:18.2 9C.l: 0000003f
+0:18.2 98.l: 80000019
+0:18.2 9C.l: 00000046
+0:18.2 98.l: 80000030
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000033
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000036
+0:18.2 9C.l: 00000053
+0:18.2 98.l: 80000039
+0:18.2 9C.l: 00000053
+0:19.2 98.l: 80000000
+0:19.2 9C.l: 00111222
+0:19.2 98.l: 80000001
+0:19.2 9C.l: 15151515
+0:19.2 98.l: 80000002
+0:19.2 9C.l: 15151515
+0:19.2 98.l: 80000003
+0:19.2 9C.l: 00000015
+0:19.2 98.l: 80000004
+0:19.2 9C.l: 002f0000
+0:19.2 98.l: 80000005
+0:19.2 9C.l: 19181918
+0:19.2 98.l: 80000006
+0:19.2 9C.l: 191a1817
+0:19.2 98.l: 80000007
+0:19.2 9C.l: 00000017
+0:19.2 98.l: 80000020
+0:19.2 9C.l: 00111222
+0:19.2 98.l: 80000021
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000022
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000023
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000024
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000025
+0:19.2 9C.l: 2f2f2f2f
+0:19.2 98.l: 80000026
+0:19.2 9C.l: 2f2f2f2f
+0:19.2 98.l: 80000027
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000010
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000013
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000016
+0:19.2 9C.l: 0000003b
+0:19.2 98.l: 80000019
+0:19.2 9C.l: 00000047
+0:19.2 98.l: 80000030
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000033
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000036
+0:19.2 9C.l: 00000053
+0:19.2 98.l: 80000039
+0:19.2 9C.l: 00000053

Added: trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings-20090909h
===================================================================
--- trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings-20090909h	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/example_input/coreboot-48G-667MHz-memsettings-20090909h	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,96 @@
+0:18.2 98.l: 80000000
+0:18.2 9C.l: 10111222
+0:18.2 98.l: 80000001
+0:18.2 9C.l: 17171716
+0:18.2 98.l: 80000002
+0:18.2 9C.l: 17161619
+0:18.2 98.l: 80000003
+0:18.2 9C.l: 00000018
+0:18.2 98.l: 80000004
+0:18.2 9C.l: 002f2f00
+0:18.2 98.l: 80000005
+0:18.2 9C.l: 17171716
+0:18.2 98.l: 80000006
+0:18.2 9C.l: 16171717
+0:18.2 98.l: 80000007
+0:18.2 9C.l: 00000017
+0:18.2 98.l: 80000020
+0:18.2 9C.l: 10111222
+0:18.2 98.l: 80000021
+0:18.2 9C.l: 15151515
+0:18.2 98.l: 80000022
+0:18.2 9C.l: 14161514
+0:18.2 98.l: 80000023
+0:18.2 9C.l: 00000014
+0:18.2 98.l: 80000024
+0:18.2 9C.l: 002f2f00
+0:18.2 98.l: 80000025
+0:18.2 9C.l: 1817171a
+0:18.2 98.l: 80000026
+0:18.2 9C.l: 1a191719
+0:18.2 98.l: 80000027
+0:18.2 9C.l: 00000018
+0:18.2 98.l: 80000010
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000013
+0:18.2 9C.l: 00000033
+0:18.2 98.l: 80000016
+0:18.2 9C.l: 00000065
+0:18.2 98.l: 80000019
+0:18.2 9C.l: 00000026
+0:18.2 98.l: 80000030
+0:18.2 9C.l: 00000000
+0:18.2 98.l: 80000033
+0:18.2 9C.l: 00000033
+0:18.2 98.l: 80000036
+0:18.2 9C.l: 00000065
+0:18.2 98.l: 80000039
+0:18.2 9C.l: 00000024
+0:19.2 98.l: 80000000
+0:19.2 9C.l: 10111222
+0:19.2 98.l: 80000001
+0:19.2 9C.l: 17171717
+0:19.2 98.l: 80000002
+0:19.2 9C.l: 17161617
+0:19.2 98.l: 80000003
+0:19.2 9C.l: 00000016
+0:19.2 98.l: 80000004
+0:19.2 9C.l: 002f2f00
+0:19.2 98.l: 80000005
+0:19.2 9C.l: 17171717
+0:19.2 98.l: 80000006
+0:19.2 9C.l: 17171617
+0:19.2 98.l: 80000007
+0:19.2 9C.l: 00000016
+0:19.2 98.l: 80000020
+0:19.2 9C.l: 10111222
+0:19.2 98.l: 80000021
+0:19.2 9C.l: 15151514
+0:19.2 98.l: 80000022
+0:19.2 9C.l: 14141514
+0:19.2 98.l: 80000023
+0:19.2 9C.l: 00000014
+0:19.2 98.l: 80000024
+0:19.2 9C.l: 002f2f00
+0:19.2 98.l: 80000025
+0:19.2 9C.l: 1717191a
+0:19.2 98.l: 80000026
+0:19.2 9C.l: 1a1a1919
+0:19.2 98.l: 80000027
+0:19.2 9C.l: 00000019
+0:19.2 98.l: 80000010
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000013
+0:19.2 9C.l: 00000031
+0:19.2 98.l: 80000016
+0:19.2 9C.l: 0000003a
+0:19.2 98.l: 80000019
+0:19.2 9C.l: 00000046
+0:19.2 98.l: 80000030
+0:19.2 9C.l: 00000000
+0:19.2 98.l: 80000033
+0:19.2 9C.l: 00000032
+0:19.2 98.l: 80000036
+0:19.2 9C.l: 0000003a
+0:19.2 98.l: 80000039
+0:19.2 9C.l: 00000043

Added: trunk/coreboot-v2/util/amdtools/example_input/lspci-cb-48G-667MHz-18.2-20090909e
===================================================================
--- trunk/coreboot-v2/util/amdtools/example_input/lspci-cb-48G-667MHz-18.2-20090909e	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/example_input/lspci-cb-48G-667MHz-18.2-20090909e	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,20 @@
+00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] DRAM Controller
+    Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
+    Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+00: 22 10 02 11 00 00 00 00 00 00 00 06 00 00 80 00
+10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+40: 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 01
+50: 01 00 00 02 01 00 00 03 01 00 00 04 01 00 00 05
+60: 00 00 00 00 e0 3f f8 00 e0 3f f8 00 e0 3f f8 00
+70: 00 00 00 00 00 00 00 00 66 00 00 00 00 00 00 00
+80: 80 88 00 00 00 00 00 00 24 b2 68 e3 50 5b 02 49
+90: 10 e8 08 00 7a 80 00 a4 30 00 00 80 00 00 00 00
+a0: e9 02 00 e3 00 00 00 00 00 00 00 00 00 00 00 00
+b0: b4 57 88 f5 5a 00 00 00 7f 0c 6b 67 0c 48 00 01
+c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+d0: 9f 76 62 72 89 83 11 20 21 ad 9d 60 c6 a4 19 00
+e0: 8b 12 31 29 c9 42 89 24 40 4a 14 21 c6 24 01 23
+f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+

Added: trunk/coreboot-v2/util/amdtools/example_input/lspci-prop-48G-667MHz-18.2
===================================================================
--- trunk/coreboot-v2/util/amdtools/example_input/lspci-prop-48G-667MHz-18.2	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/example_input/lspci-prop-48G-667MHz-18.2	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,19 @@
+00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron] DRAM Controller
+    Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
+    Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+00: 22 10 02 11 00 00 00 00 00 00 00 06 00 00 80 00
+10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+40: 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 01
+50: 01 00 00 02 01 00 00 03 01 00 00 04 01 00 00 05
+60: 00 00 00 00 e0 3f f8 00 e0 3f f8 00 e0 3f f8 00
+70: 00 00 00 00 00 00 00 00 46 00 00 00 00 00 00 00
+80: 80 88 00 00 00 00 00 00 24 ca 69 e3 20 13 02 49
+90: 10 e8 00 00 7a 00 00 64 39 00 00 80 44 00 00 00
+a0: eb 02 00 e3 00 00 00 00 00 00 00 00 00 00 00 00
+b0: f4 d1 6e 45 9a 00 00 00 7f 0c 6b 77 4c 48 00 20
+c0: 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
+d0: 9f 76 62 52 89 93 11 00 21 ad 95 60 c7 b4 19 01
+e0: 8b 16 31 29 c9 42 89 24 40 4a 14 21 c6 34 01 83
+f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Added: trunk/coreboot-v2/util/amdtools/k8-compare-pci-space.pl
===================================================================
--- trunk/coreboot-v2/util/amdtools/k8-compare-pci-space.pl	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/k8-compare-pci-space.pl	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,311 @@
+#!/usr/bin/perl -w
+use Getopt::Long;
+
+use strict;
+
+my $NAME = $0;
+my $VERSION = '0.01';
+my $DATE = '2009-09-04';
+my $AUTHOR = "Ward Vandewege <ward\@jhvc.com>";
+my $COPYRIGHT = "2009";
+my $LICENSE = "GPL v3 - http://www.fsf.org/licenses/gpl.txt";
+my $URL = "http://coreboot.org";
+
+my $DEBUG = 0;
+
+our %info;
+my %data;
+my %printed;
+
+$|=1;
+
+&main();
+
+sub version_information {
+  my ($NAME,$VERSION,$DATE,$COPYRIGHT,$AUTHOR,$LICENSE,$URL) = (shift,shift,shift,shift,shift,shift,shift);
+  print "\nThis is $NAME version $VERSION ($DATE)\n";
+  print "Copyright (c) $COPYRIGHT by $AUTHOR\n";
+  print "License: $LICENSE\n";
+  print "More information at $URL\n\n";
+  exit;
+}
+
+sub usage_information {
+  my $retval = "\n$NAME v$VERSION ($DATE)\n";
+  $retval .= "\nYou have not supplied all required parameters. $NAME takes these arguments:\n";
+  $retval .= " $NAME -f <filename1> -f <filename2>\n\n";
+  $retval .= "  -f <filename1>    is the name of a file with k8 memory configuration values\n";
+  $retval .= "  -f <filename2>    is the name of a second file with k8 memory configuration values, to compare with filename1\n";
+  $retval .= "  -v (optional)  provides version information\n";
+  $retval .= "\nGenerate input files for this program with, for example, `lspci -s 00:18.2 -vvxxx`\n\n";
+  print $retval;
+  exit;
+}
+
+sub parse_file {
+    my $register = '';
+    my $device = '';
+    my $devreg = '';
+    my $filename = shift;
+    my %data = @_;
+    open(TMP, $filename) || die "Could not open $filename: $!\n";
+    while (<TMP>) {
+        chomp;
+        $device = $1 if (/^([a-f0-9]+:[a-f0-9]+\.[a-f0-9]+) /i);
+        next if (!(/^([a-f0-9]{2}): ([[a-f0-9 ]+)$/i));
+        # Line format
+        # 00: 22 10 02 11 00 00 00 00 00 00 00 06 00 00 80 00
+#print STDERR hex($1) . " ($1): $2\n"; 
+        my $regoffset = hex($1);
+        my @values = split(/ /,$2);
+        for (my $i=0;$i<=$#values;$i++) {
+            $register = sprintf("%02x",$regoffset+$i);
+            my $packed = pack("H*",$values[$i]);    # Pack our number so we can easily represent it in binary
+            $data{$device} = {} if (!defined($data{$device}));
+            $data{$device}{$register} = {} if (!defined($data{$device}{$register}));
+            $data{$device}{$register}{$filename} = $packed;
+#print STDERR "$device -> $register -> ($filename) setting to $values[$i]\n";
+        }
+    }
+    return %data;
+}
+
+sub parse_file_old {
+    my $register = '';
+    my $devreg = '';
+    my $filename = shift;
+    my %data = @_;
+    open(TMP, $filename) || die "Could not open $filename: $!\n";
+    while (<TMP>) {
+        chomp;
+        # Line format - pairs of lines:
+        # 0:18.2 98.l: 80000000
+        # 0:18.2 9C.l: 10111222
+        # First field is pci device. Second field is register offset (hex)
+        # where third field value (in hex) was read from.
+        my @tmp = split(/ /);
+        $tmp[1] =~ s/:$//;  # strip optional trailing colon on second field
+
+        my $device = $tmp[0];
+        my $packed = pack("H*",$tmp[2]);    # Pack our number so we can easily represent it in binary
+        my $binrep = unpack("B*", $packed); # Binary string representation
+
+        if ($tmp[1] eq '98.l') {
+            $register = ($tmp[2] =~ /(..)$/)[0]; # last 2 digits are (hex) of what we wrote to the register, if second field is 98.l
+            $devreg = "$device $register";
+            if ("$binrep" =~ /^1/) {  
+                # bit 31 *must* be 1 if readout is to be correct
+                print "$tmp[0] - $register<br>\n" if ($DEBUG);
+            } else {
+                print "ERROR: we read too fast: $tmp[2] does not have bit 31 set ($binrep)\n";
+                exit;
+            }
+        } else {
+            # last field is register value (hex)
+            print "$tmp[2]h ($binrep)<br>\n" if ($DEBUG);
+            $data{$devreg} = {} if (!defined($data{$devreg}));
+            $data{$devreg}{$filename} = $packed;
+        }
+    }
+    return %data;   
+}
+
+sub interpret_differences {
+    my $dev = shift;
+    my $reg = shift;
+    $reg = sprintf("%02s",$reg);
+    my $tag1 = shift;
+    my $val1 = shift;
+    my $tag2 = shift;
+    my $val2 = shift;
+    my $retval = '';
+    my $retval2 = '';
+
+    # XOR values together - the positions with 1 after the XOR are the ones with the differences
+    my $xor = $val1 ^ $val2;
+
+    my @val1 = split(//,unpack("B*",$val1));
+    my @val2 = split(//,unpack("B*",$val2));
+    my @xor = split(//,unpack("B*",$xor));
+
+    my %changed;
+
+    my $decregbase = hex($reg) - (hex($reg) % 4);
+
+    if (!exists($printed{$decregbase})) {
+        print "$dev $reg\n";
+        print STDERR "$dev $reg\n";
+        my $tmp = sprintf("%44s: %02x", $tag1, $decregbase) . ": ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+3)}{$tag1}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+2)}{$tag1}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+1)}{$tag1}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase)}{$tag1}) . "\n";
+        $tmp .= sprintf("%44s: %02x", $tag2, $decregbase) . ": ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+3)}{$tag2}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+2)}{$tag2}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase+1)}{$tag2}) . " ";
+        $tmp .= unpack("H*",$data{$dev}{sprintf("%02x", $decregbase)}{$tag2}) . "\n";
+        print "<pre>$tmp</pre>\n";
+        $tmp = sprintf("%44s: %02x", $tag1, $decregbase) . ": ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+3)}{$tag1}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+2)}{$tag1}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+1)}{$tag1}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase)}{$tag1}) . "\n";
+        $tmp .= sprintf("%44s: %02x", $tag2, $decregbase) . ": ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+3)}{$tag2}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+2)}{$tag2}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase+1)}{$tag2}) . " ";
+        $tmp .= unpack("B*",$data{$dev}{sprintf("%02x", $decregbase)}{$tag2}) . "\n";
+        print "<pre>$tmp</pre>\n";
+        $printed{$decregbase} = 1;
+    }
+
+    if (!exists($info{$reg})) {
+        print STDERR "<pre>MISSING DATA for register $reg ($tag1) --- ";
+        print STDERR "$reg: " . unpack("H*",$data{$dev}{$reg}{$tag1}) . "</pre>\n";
+        return '';
+    }
+
+    for (my $i=0; $i<=$#xor;$i++) {
+      my $invi = 31 - $i;
+      if ($xor[$i] eq '1') {
+#print STDERR "REG: $reg INVI: $invi\n";
+#print STDERR $info{$reg}{'fields'}{$invi} . "\n";
+#print STDERR $info{$reg}{'fields'}{$invi}{'range'} . "\n";
+        my $r = $info{$reg}{'fields'}{$invi}{'range'};
+#        if (!exists($changed{$r})) {
+#            $changed{$r}{'v1'} = '';
+#            $changed{$r}{'v2'} = '';
+#        }
+#        $changed{$r}{'v1'} .= $val1[$i];
+#        $changed{$r}{'v2'} .= $val2[$i];
+        $changed{$r}{'v1'} = 1;
+        $changed{$r}{'v2'} = 1;
+      }
+    }
+
+    foreach my $r (keys %changed) {
+        my $width = $info{$reg}{'ranges'}{$r}{'width'};
+        #$changed{$r}{'v1'} = sprintf("%0" . $width . "sb",$changed{$r}{'v1'});
+        #$changed{$r}{'v2'} = sprintf("%0" . $width . "sb",$changed{$r}{'v2'});
+        #my $v1 = $changed{$r}{'v1'};
+        #my $v2 = $changed{$r}{'v2'};
+        my $v1 = substr(unpack("B*",$val1),31-$info{$reg}{'ranges'}{$r}{'end'},$info{$reg}{'ranges'}{$r}{'width'}) . 'b';
+        my $v2 = substr(unpack("B*",$val2),31-$info{$reg}{'ranges'}{$r}{'end'},$info{$reg}{'ranges'}{$r}{'width'}) . 'b';
+
+        my $desc = $info{$reg}{'ranges'}{$r}{'description'};
+        $desc =~ s/\n+/<br>/g;
+
+        $retval2 .= $info{$reg}{'ranges'}{$r}{'function'} . " (" . $info{$reg}{'ranges'}{$r}{'mnemonic'} . ") - Bits ($r)" . "<br>";
+        $retval2 .= "  <i>$desc</i><p>" if ($desc ne '');
+
+        $v1 = $v1 . " (" . $info{$reg}{'ranges'}{$r}{'values'}{$v1} . ")" if (exists($info{$reg}{'ranges'}{$r}{'values'}{$v1}));
+        $v2 = $v2 . " (" . $info{$reg}{'ranges'}{$r}{'values'}{$v2} . ")" if (exists($info{$reg}{'ranges'}{$r}{'values'}{$v2}));
+        $retval2 .= sprintf("<b><a href=\"$tag1\">%44s</a>: %s</b>\n",$tag1, $v1);
+        $retval2 .= sprintf("<b><a href=\"$tag2\">%44s</a>: %s</b>\n",$tag2, $v2);
+        $retval2 .= "<p>";
+    }
+
+
+# this prints out the bitwise differences. TODO: clean up
+
+#    for (my $i=0; $i<=$#xor;$i++) {
+#        my $invi = 31 - $i;
+#        if ($xor[$i] eq '1') {
+#            my $m = $info{$reg}{'fields'}{$invi}{'mnemonic'};
+#            my $f = $info{$reg}{'fields'}{$invi}{'function'};
+#            my $range = $info{$reg}{'fields'}{$invi}{'range'};
+#            if ($m && $f) {
+#                $retval2 .= "Bit $invi ($info{$reg}{'fields'}{$invi}{'mnemonic'} - $info{$reg}{'fields'}{$invi}{'function'}):\n";
+#                $retval2 .= sprintf("%32s: %d\n",$tag1, $val1[$i]);
+#                $retval2 .= sprintf("%32s: %d\n",$tag2, $val2[$i]);
+#            } else {
+#                $retval2 .= "Bit $invi:\n";
+#                $retval2 .= sprintf("%32s: %d\n",$tag1, $val1[$i]);
+#                $retval2 .= sprintf("%32s: %d\n",$tag2, $val2[$i]);
+#            }
+#        }
+#    }
+
+    $retval .= "\n";
+    if ($retval2 ne '') {
+        $retval .= "\n\n$retval2\n";
+        my $n = $info{$reg}{'name'};
+        my $d = $info{$reg}{'description'};
+        $n ||= '';
+        $d ||= '';
+        my $old = $retval;
+        $retval = '';
+        $retval .= sprintf("%40s -> %s<br>\n","XOR",unpack("B*",$xor)) if ($DEBUG);
+        $retval .= "\n$n\n" if ($n ne '');
+        $retval .= "  $d" if ($d ne '');
+        $retval .= $old;
+        $retval .= "\n";
+    }
+
+    return "<pre>$retval</pre>";
+}
+
+sub load_datafile {
+  my $file = 'bkdg.data';
+  my $return = '';
+
+  if (-f $file) {
+      unless ($return = do $file) {
+        warn "couldn't parse $file: $@" if $@;
+        warn "couldn't do $file: $!"    unless defined $return;
+        warn "couldn't run $file"       unless $return;
+      }
+  } else {
+    print "Warning: data file '$file' not found - $0 will only report on differing bits without explanation.\n";
+  }
+
+}
+
+sub main {
+  my @filenames;
+  my $version = 0;
+
+  GetOptions ("filename=s" => \@filenames,  "version" => \$version);
+
+  &version_information($NAME,$VERSION,$DATE,$COPYRIGHT,$AUTHOR,$LICENSE,$URL) if ($version);
+
+  &usage_information() if ($#filenames < 1);
+
+  &load_datafile();
+
+  foreach my $file (@filenames) {
+    print STDERR "processing $file\n";
+    %data = &parse_file($file,%data);
+  }
+
+  print "<html>\n<body>\n";
+
+  foreach  my $dev (sort keys %data) {
+
+    foreach  my $reg (sort keys %{$data{$dev}}) {
+        my $first = pack("H*",'00000000');
+        my $firstfile = '';
+        foreach my $file (reverse sort keys %{$data{$dev}{$reg}}) {
+            if (unpack("H*",$first) eq '00000000') {
+                $first = $data{$dev}{$reg}{$file};
+                $firstfile = $file;
+            }
+            if (unpack("H*",$first) ne unpack("H*",$data{$dev}{$reg}{$file})) {
+                #my $reg = ($key =~ /\s+([a-z0-9]+)$/i)[0];
+                if ($DEBUG) {
+                    print "<pre>";
+                    printf("%44s -> %s (%s)\n",$firstfile,unpack("B*",$first),unpack("H*",$first));
+                    printf("%44s -> %s (%s)\n",$file,unpack("B*",$data{$dev}{$reg}{$file}),unpack("H*",$data{$dev}{$reg}{$file}));
+                    print "</pre>";
+                }
+
+                print &interpret_differences($dev,$reg,$firstfile,$first,$file,$data{$dev}{$reg}{$file});
+            }
+        }
+    }
+  }
+  print "</body>\n</html>\n";
+
+}
+


Property changes on: trunk/coreboot-v2/util/amdtools/k8-compare-pci-space.pl
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/coreboot-v2/util/amdtools/k8-interpret-extended-memory-settings.pl
===================================================================
--- trunk/coreboot-v2/util/amdtools/k8-interpret-extended-memory-settings.pl	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/k8-interpret-extended-memory-settings.pl	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,248 @@
+#!/usr/bin/perl -w
+use Getopt::Long;
+
+use strict;
+
+my $NAME = $0;
+my $VERSION = '0.01';
+my $DATE = '2009-09-04';
+my $AUTHOR = "Ward Vandewege <ward\@jhvc.com>";
+my $COPYRIGHT = "2009";
+my $LICENSE = "GPL v3 - http://www.fsf.org/licenses/gpl.txt";
+my $URL = "http://coreboot.org";
+
+my $DEBUG = 0;
+
+our %info;
+
+$|=1;
+
+&main();
+
+sub version_information {
+  my ($NAME,$VERSION,$DATE,$COPYRIGHT,$AUTHOR,$LICENSE,$URL) = (shift,shift,shift,shift,shift,shift,shift);
+  print "\nThis is $NAME version $VERSION ($DATE)\n";
+  print "Copyright (c) $COPYRIGHT by $AUTHOR\n";
+  print "License: $LICENSE\n";
+  print "More information at $URL\n\n";
+  exit;
+}
+
+sub usage_information {
+  my $retval = "\n$NAME v$VERSION ($DATE)\n";
+  $retval .= "\nYou have not supplied all required parameters. $NAME takes these arguments:\n";
+  $retval .= " $NAME -f <filename1> -f <filename2>\n\n";
+  $retval .= "  -f <filename1>    is the name of a file with k8 memory configuration values\n";
+  $retval .= "  -f <filename2>    is the name of a second file with k8 memory configuration values, to compare with filename1\n";
+  $retval .= "  -v (optional)  provides version information\n";
+  $retval .= "\nSee the k8-read-mem-settings.sh script for an example of how to generate the input files to this script.\n\n";
+  print $retval;
+  exit;
+}
+
+sub parse_file {
+    my $register = '';
+    my $devreg = '';
+    my $filename = shift;
+    my %data = @_;
+    open(TMP, $filename) || die "Could not open $filename: $!\n";
+    while (<TMP>) {
+        chomp;
+        # Line format - pairs of lines:
+        # 0:18.2 98.l: 80000000
+        # 0:18.2 9C.l: 10111222
+        # First field is pci device. Second field is register offset (hex)
+        # where third field value (in hex) was read from.
+        my @tmp = split(/ /);
+        $tmp[1] =~ s/:$//;  # strip optional trailing colon on second field
+
+        my $device = $tmp[0];
+        my $packed = pack("H*",$tmp[2]);    # Pack our number so we can easily represent it in binary
+        my $binrep = unpack("B*", $packed); # Binary string representation
+
+        if ($tmp[1] eq '98.l') {
+            $register = ($tmp[2] =~ /(..)$/)[0]; # last 2 digits are (hex) of what we wrote to the register, if second field is 98.l
+            $devreg = "$device $register";
+            if ("$binrep" =~ /^1/) {  
+                # bit 31 *must* be 1 if readout is to be correct
+                print "$tmp[0] - $register<br>\n" if ($DEBUG);
+            } else {
+                print "ERROR: we read too fast: $tmp[2] does not have bit 31 set ($binrep)\n";
+                exit;
+            }
+        } else {
+            # last field is register value (hex)
+            print "$tmp[2]h ($binrep)<br>\n" if ($DEBUG);
+            $data{$devreg} = {} if (!defined($data{$devreg}));
+            $data{$devreg}{$filename} = $packed;
+        }
+    }
+    return %data;   
+}
+
+sub interpret_differences {
+    my $reg = shift;
+    $reg = sprintf("%02s",$reg);
+    my $tag1 = shift;
+    my $val1 = shift;
+    my $tag2 = shift;
+    my $val2 = shift;
+    my $retval = '';
+    my $retval2 = '';
+
+    # XOR values together - the positions with 1 after the XOR are the ones with the differences
+    my $xor = $val1 ^ $val2;
+
+    my @val1 = split(//,unpack("B*",$val1));
+    my @val2 = split(//,unpack("B*",$val2));
+    my @xor = split(//,unpack("B*",$xor));
+
+    my %changed;
+
+    if (!exists($info{$reg})) {
+        print STDERR "MISSING DATA for register $reg\n";
+        return '';
+    }
+
+    for (my $i=0; $i<=$#xor;$i++) {
+      my $invi = 31 - $i;
+      if ($xor[$i] eq '1') {
+#print STDERR "REG: $reg INVI: $invi\n";
+#print STDERR $info{$reg}{'fields'}{$invi} . "\n";
+#print STDERR $info{$reg}{'fields'}{$invi}{'range'} . "\n";
+        my $r = $info{$reg}{'fields'}{$invi}{'range'};
+#        if (!exists($changed{$r})) {
+#            $changed{$r}{'v1'} = '';
+#            $changed{$r}{'v2'} = '';
+#        }
+#        $changed{$r}{'v1'} .= $val1[$i];
+#        $changed{$r}{'v2'} .= $val2[$i];
+        $changed{$r}{'v1'} = 1;
+        $changed{$r}{'v2'} = 1;
+      }
+    }
+
+    foreach my $r (keys %changed) {
+        my $width = $info{$reg}{'ranges'}{$r}{'width'};
+        #$changed{$r}{'v1'} = sprintf("%0" . $width . "sb",$changed{$r}{'v1'});
+        #$changed{$r}{'v2'} = sprintf("%0" . $width . "sb",$changed{$r}{'v2'});
+        #my $v1 = $changed{$r}{'v1'};
+        #my $v2 = $changed{$r}{'v2'};
+        my $v1 = substr(unpack("B*",$val1),31-$info{$reg}{'ranges'}{$r}{'end'},$info{$reg}{'ranges'}{$r}{'width'}) . 'b';
+        my $v2 = substr(unpack("B*",$val2),31-$info{$reg}{'ranges'}{$r}{'end'},$info{$reg}{'ranges'}{$r}{'width'}) . 'b';
+
+        my $desc = $info{$reg}{'ranges'}{$r}{'description'};
+        $desc =~ s/\n+/<br>/g;
+
+        $retval2 .= $info{$reg}{'ranges'}{$r}{'function'} . " (" . $info{$reg}{'ranges'}{$r}{'mnemonic'} . ") - Bits ($r)" . "<br>";
+        $retval2 .= "  <i>$desc</i><p>" if ($desc ne '');
+
+        $v1 = $v1 . " (" . $info{$reg}{'ranges'}{$r}{'values'}{$v1} . ")" if (exists($info{$reg}{'ranges'}{$r}{'values'}{$v1}));
+        $v2 = $v2 . " (" . $info{$reg}{'ranges'}{$r}{'values'}{$v2} . ")" if (exists($info{$reg}{'ranges'}{$r}{'values'}{$v2}));
+        $retval2 .= sprintf("<b><a href=\"$tag1\">%44s</a>: %s</b>\n",$tag1, $v1);
+        $retval2 .= sprintf("<b><a href=\"$tag2\">%44s</a>: %s</b>\n",$tag2, $v2);
+        $retval2 .= "<p>";
+    }
+
+
+# this prints out the bitwise differences. TODO: clean up
+
+#    for (my $i=0; $i<=$#xor;$i++) {
+#        my $invi = 31 - $i;
+#        if ($xor[$i] eq '1') {
+#            my $m = $info{$reg}{'fields'}{$invi}{'mnemonic'};
+#            my $f = $info{$reg}{'fields'}{$invi}{'function'};
+#            my $range = $info{$reg}{'fields'}{$invi}{'range'};
+#            if ($m && $f) {
+#                $retval2 .= "Bit $invi ($info{$reg}{'fields'}{$invi}{'mnemonic'} - $info{$reg}{'fields'}{$invi}{'function'}):\n";
+#                $retval2 .= sprintf("%32s: %d\n",$tag1, $val1[$i]);
+#                $retval2 .= sprintf("%32s: %d\n",$tag2, $val2[$i]);
+#            } else {
+#                $retval2 .= "Bit $invi:\n";
+#                $retval2 .= sprintf("%32s: %d\n",$tag1, $val1[$i]);
+#                $retval2 .= sprintf("%32s: %d\n",$tag2, $val2[$i]);
+#            }
+#        }
+#    }
+
+    $retval .= "\n";
+    if ($retval2 ne '') {
+        $retval .= "\n\n$retval2\n";
+        my $n = $info{$reg}{'name'};
+        my $d = $info{$reg}{'description'};
+        $n ||= '';
+        $d ||= '';
+        my $old = $retval;
+        $retval = '';
+        $retval .= sprintf("%40s -> %s<br>\n","XOR",unpack("B*",$xor)) if ($DEBUG);
+        $retval .= "\n$n\n" if ($n ne '');
+        $retval .= "  $d" if ($d ne '');
+        $retval .= $old;
+        $retval .= "\n";
+    }
+
+    return "<pre>$retval</pre>";
+}
+
+sub load_datafile {
+  my $file = 'bkdg.data';
+  my $return = '';
+
+  if (-f $file) {
+      unless ($return = do $file) {
+        warn "couldn't parse $file: $@" if $@;
+        warn "couldn't do $file: $!"    unless defined $return;
+        warn "couldn't run $file"       unless $return;
+      }
+  } else {
+    print "Warning: data file '$file' not found - $0 will only report on differing bits without explanation.\n";
+  }
+
+}
+
+sub main {
+  my @filenames;
+  my $version = 0;
+  my %data;
+
+  GetOptions ("filename=s" => \@filenames,  "version" => \$version);
+
+  &version_information($NAME,$VERSION,$DATE,$COPYRIGHT,$AUTHOR,$LICENSE,$URL) if ($version);
+
+  &usage_information() if ($#filenames < 1);
+
+  &load_datafile();
+
+  foreach my $file (@filenames) {
+    print STDERR "processing $file\n";
+    %data = &parse_file($file,%data);
+  }
+
+  print "<html>\n<body>\n";
+
+    foreach  my $key (sort keys %data) {
+        my $first = pack("H*",'00000000');
+        my $firstfile = '';
+        foreach my $k2 (reverse sort keys %{$data{$key}}) {
+            if (unpack("H*",$first) eq '00000000') {
+                $first = $data{$key}{$k2};
+                $firstfile = $k2;
+            }
+            if (unpack("H*",$first) ne unpack("H*",$data{$key}{$k2})) {
+                my $reg = ($key =~ /\s+([a-z0-9]+)$/i)[0];
+                print "$key\n";
+                if ($DEBUG) {
+                    print "<pre>";
+                    printf("%44s -> %s (%s)\n",$firstfile,unpack("B*",$first),unpack("H*",$first));
+                    printf("%44s -> %s (%s)\n",$k2,unpack("B*",$data{$key}{$k2}),unpack("H*",$data{$key}{$k2}));
+                    print "</pre>";
+                }
+
+                print &interpret_differences($reg,$firstfile,$first,$k2,$data{$key}{$k2});
+            }
+        }
+    }
+  print "</body>\n</html>\n";
+
+}
+


Property changes on: trunk/coreboot-v2/util/amdtools/k8-interpret-extended-memory-settings.pl
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/coreboot-v2/util/amdtools/k8-read-mem-settings.sh
===================================================================
--- trunk/coreboot-v2/util/amdtools/k8-read-mem-settings.sh	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/k8-read-mem-settings.sh	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# This is an example that generates data files that are understood by the
+# k8-interpret-extended-memory-settings.pl script. Adjust the pci ids for your
+# board (0:18.2 and 0:19.2 are correct for supermicro h8dme)
+
+# Ward Vandewege, 2009-09-04
+
+
+for OFFSET in 00, 01, 02, 03, 04, 05, 06, 07, 20, 21, 22, 23, 24, 25, 26, 27, 10, 13, 16, 19, 30, 33, 36, 39; do
+
+  setpci -s 0:18.2 98.l=$OFFSET
+  echo 0:18.2 98.l: `setpci -s 0:18.2 98.l`
+  echo 0:18.2 9C.l: `setpci -s 0:18.2 9C.l`
+
+done
+
+for OFFSET in 00, 01, 02, 03, 04, 05, 06, 07, 20, 21, 22, 23, 24, 25, 26, 27, 10, 13, 16, 19, 30, 33, 36, 39; do
+
+  setpci -s 0:19.2 98.l=$OFFSET
+  echo 0:19.2 98.l: `setpci -s 0:19.2 98.l`
+  echo 0:19.2 9C.l: `setpci -s 0:19.2 9C.l`
+
+done
+


Property changes on: trunk/coreboot-v2/util/amdtools/k8-read-mem-settings.sh
___________________________________________________________________
Added: svn:executable
   + *

Added: trunk/coreboot-v2/util/amdtools/parse-bkdg.pl
===================================================================
--- trunk/coreboot-v2/util/amdtools/parse-bkdg.pl	                        (rev 0)
+++ trunk/coreboot-v2/util/amdtools/parse-bkdg.pl	2009-10-28 19:41:52 UTC (rev 4886)
@@ -0,0 +1,286 @@
+#!/usr/bin/perl -w
+
+my $NAME = $0;
+my $VERSION = '0.01';
+my $DATE = '2009-09-04';
+my $AUTHOR = "Ward Vandewege <ward\@jhvc.com>";
+my $COPYRIGHT = "2009";
+my $LICENSE = "GPL v3 - http://www.fsf.org/licenses/gpl.txt";
+my $URL = "http://coreboot.org";
+
+my $DEBUG = 0;
+
+use strict;
+
+# Run the bkdg for k8 through pdftotext first (from the poppler package)
+
+my @registers = ();
+my $raw_register = '';
+
+my $name = '';
+my $description = '';
+my $step = 0;
+my $oldstep = 0;
+
+my $previous_res = 0;
+my $previous_start = 0;
+my $previous_stop = 0;
+my $strip_empties = 0;
+
+my $previous_bits = '';
+
+our %info;
+
+my %typos;
+
+$typos{'CkeDreStrength'} = 'CkeDrvStrength';
+
+while (<>) {
+    my $line = $_;
+    chomp($line);
+
+    foreach my $k (keys %typos) {
+        $line =~ s/$k/$typos{$k}/;
+    }
+
+    # Make sure we do not include headers in our output
+    if (($line =~ /^Chapter 4/) || ($line =~ /Chapter 4$/)) {
+        $oldstep = $step;
+        $step = 99;
+        next;
+    }
+    if ($step == 99) {  # header
+        if ($line =~ /Processors$/) {
+            $step = $oldstep;
+            $strip_empties = 1;
+        }
+        next;
+    }
+
+    if ($strip_empties) {
+        # Headers are followed by two blank lines. Strip them.
+        if ($line =~ /^\s*$/) {
+            next;
+        } else {
+            $strip_empties = 0;
+        }
+    }
+
+
+    if (($step % 6 == 0) && ($line =~ /^\d+\.\d+\.\d+\s+(.*)$/)) {
+        $step = 1;
+        next;
+    }
+    if ($step == 1) {
+        $description = "$line\n";
+        $step = 2;
+        next;
+    }
+    #print STDERR "STEP: $step\n";
+    #print STDERR "$line\n";
+
+    if ((($step == 0) || ($step == 6) || ($step == 2)) && ($line =~ /^(.*)\s+Function\s+\d+:\s+Offset\s+..h$/)) {
+        $name = $1;
+        $name =~ s/ +$//;
+        $step = 3;
+        $description =~ s/\n+$//ms;
+
+        if ($previous_bits ne '') {
+          &finish_record($previous_bits);
+          $previous_bits = ''; # reset previous_bits (used in step 6)
+        }
+
+
+        next;
+    } elsif ($step == 2) {
+        $description .= "$line\n";
+        next;
+    }
+
+    if (($step == 3) && ($line =~ /^\s+Index (.+h)$/)) {
+        $raw_register= $1;
+        @registers = split(/,/,$raw_register);
+        for (my $i=0;$i<=$#registers;$i++) {
+            $registers[$i] =~ s/ //g;
+            $registers[$i] =~ s/h$//;
+        }
+        # OK, we have our register(s), so now we can print out the name and description lines.
+        print "\$info{'$registers[0]'}{'name'} = \"$name\";\n";
+        print "\$info{'$registers[0]'}{'description'} = \"$description\";\n";
+        $step = 4;
+        next;
+    }
+
+    if (($step == 4) && ($line =~ /^Bits\s+Mnemonic\s+Function\s+R\/W\s+Reset$/)) {
+        $step = 5;
+        next;
+    }
+
+    if (($step == 5) && (!($line =~ /^Field Descriptions$/))) {
+        $line =~ s/^ +//; # Strip leading spaces
+        my @f = split(/  +/,$line);
+
+        # skip blank lines
+        next if (!exists($f[0]));
+
+        # skip headers (they could be repeated if the table crosses a page boundary
+        next if ($f[0] eq 'Bits');
+
+        # Clean up funky field separator
+        if ($f[0] =~ /\d+.+\d+/) {
+            $f[0] =~ s/[^\d]+/-/g;
+        }
+
+        my ($start, $stop, $width) = (0,0,0);
+        if ($f[0] =~ /-/) {
+            $f[0] =~ s/^(\d+)[^\d]+(\d+)$/$1-$2/;
+            ($stop,$start) = ($1,$2);
+            $width = $stop-$start+1;
+        } else {
+          if ($f[0] =~ /^\d+$/) {
+            $start = $stop = $f[0];
+            $width = 1;
+          } else {
+            # continuation from previous line
+            $start = $stop = $width = 0;
+          }
+        }
+
+        # Some lines have only bit entries
+        if (($#f < 1) && ($f[0] =~ /^\d+(|\-\d+)/)) {
+          $f[4] = '';
+          $f[3] = '';
+          $f[2] = '';
+          $f[1] = '';
+        } elsif ($#f < 1) {
+          # Some lines are a continuation of the function field a line above
+          $f[4] = '';
+          $f[3] = '';
+          $f[2] = $f[0];
+          $f[1] = '';
+          $f[0] = '';
+          my $tmp = "\$info{'$registers[0]'}{'ranges'}{" . $previous_res . "}{'function'} .= \"" . $f[2] . "\";\n";
+          print &multiply($tmp,$previous_res,$previous_start,$previous_stop);
+          next;
+        }
+
+        # Some lines have only bit and reset entries
+        if ($#f < 2) {
+          $f[4] = $f[1];
+          $f[3] = '';
+          $f[2] = '';
+          $f[1] = '';
+        }
+
+        # Some lines have no mnemonic and no function
+        if ($#f < 3) {
+          $f[4] = $f[2];
+          $f[3] = $f[1];
+          $f[2] = '';
+          $f[1] = '';
+        }
+
+        # functions with 'reserved' mnemonic have no function
+        if ($f[1] =~ /^reserved$/i) {
+            $f[4] = $f[3];
+            $f[3] = $f[2];
+            $f[2] = '';
+        }
+
+        $previous_res = $f[0];
+        $previous_start = $start;
+        $previous_stop = $stop;
+
+        # the 'range' field is not useful in this instance, but used in the 'fields' version of this block to easily go 
+        # from a bit position to the corresponding range.
+        my $str = "
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'function'} = \"" . $f[2] . "\";
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'mnemonic'} = \"" . $f[1] . "\";
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'description'} = \"" . "\";
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'begin'} = $start;
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'end'} = $stop;
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'width'} = $width;
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'rw'} = \"" . $f[3] . "\";
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'reset'} = \"" . $f[4] . "\";
+\$info{'$registers[0]'}{'ranges'}{'" . $f[0] . "'}{'range'} = \"" . $f[0] . "\";
+";
+        my $output;
+
+        $output = &multiply($str,$f[0],$start,$stop);
+
+        # Load the data structure here, too
+        eval($output);
+
+        print $output . "\n\n";
+    } elsif (($step == 5) && ($line =~ /^Field Descriptions$/)) {
+        $step = 6;
+        next;
+    }
+
+    if ($step == 6) {
+        if ($line =~ /^(.*?)\((.*?)\).+Bit(s|) +(.*?)\. (.*)$/) {
+          my $bits = $4;
+          my $desc = $5;
+          $bits =~ s/[^\d]+/-/;
+
+          if ($previous_bits ne '') {
+            # We're done with a field description block
+            print "\$info{'$registers[0]'}{'ranges'}{'$previous_bits'}{'description'} = \"" . $info{$registers[0]}{'ranges'}{$previous_bits}{'description'} . "\";\n";
+            foreach my $k (keys %{$info{$registers[0]}{'ranges'}{$previous_bits}{'values'}}) {
+              print "\$info{'$registers[0]'}{'ranges'}{'$previous_bits'}{'values'}{'$k'} = \"" . $info{$registers[0]}{'ranges'}{$previous_bits}{'values'}{$k} . "\";\n";
+            }
+          }
+
+          if (exists($info{$registers[0]}{'ranges'}{$bits})) {
+            print STDERR "match ($bits) on $line\n";
+            $info{$registers[0]}{'ranges'}{$bits}{'description'} = $desc . "\n";
+            $previous_bits = $bits;
+          }
+        } elsif ($previous_bits ne '') {
+          $info{$registers[0]}{'ranges'}{$previous_bits}{'description'} .= $line . "\n";
+          if ($line =~ /([0-9a-f]+b|[0-9a-f]+h) = (.*)$/i) {
+            $info{$registers[0]}{'ranges'}{$previous_bits}{'values'}{$1} = $2;
+          }
+        }
+    }
+
+}
+&finish_record($previous_bits);
+
+
+print "1;\n";
+
+sub multiply {
+  my $str = shift;
+  my $range = shift;
+  my $start = shift;
+  my $stop = shift;
+  my $output = '';
+  for (my $i=$start;$i<=$stop;$i++) {
+    my $tmp = $str;
+    $tmp =~ s/\{'$range'\}/{'$i'}/g;
+    $tmp =~ s/\{'ranges'\}/{'fields'}/g;
+    $tmp .= 
+    $output .= $tmp;
+  }
+
+  #$output .= $str if (($stop - $start + 1) > 1);
+  $output .= $str;
+
+  return $output;
+}
+
+sub finish_record {
+  my $previous_bits = shift;
+   # We're done with a field description block
+          print "\$info{'$registers[0]'}{'ranges'}{'$previous_bits'}{'description'} = \"" . $info{$registers[0]}{'ranges'}{$previous_bits}{'description'} . "\";\n";
+          foreach my $k (keys %{$info{$registers[0]}{'ranges'}{$previous_bits}{'values'}}) {
+            print "\$info{'$registers[0]'}{'ranges'}{'$previous_bits'}{'values'}{'$k'} = \"" . $info{$registers[0]}{'ranges'}{$previous_bits}{'values'}{$k} . "\";\n";
+          }
+
+          # End of table. If this data applies to more than one register, print duplication lines.
+          for (my $i=1;$i<=$#registers;$i++) {
+            print "\$info{'$registers[$i]'} = \$info{'$registers[0]'};\n";
+          }
+
+}


Property changes on: trunk/coreboot-v2/util/amdtools/parse-bkdg.pl
___________________________________________________________________
Added: svn:executable
   + *





More information about the coreboot mailing list