#!/usr/bin/env ruby # # Copyright © 2014 Siarhei Siamashka # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. if not ARGV[0] or not File.directory?(ARGV[0]) then printf("Usage: #{$PROGRAM_NAME} [results_directory] > report.html\n") printf("\n") printf("Where:\n") printf(" results_directory - is the directory populated by\n") printf(" the scan-for-best-tpr3.rb script\n") printf(" report.html - is the output of this script\n") exit(1) end def read_file(dir, name) fullname = File.join(dir, name) return if not File.exists?(fullname) fh = File.open(fullname) data = fh.read fh.close return data end def subtest_dir_to_html_table(dir) mfxdly_list = [0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38] sdphase_list = [0x3, 0x2, 0x1, 0x0, 0xe, 0xd, 0xc] sdphase_label = [90, 72, 54, 36, 108, 90, 72, 54, 126, 108, 90, 72, 144, 126, 108, 90] def lookup_tpr3(dir, tpr3) filename = File.join(dir, sprintf("tpr3_0x%08X", tpr3)) return "" if not File.exists?(filename) fh = File.open(filename) data = fh.read fh.close color = "#FF0000" if data =~ /memtester success rate: (\d+)\/(\d+)/ then passed_tests = $1.to_i total_tests = $1.to_i if passed_tests == 5 then color = "green" else green_part = 127 + passed_tests * 128 / 4 blue_part = total_tests * 128 / 4 color = sprintf("#FF%02X%02X", green_part, blue_part) end end return sprintf("0x%06X", color, data, tpr3) end printf("\n") printf("
MFxDLY \\ SDPHASE") sdphase_list.each {|sdphase| printf("%d", sdphase_label[sdphase]) } mfxdly_list.each {|mfxdly| printf("
%3X", mfxdly) sdphase_list.each {|sdphase| printf("%s", lookup_tpr3(dir, (mfxdly << 16) | (sdphase * 0x1111))) } } printf("
\n") end print "

This is a DRAM tuning/overclocking stability report for various Allwinner A10/A13/A20 based devices.It can be automatically generated by the tools from https://github.com/ssvb/a10-meminfo. Here we primarily focus on finding optimal dram_tpr3 values, tuned individually for every sunxi device. Currently these values need to be hardcoded into the sources of the u-boot-sunxi bootloader. The dram_tpr3 parameter is just a hexadecimal number with the following bit fields:

The RK30XX manual can be checked for more details about the MFWDLY, MFBDLY and SDPHASE bit fields. The Rockchip 30XX family of SoCs is apparently using the same DRAM controller IP.

Results interpretation (some results are actually a mix of RED and YELLOW):

" dirlist = [] Dir.glob(File.join(ARGV[0], "*")).each {|f| next if not File.directory?(f) dirlist.push(f) } def strip_html_tags(text) return text.gsub(/\<[\/]?a.*?\>/, "") end # Group results from the same device/configuration/description tmp = {} dirlist.sort.each {|f| if File.basename(f) =~ /(.*MHz\-[0-9A-F]{8})/ then id = $1 id = (read_file(f, "_description.txt") or "") + " : " + id tmp[id] = [] if not tmp.has_key?(id) tmp[id].push(f) end } dirlist = [] tmp.to_a.sort {|x,y| strip_html_tags(x[0]) <=> strip_html_tags(y[0]) }.each {|x| dirlist.push(x[1]) } dirlist.each {|a| printf("%s (reliability for different dram_tpr3 settings)\n", (read_file(a[0], "_description.txt") or "Unknown device")) printf("\n") printf("") printf("
\n") printf("
%s", read_file(a[0], "_a10_meminfo.txt").gsub("\n", "
")) printf("
") a.each {|f| printf("
") subtest_dir_to_html_table(f) } printf("
") printf("

\n") } print "

Notes:

"