| | 842 | # Base, high-bit, 3-bit fraction code |
| | 843 | sub ddr2_sdram_rtime($$$) |
| | 844 | { |
| | 845 | my ($rtime, $msb, $ext) = @_; |
| | 846 | my @table = (0, .25, .33, .50, .66, .75); |
| | 847 | |
| | 848 | return $rtime + $msb * 256 + $table[$ext]; |
| | 849 | } |
| | 850 | |
| | 851 | sub ddr2_module_types($) |
| | 852 | { |
| | 853 | my $byte = shift; |
| | 854 | my @types = qw(RDIMM UDIMM SO-DIMM Micro-DIMM Mini-RDIMM Mini-UDIMM); |
| | 855 | my @widths = (133.35, 133.25, 67.6, 45.5, 82.0, 82.0); |
| | 856 | my @suptypes; |
| | 857 | local $_; |
| | 858 | |
| | 859 | foreach (0..5) { |
| | 860 | push @suptypes, "$types[$_] ($widths[$_] mm)" |
| | 861 | if ($byte & (1 << $_)); |
| | 862 | } |
| | 863 | |
| | 864 | return @suptypes; |
| | 865 | } |
| | 866 | |
| | 867 | sub ddr2_refresh_rate($) |
| | 868 | { |
| | 869 | my $byte = shift; |
| | 870 | my @refresh = qw(Normal Reduced Reduced Extended Extended Extended); |
| | 871 | my @refresht = (15.625, 3.9, 7.8, 31.3, 62.5, 125); |
| | 872 | |
| | 873 | return "$refresh[$byte & 0x7f] ($refresht[$byte & 0x7f] us)". |
| | 874 | ($byte & 0x80 ? " - Self Refresh" : ""); |
| | 875 | } |
| | 876 | |
| | 918 | printl "Banks x Rows x Columns x Bits", |
| | 919 | join(' x ', $bytes->[17], $bytes->[3], $bytes->[4], $bytes->[6]); |
| | 920 | printl "Ranks", ($bytes->[5] & 7) + 1; |
| | 921 | |
| | 922 | printl "SDRAM Device Width", $bytes->[13]." bits"; |
| | 923 | |
| | 924 | my @heights = ('< 25.4', '25.4', '25.4 - 30.0', '30.0', '30.5', '> 30.5'); |
| | 925 | printl "Module Height", $heights[$bytes->[5] >> 5]." mm"; |
| | 926 | |
| | 927 | my @suptypes = ddr2_module_types($bytes->[20]); |
| | 928 | printl "Module Type".(@suptypes > 1 ? 's' : ''), join(', ', @suptypes); |
| | 929 | |
| | 930 | printl "DRAM Package", $bytes->[5] & 0x10 ? "Stack" : "Planar"; |
| | 931 | |
| | 932 | my @volts = ("TTL (5V Tolerant)", "LVTTL", "HSTL 1.5V", |
| | 933 | "SSTL 3.3V", "SSTL 2.5V", "SSTL 1.8V", "TBD"); |
| | 934 | printl "Voltage Interface Level", $volts[$bytes->[8]]; |
| | 935 | |
| | 936 | printl "Refresh Rate", ddr2_refresh_rate($bytes->[12]); |
| | 937 | |
| | 938 | my @burst; |
| | 939 | push @burst, 4 if ($bytes->[16] & 4); |
| | 940 | push @burst, 8 if ($bytes->[16] & 8); |
| | 941 | $burst[0] = 'None' if !@burst; |
| | 942 | printl "Supported Burst Lengths", join(', ', @burst); |
| | 943 | |
| 915 | | printl "Minimum Cycle Time (CAS ".($highestCAS-1).")", |
| 916 | | ddr2_sdram_ctime($bytes->[23]) . " ns"; |
| 917 | | printl "Maximum Access Time (CAS ".($highestCAS-1).")", |
| 918 | | ddr2_sdram_atime($bytes->[24]) . " ns"; |
| | 981 | printl "Minimum Cycle Time at CAS ".($highestCAS-1), |
| | 982 | tns(ddr2_sdram_ctime($bytes->[23])); |
| | 983 | printl "Maximum Access Time at CAS ".($highestCAS-1), |
| | 984 | tns(ddr2_sdram_atime($bytes->[24])); |
| 922 | | printl "Minimum Cycle Time (CAS ".($highestCAS-2).")", |
| 923 | | ddr2_sdram_ctime($bytes->[25]) . " ns"; |
| 924 | | printl "Maximum Access Time (CAS ".($highestCAS-2).")", |
| 925 | | ddr2_sdram_atime($bytes->[26]) . " ns"; |
| 926 | | } |
| | 988 | printl "Minimum Cycle Time at CAS ".($highestCAS-2), |
| | 989 | tns(ddr2_sdram_ctime($bytes->[25])); |
| | 990 | printl "Maximum Access Time at CAS ".($highestCAS-2), |
| | 991 | tns(ddr2_sdram_atime($bytes->[26])); |
| | 992 | } |
| | 993 | printl "Maximum Cycle Time (tCK max)", |
| | 994 | tns(ddr2_sdram_ctime($bytes->[43])); |
| | 995 | |
| | 996 | # more timing information |
| | 997 | prints("Timing Parameters"); |
| | 998 | printl "Address/Command Setup Time Before Clock (tIS)", |
| | 999 | tns(ddr2_sdram_atime($bytes->[32])); |
| | 1000 | printl "Address/Command Hold Time After Clock (tIH)", |
| | 1001 | tns(ddr2_sdram_atime($bytes->[33])); |
| | 1002 | printl "Data Input Setup Time Before Strobe (tDS)", |
| | 1003 | tns(ddr2_sdram_atime($bytes->[34])); |
| | 1004 | printl "Data Input Hold Time After Strobe (tDH)", |
| | 1005 | tns(ddr2_sdram_atime($bytes->[35])); |
| | 1006 | printl "Minimum Row Precharge Delay (tRP)", tns($trp); |
| | 1007 | printl "Minimum Row Active to Row Active Delay (tRRD)", |
| | 1008 | tns($bytes->[28]/4); |
| | 1009 | printl "Minimum RAS# to CAS# Delay (tRCD)", tns($trcd); |
| | 1010 | printl "Minimum RAS# Pulse Width (tRAS)", tns($tras); |
| | 1011 | printl "Write Recovery Time (tWR)", tns($bytes->[36]/4); |
| | 1012 | printl "Minimum Write to Read CMD Delay (tWTR)", tns($bytes->[37]/4); |
| | 1013 | printl "Minimum Read to Pre-charge CMD Delay (tRTP)", tns($bytes->[38]/4); |
| | 1014 | printl "Minimum Active to Auto-refresh Delay (tRC)", |
| | 1015 | tns(ddr2_sdram_rtime($bytes->[41], 0, ($bytes->[40] >> 4) & 7)); |
| | 1016 | printl "Minimum Recovery Delay (tRFC)", |
| | 1017 | tns(ddr2_sdram_rtime($bytes->[42], $bytes->[40] & 1, |
| | 1018 | ($bytes->[40] >> 1) & 7)); |
| | 1019 | printl "Maximum DQS to DQ Skew (tDQSQ)", tns($bytes->[44]/100); |
| | 1020 | printl "Maximum Read Data Hold Skew (tQHS)", tns($bytes->[45]/100); |
| | 1021 | printl "PLL Relock Time", $bytes->[46] . " us" if ($bytes->[46]); |