summaryrefslogtreecommitdiff
authorTong Li <tong.li@amlogic.com>2018-01-08 06:13:43 (GMT)
committer Tong Li <tong.li@amlogic.com>2018-01-08 06:17:41 (GMT)
commitbf0f51dd9ef304db5152dcf0fb3b8296e67e7759 (patch)
treea937655b3fb24ab77189aa04f6ecf7f38cf11d15
parent1069c6c39759979b704e828d8943d2c0bde8c195 (diff)
downloadtools-bf0f51dd9ef304db5152dcf0fb3b8296e67e7759.zip
tools-bf0f51dd9ef304db5152dcf0fb3b8296e67e7759.tar.gz
tools-bf0f51dd9ef304db5152dcf0fb3b8296e67e7759.tar.bz2
PD#NONE: add cpuburn.[1/1]
Change-Id: Ic37c38e0b3751c7635c899af700ac42c6040302c
Diffstat
-rw-r--r--cpuburn/Android.mk25
-rw-r--r--cpuburn/README.md4
-rw-r--r--cpuburn/cpuburn-a53.S183
-rw-r--r--cpuburn/cpuburn-a7.S91
-rw-r--r--cpuburn/cpuburn-a8.S73
-rw-r--r--cpuburn/cpuburn-a9.S97
-rw-r--r--cpuburn/cpuburn-krait.S96
-rw-r--r--cpuburn/cpufreq-ljt-stress-test217
-rw-r--r--cpuburn/gnuplot-sunxi-cpufreq112
9 files changed, 898 insertions, 0 deletions
diff --git a/cpuburn/Android.mk b/cpuburn/Android.mk
new file mode 100644
index 0000000..e47b258
--- a/dev/null
+++ b/cpuburn/Android.mk
@@ -0,0 +1,25 @@
+# Copyright 2006 The Android Open Source Project
+
+# XXX using libutils for simulator build only...
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ cpuburn-a53.S \
+
+LOCAL_STATIC_LIBRARIES:= \
+ libcutils \
+ libc
+
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+LOCAL_LDLIBS += -lpthread
+LOCAL_MODULE:= cpuburn-a53
+include $(BUILD_EXECUTABLE)
diff --git a/cpuburn/README.md b/cpuburn/README.md
new file mode 100644
index 0000000..3fd963b
--- a/dev/null
+++ b/cpuburn/README.md
@@ -0,0 +1,4 @@
+cpuburn
+=======
+
+A collection of cpuburn programs tuned for different ARM hardware
diff --git a/cpuburn/cpuburn-a53.S b/cpuburn/cpuburn-a53.S
new file mode 100644
index 0000000..2b50295
--- a/dev/null
+++ b/cpuburn/cpuburn-a53.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright © 2016 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This program tries to stress ARM Cortex-A53 processor to generate as
+ * much heat as possible.
+ * WARNING: improperly cooled or otherwise flawed hardware may potentially
+ * overheat and fail. Use at your own risk.
+ *
+ * Compilation instructions:
+ * $ aarch64-linux-gnu-gcc -o cpuburn-a53 cpuburn-a53.S
+ * or
+ * $ arm-linux-gnueabihf-gcc -o cpuburn-a53 cpuburn-a53.S
+ *
+ * See http://ssvb.github.io/2012/04/10/cpuburn-arm-cortex-a9.html
+ * for more details.
+ */
+
+#define LOOP_UNROLL_FACTOR 100
+
+#ifdef __aarch64__
+
+/****************************************************************************/
+/* 64-bit implementation */
+/****************************************************************************/
+
+ .cpu cortex-a53+fp+simd
+ .text
+ .align 2
+ .global main
+ .type main, %function
+
+main:
+ stp x29, x30, [sp, #-16]!
+
+#ifdef __linux__
+ mov w0, #84 /* _SC_NPROCESSORS_ONLN */
+ bl sysconf
+ mov w29, w0
+ cmp w29, #2
+ blt 1f
+ bl fork /* have at least 2 cores */
+ cmp w29, #4
+ blt 1f
+ bl fork /* have at least 4 cores */
+ cmp w29, #8
+ blt 1f
+ bl fork /* have at least 8 cores */
+1:
+#endif
+
+ movi v28.16b, #0xff
+ movi v29.16b, #0xff
+ movi v30.16b, #0xff
+ movi v31.16b, #0xff
+
+ adr x4, 9f
+ add x4, x4, #1
+ mov x1, #0
+ mov x2, #(64 / 4)
+
+ b 0f
+
+ .ltorg
+9:
+ .rept 64
+ .long 0xffffffff
+ .endr
+
+ .balign 64
+0:
+ .rept LOOP_UNROLL_FACTOR
+ uaba v8.4s, v28.4s, v29.4s
+ bne 1f
+1: uaba v9.4s, v30.4s, v31.4s
+ ldr w0, [x4, x1, lsl #2]
+ uaba v10.4s, v28.4s, v29.4s
+ bne 1f
+1: uaba v11.4s, v30.4s, v31.4s
+ ldr w0, [x4, x2, lsl #2]
+ .endr
+ b 0b
+
+ mov w0, #0
+ ldp x29, x30, [sp], #16
+ ret
+
+/****************************************************************************/
+
+#else
+
+/****************************************************************************/
+/* 32-bit implementation */
+/****************************************************************************/
+
+ .syntax unified
+ .text
+ .arch armv7-a
+ .fpu neon
+ .global main
+ .type main, %function
+ .align 2
+ .arm
+
+main:
+ push {r4-r12, lr}
+ vpush {q8-q15}
+
+#ifdef __linux__
+ mov r0, 84 /* _SC_NPROCESSORS_ONLN */
+ bl sysconf
+ mov r4, r0
+ cmp r4, #2
+ blt 1f
+ bl fork /* have at least 2 cores */
+ cmp r4, #4
+ blt 1f
+ bl fork /* have at least 4 cores */
+ cmp r4, #8
+ blt 1f
+ bl fork /* have at least 8 cores */
+1:
+#endif
+
+ vmov.u8 q12, #0xff
+ vmov.u8 q13, #0xff
+ vmov.u8 q14, #0xff
+ vmov.u8 q15, #0xff
+
+ adr lr, 9f
+ add lr, lr, #1
+ mov r1, #(64 / 4)
+ mov r2, #(-64 / 4)
+
+ b 0f
+
+ .ltorg
+9:
+ .rept 64
+ .long 0xffffffff
+ .endr
+
+ .balign 64
+0:
+ .rept LOOP_UNROLL_FACTOR
+ vaba.u32 q8, q12, q13
+ bne 1f
+1: vaba.u32 q9, q14, q15
+ ldrne r0, [lr, r1, lsl #2]!
+ vaba.u32 q10, q12, q13
+ bne 1f
+1: vaba.u32 q11, q14, q15
+ ldrne r0, [lr, r2, lsl #2]!
+ .endr
+ b 0b
+
+ vpop {q8-q15}
+ mov r0, #0
+ pop {r4-r12, pc}
+
+/****************************************************************************/
+
+#endif
diff --git a/cpuburn/cpuburn-a7.S b/cpuburn/cpuburn-a7.S
new file mode 100644
index 0000000..74e925a
--- a/dev/null
+++ b/cpuburn/cpuburn-a7.S
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This program tries to stress ARM Cortex-A7 processor to generate as
+ * much heat as possible.
+ * WARNING: improperly cooled or otherwise flawed hardware may potentially
+ * overheat and fail. Use at your own risk.
+ *
+ * Compilation instructions:
+ * $ arm-linux-gnueabihf-gcc -o cpuburn-a7 cpuburn-a7.S
+ *
+ * See http://ssvb.github.io/2012/04/10/cpuburn-arm-cortex-a9.html
+ * for more details.
+ */
+
+ .syntax unified
+ .text
+ .arch armv7-a
+ .fpu neon
+ .arm
+
+ .global main
+
+.func main
+.type main, %function
+main:
+ push {r4-r12, lr}
+
+#ifdef __linux__
+ mov r0, 84 /* _SC_NPROCESSORS_ONLN */
+ bl sysconf
+ mov r4, r0
+ cmp r4, #2
+ blt 1f
+ bl fork /* have at least 2 cores */
+ cmp r4, #4
+ blt 1f
+ bl fork /* have at least 4 cores */
+ cmp r4, #8
+ blt 1f
+ bl fork /* have at least 8 cores */
+1:
+#endif
+
+ adr lr, 9f
+ add lr, lr, #129
+ mov r1, #(64 / 4)
+ mov r2, #(-64 / 4)
+ mov ip, #1
+ b 0f
+
+ .balign 64
+9:
+ .rept 128
+ .long 0xffffffff
+ .endr
+
+ .balign 64
+/****************************************************************************/
+/* Main loop (2 cycles per loop iteration, reaching peak IPC=2) */
+/****************************************************************************/
+0: ldrne r0, [lr, r1, lsl #2]
+ subs ip, ip, #0
+
+ ldrne r0, [lr, r2, lsl #2]
+ bne 0b
+
+ mov r0, #0
+ pop {r4-r12, pc}
+.endfunc
diff --git a/cpuburn/cpuburn-a8.S b/cpuburn/cpuburn-a8.S
new file mode 100644
index 0000000..c6f93a6
--- a/dev/null
+++ b/cpuburn/cpuburn-a8.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This program tries to stress ARM Cortex-A8 processor to generate as
+ * much heat as possible.
+ * WARNING: improperly cooled or otherwise flawed hardware may potentially
+ * overheat and fail. Use at your own risk.
+ *
+ * Compilation instructions:
+ * $ arm-linux-gnueabihf-gcc -o cpuburn-a8 cpuburn-a8.S
+ *
+ * See http://ssvb.github.com/2012/04/10/cpuburn-arm-cortex-a9.html
+ * for more details.
+ */
+ .syntax unified
+ .text
+ .arch armv7-a
+ .fpu neon
+ .thumb
+
+ .global main
+
+/* optimal value for LOOP_UNROLL_FACTOR seems to be BTB size dependent */
+#define LOOP_UNROLL_FACTOR 130
+/* 16 seems to be a good choice */
+#define STEP 16
+
+.func main
+.thumb_func
+main:
+ mov lr, pc
+ adds lr, lr, #63
+ bic lr, lr, #63
+ mov ip, #STEP
+ .p2align 2
+0:
+ .rept LOOP_UNROLL_FACTOR
+ vld2.8 {q0}, [lr, :128], ip
+ vaba.u8 q4, q4, q3
+ bne 1f
+1: vld2.8 {q1}, [lr, :128], ip
+ vaba.u8 q5, q5, q0
+ vld2.8 {q2}, [lr, :128], ip
+ vaba.u8 q6, q6, q1
+ bne 1f
+1: vld2.8 {q3}, [lr, :128], ip
+ vaba.u8 q7, q7, q2
+ smuad r0, r1, r2
+ subs lr, lr, #(STEP * 4)
+ .endr
+ bne 0b
+.endfunc
diff --git a/cpuburn/cpuburn-a9.S b/cpuburn/cpuburn-a9.S
new file mode 100644
index 0000000..0338b00
--- a/dev/null
+++ b/cpuburn/cpuburn-a9.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This program tries to stress ARM Cortex-A9 processor to generate as
+ * much heat as possible. Needs NEON, so does not work on Tegra 2.
+ * WARNING: improperly cooled or otherwise flawed hardware may potentially
+ * overheat and fail. Use at your own risk.
+ *
+ * Compilation instructions:
+ * $ arm-linux-gnueabihf-gcc -o cpuburn-a9 cpuburn-a9.S
+ *
+ * See http://ssvb.github.com/2012/04/10/cpuburn-arm-cortex-a9.html
+ * for more details.
+ */
+ .syntax unified
+ .text
+ .arch armv7-a
+ .fpu neon
+ .arm
+
+ .global main
+ .global sysconf
+ .global fork
+
+/* optimal value for LOOP_UNROLL_FACTOR seems to be BTB size dependent */
+#define LOOP_UNROLL_FACTOR 110
+/* 64 seems to be a good choice */
+#define STEP 64
+
+.func main
+.type main, %function
+main:
+
+#ifdef __linux__
+ mov r0, 84 /* _SC_NPROCESSORS_ONLN */
+ blx sysconf
+ mov r4, r0
+ cmp r4, #2
+ blt 1f
+ blx fork /* have at least 2 cores */
+ cmp r4, #4
+ blt 1f
+ blx fork /* have at least 4 cores */
+1:
+#endif
+
+ ldr lr, =(STEP * 4 + 15)
+ subs lr, sp, lr
+ bic lr, lr, #15
+ mov ip, #STEP
+ mov r0, #0
+ mov r1, #0
+ mov r2, #0
+ mov r3, #0
+ ldr r4, =0xFFFFFFFF
+ b 0f
+ .ltorg
+0:
+ .rept LOOP_UNROLL_FACTOR
+ vld2.8 {q0}, [lr, :128], ip
+ it ne
+ smlalne r0, r1, lr, r4
+ bne 1f
+1:
+ vld2.8 {q1}, [lr, :128], ip
+ it ne
+ smlalne r2, r3, lr, r4
+ bne 1f
+1:
+ vld2.8 {q2}, [lr, :128], ip
+ vld2.8 {q3}, [lr, :128], ip
+ it ne
+ subsne lr, lr, #(STEP * 4)
+ .endr
+ bne 0b
+.endfunc
diff --git a/cpuburn/cpuburn-krait.S b/cpuburn/cpuburn-krait.S
new file mode 100644
index 0000000..02f8c73
--- a/dev/null
+++ b/cpuburn/cpuburn-krait.S
@@ -0,0 +1,96 @@
+/*
+ * Copyright © 2016 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This program tries to stress Qualcomm Krait 300/400 processor to generate
+ * as much heat as possible.
+ * WARNING: improperly cooled or otherwise flawed hardware may potentially
+ * overheat and fail. Use at your own risk.
+ *
+ * Compilation instructions:
+ * $ arm-linux-gnueabihf-gcc -o cpuburn-krait cpuburn-krait.S
+ *
+ * See http://ssvb.github.io/2012/04/10/cpuburn-arm-cortex-a9.html
+ * for more details.
+ */
+
+ .syntax unified
+ .text
+ .arch armv7-a
+ .fpu neon
+ .global main
+ .type main, %function
+ .align 2
+ .arm
+
+main:
+ push {r4-r12, lr}
+
+#ifdef __linux__
+ mov r0, #84 /* _SC_NPROCESSORS_ONLN */
+ bl sysconf
+ mov r4, r0
+ cmp r4, #2
+ blt 1f
+ bl fork /* have at least 2 cores */
+ cmp r4, #4
+ blt 1f
+ bl fork /* have at least 4 cores */
+ cmp r4, #8
+ blt 1f
+ bl fork /* have at least 8 cores */
+1:
+#endif
+ vmov.u8 q8, #0x0
+ vmov.u8 q9, #0x0
+ vmov.u8 q14, #0xff
+ vmov.u8 q15, #0xff
+
+ adr lr, 9f
+ mov r1, #16
+ mov r2, #-16
+ mov ip, #1
+ b 0f
+
+ .balign 64
+9:
+ .rept 64
+ .long 0xffffffff
+ .endr
+
+ .balign 64
+/****************************************************************************/
+/* Main loop (2 cycles per loop iteration, reaching peak IPC=3) */
+/****************************************************************************/
+0: vld2.8 {q1}, [lr, :128], r1
+ vaba.u8 q8, q2, q14
+
+ vld2.8 {q2}, [lr, :128], r2
+ vaba.u8 q9, q1, q15
+
+ subs ip, ip, #0
+ bne 0b
+/****************************************************************************/
+
+ mov r0, #0
+ pop {r4-r12, pc}
diff --git a/cpuburn/cpufreq-ljt-stress-test b/cpuburn/cpufreq-ljt-stress-test
new file mode 100644
index 0000000..dc3f93e
--- a/dev/null
+++ b/cpuburn/cpufreq-ljt-stress-test
@@ -0,0 +1,217 @@
+#!/usr/bin/env ruby
+#
+# Copyright © 2014 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+raise "Please upgrade ruby to at least version 1.9" if RUBY_VERSION =~ /^1\.8/
+
+require 'shellwords'
+
+# Test the availability of the required tools
+
+def tool_exists(tool_name)
+ `which #{tool_name} > /dev/null 2>&1`
+ if $?.to_i != 0 then
+ printf("Error: the required '%s' executable is not found in PATH\n", tool_name)
+ return false
+ else
+ return true
+ end
+end
+
+exit(1) if not tool_exists("md5sum") or
+ not tool_exists("nproc") or
+ not tool_exists("taskset")
+
+$cjpeg = "cjpeg"
+$djpeg = "djpeg"
+
+def download_and_compile_libjpeg_turbo()
+ exit(1) if not tool_exists("wget") or
+ not tool_exists("tar") or
+ not tool_exists("gcc")
+
+ shellescaped_dirname = Shellwords.escape(File.dirname(__FILE__))
+ ljtname = File.join(File.dirname(__FILE__), "libjpeg-turbo-1.3.1")
+ shellescaped_ljtname = Shellwords.escape(ljtname)
+
+ if File.exists?(File.join(ljtname, "djpeg")) then
+ $cjpeg = Shellwords.escape(File.join(ljtname, "cjpeg"))
+ $djpeg = Shellwords.escape(File.join(ljtname, "djpeg"))
+ return
+ end
+
+ if not `md5sum #{shellescaped_ljtname}.tar.gz 2>&1` =~ /2c3a68129dac443a72815ff5bb374b05/ then
+ url = "http://downloads.sourceforge.net/project/libjpeg-turbo/1.3.1/libjpeg-turbo-1.3.1.tar.gz"
+ printf("Downloading libjpeg-turbo-1.3.1.tar.gz ...")
+ `wget -c #{url} -O #{shellescaped_ljtname}.tar.gz 2>&1`
+ if $?.to_i != 0 then
+ printf(" failed\n")
+ exit(1)
+ end
+ printf(" done\n")
+ end
+ if not `md5sum #{shellescaped_ljtname}.tar.gz 2>&1` =~ /2c3a68129dac443a72815ff5bb374b05/ then
+ printf("MD5 check failed for the downloaded libjpeg-turbo-1.3.1.tar.gz\n")
+ exit(1)
+ end
+
+ printf("Extracting libjpeg-turbo-1.3.1.tar.gz ...")
+ `tar -xzf #{shellescaped_ljtname}.tar.gz -C #{shellescaped_dirname}`
+ if $?.to_i != 0 then
+ printf(" failed\n")
+ exit(1)
+ end
+ printf(" done\n")
+
+ Dir.chdir(ljtname) {
+ printf("Compiling libjpeg-turbo, please be patient ...")
+ compilation_log = `./configure --disable-shared && make -j2 2>&1`
+ if $?.to_i != 0 then
+ printf(" failed\n%s\n", compilation_log)
+ exit(1)
+ end
+ printf(" done\n")
+ }
+
+ $cjpeg = Shellwords.escape(File.join(ljtname, "cjpeg"))
+ $djpeg = Shellwords.escape(File.join(ljtname, "djpeg"))
+end
+
+# Check if we have the right cjpeg and djpeg
+if not `#{$djpeg} -v </dev/null 2>&1` =~ /libjpeg\-turbo/ or
+ not `#{$cjpeg} -v </dev/null 2>&1` =~ /libjpeg\-turbo/
+then
+ printf("The cjpeg and djpeg tools from libjpeg-turbo are not found.\n")
+ printf("Trying to download and compile them.\n")
+ download_and_compile_libjpeg_turbo()
+end
+
+###############################################################################
+
+def create_random_jpg(filename, width, height)
+ IO.popen(sprintf("#{$cjpeg} -q 95 > %s", Shellwords.escape(filename)), "wb") {|fh|
+ fh.printf("P3\n%d %d\n255\n", width, height)
+ fh.write(Random.new(0).bytes(3 * width * height).bytes.to_a.map {|x|
+ x.to_s }.join(" "))
+ }
+end
+
+def read_file(filename)
+ return if not File.exists?(filename)
+ fh = File.open(filename, "rb")
+ data = fh.read
+ fh.close
+ return data
+end
+
+def write_file(filename, data)
+ begin
+ fh = File.open(filename, "wb")
+ fh.write(data)
+ fh.close
+ rescue
+ return false
+ end
+ return true
+end
+
+def set_userspace_governor(core)
+ write_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/scaling_governor", "userspace")
+ governor = read_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/scaling_governor")
+ return false if not governor
+ return governor.strip == "userspace"
+end
+
+def set_freq(core, freq)
+ write_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/scaling_setspeed", freq.to_s)
+ cur_freq = read_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/scaling_cur_freq")
+ return false if not cur_freq
+ return cur_freq.to_i == freq
+end
+
+def get_freq_list(core)
+ freq_list = read_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/scaling_available_frequencies")
+ if not freq_list then
+ freq_list = read_file("/sys/devices/system/cpu/cpu#{core}/cpufreq/stats/time_in_state")
+ return [] if not freq_list
+ return freq_list.split(/\s+/).each_slice(2).map {|x| x[0].to_i}
+ end
+ return freq_list.split(" ").map {|x| x.to_i}
+end
+
+jpgname = File.join(File.dirname(__FILE__), "whitenoise-1920x1080.jpg")
+shellescaped_jpgname = Shellwords.escape(jpgname)
+
+if not File.exists?(jpgname) then
+ printf("Creating '%s' ...", jpgname)
+ create_random_jpg(jpgname, 1920, 1080)
+ printf(" done\n")
+end
+
+number_of_cpu_cores = `nproc`.to_i
+
+test_failed = false
+
+min_freq = 0
+max_freq = 10000
+
+printf("CPU stress test, which is doing JPEG decoding by libjpeg-turbo\n")
+printf("at different cpufreq operating points.\n")
+
+if ARGV[0] and ARGV[1] then
+ min_freq = [ARGV[0].to_i, ARGV[1].to_i].min
+ max_freq = [ARGV[0].to_i, ARGV[1].to_i].max
+ printf("\nTesting CPU clock frequencies between %d MHz and %d MHz\n",
+ min_freq, max_freq)
+end
+
+0.upto(number_of_cpu_cores - 1) {|core|
+ printf("\nTesting CPU %d\n", core)
+ if not set_userspace_governor(core) then
+ raise "Can't set the userspace cpufreq governor"
+ end
+
+ freq_list = get_freq_list(core)
+ freq_list.sort.reverse.each {|freq|
+ printf("%5d MHz ", freq / 1000)
+ if freq < min_freq * 1000 or freq > max_freq * 1000 or not set_freq(core, freq)
+ then
+ printf("SKIPPED\n")
+ next
+ end
+ subtest_failed = false
+ expected_result = `taskset -c #{core} #{$djpeg} #{shellescaped_jpgname} | md5sum`
+ 1.upto(60) {
+ printf(".")
+ STDOUT.flush
+ if `taskset -c #{core} #{$djpeg} #{shellescaped_jpgname} | md5sum` != expected_result
+ then
+ subtest_failed = true
+ break
+ end
+ }
+ test_failed = true if subtest_failed
+ printf(subtest_failed ? " FAILED\n" : " OK\n")
+ }
+}
+
+printf("\nOverall result : %s\n", (test_failed ? "FAILED" : "PASSED"))
diff --git a/cpuburn/gnuplot-sunxi-cpufreq b/cpuburn/gnuplot-sunxi-cpufreq
new file mode 100644
index 0000000..ba80b39
--- a/dev/null
+++ b/cpuburn/gnuplot-sunxi-cpufreq
@@ -0,0 +1,112 @@
+#!/usr/bin/env ruby
+#
+# Copyright © 2014 Siarhei Siamashka <siarhei.siamashka@gmail.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+require 'tempfile'
+
+# Test the availability of the required tools
+
+def tool_exists(tool_name)
+ `which #{tool_name} > /dev/null 2>&1`
+ if $?.to_i != 0 then
+ printf("Error: the required '%s' executable is not found in PATH\n", tool_name)
+ return false
+ else
+ return true
+ end
+end
+
+exit(1) if not tool_exists("gnuplot")
+
+pngfile = nil
+cpufreq_src_files = []
+
+ARGV.each {|a|
+ if a =~ /\.png$/ then
+ pngfile = a
+ else
+ cpufreq_src_files.push(a) if File.exists?(a)
+ end
+}
+
+if not pngfile or cpufreq_src_files.size == 0 then
+ printf("Usage: #{$PROGRAM_NAME} <png_file> <cpufreq_src_file> [cpufreq_src_file]\n")
+ printf("Where:\n")
+ printf(" png_file - resulting PNG file with the plot.\n")
+ printf(" cpufreq_src_file - source file with the cpufreq table\n")
+ printf(" to parse (from the sunxi-3.4 kernel).\n")
+ exit(1)
+end
+
+data = {}
+# Parse the linux-sunxi cpufreq tables
+tablename = nil
+cpufreq_src_files.each {|filename|
+ File.open(filename).each_line {|l|
+ if l =~ /static struct cpufreq_dvfs (.*?)[_]?dvfs_table\[\]/ then
+ tablename = $1
+ tablename = "unknown" if tablename == ""
+ data[tablename] = [] if not data.has_key?(tablename)
+ end
+ if l =~ /\.freq\s*\=\s*(\d+),\s*\.volt\s*\=\s*(\d+)/ then
+ freq = $1.to_i / 1000000
+ volt = $2.to_f / 1000
+ if freq == 0 then
+ tablename = nil
+ end
+ data[tablename].push([freq, volt]) if tablename
+ end
+ }
+}
+
+# Prepare and feed data to gnuplot
+tmpfiles = {}
+data.each {|tablename, data|
+ tmpfiles[tablename] = Tempfile.new(tablename)
+ data.each {|v|
+ tmpfiles[tablename].printf("%f %f\n", v[0], v[1])
+ }
+ tmpfiles[tablename].flush
+}
+
+IO.popen("gnuplot", "w") {|fh|
+ fh.write "
+ set terminal png size 1600, 900
+ set output '#{pngfile}'
+ set format y '%.3f'
+ set xtics 48
+ set ytics 0.025
+ set grid xtics ytics
+ set yrange [0.9:1.575]
+ set xlabel 'CPU clock frequency, MHz'
+ set ylabel 'Required core voltage for reliable operation, V'
+ set style line 1 lc rgb 'blue' linewidth 10
+ set style line 2 lc rgb 'cyan' linewidth 8
+ set style line 3 lc rgb 'orange' linewidth 6
+ set style line 4 lc rgb 'brown' linewidth 4
+ "
+ plotdata = data.sort.map.with_index {|x, i|
+ "'%s' using 1:2 with linespoints ls #{i + 1} title '%s'" %
+ [tmpfiles[x[0]].path, x[0]]
+ }
+ fh.printf("plot %s\n", plotdata.join(","))
+}