Author: wmb Date: Mon Mar 25 23:36:14 2013 New Revision: 3623 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3623
Log: OLPC XO-4 - improved the reliability of the audio test: a) Instead of the real random number generator, use a LFSR-based PRNG, with a polynomial that happens to give a good spectrum for acoustic testing with OLPC speakers. In addition to working around a unit- dependent problem with the MMP3's hardware RNG, this also speeds up the test because the LFSR is faster than the hardware RNG. b) Store 16-bit "random" values in the audio buffer instead of using 32-bit random numbers and hoping that the top and bottom halves are uncorrelated. This seems to give better decorrelation of left and right signals. c) Hard-reset the audio subsystem by powering off/on the audio island between the acoustic and loopback tests, thus making the loopback test more repeatable.
Added: forth/lib/lfsr-memtest.fth Modified: cpu/arm/olpc/build-fw.fth cpu/arm/olpc/sound.fth cpu/x86/pc/olpc/via/fw.bth dev/hdaudio/noiseburst.fth dev/hdaudio/test.fth forth/lib/lfsr.fth
Modified: cpu/arm/olpc/build-fw.fth ============================================================================== --- cpu/arm/olpc/build-fw.fth Thu Mar 21 07:33:20 2013 (r3622) +++ cpu/arm/olpc/build-fw.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -741,6 +741,15 @@
fload ${BP}/cpu/arm/saverom.fth \ Save the dictionary for standalone startup
+fload ${BP}/forth/lib/lfsr.fth +0 value lfsr-state +: init-audio-noise ( -- ) + random-long to lfsr-state + \ Use a polynomial with a 32-bit period + lfsr-polynomials d# 32 na+ @ to lfsr-poly +; +: audio-noise ( -- n ) lfsr-state lfsr-step dup to lfsr-state ; + fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
\ Because visible doesn't work sometimes when calling back from Linux
Modified: cpu/arm/olpc/sound.fth ============================================================================== --- cpu/arm/olpc/sound.fth Thu Mar 21 07:33:20 2013 (r3622) +++ cpu/arm/olpc/sound.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -182,6 +182,14 @@ then false ; +\ This is a grotesque workaround for a hardware problem. The audio +\ subsystem (SSPA + ADMA) works reasonably reliably right after the +\ audio island is powered on, but subsequent tries tend to get +\ confused about which channel is which, and possibly about the +\ initial SSPA FIFO contents. Resetting between test phases makes +\ the test work more reliably. Attempts to get help from the vendor, +\ over a long period of time, were unsuccessful. +: reset-audio ( -- ) audio-clock-off d# 50 ms audio-clock-on drop ;
: reset-rx ( -- ) h# 8000.0002 h# 0c sspa! ;
Modified: cpu/x86/pc/olpc/via/fw.bth ============================================================================== --- cpu/x86/pc/olpc/via/fw.bth Thu Mar 21 07:33:20 2013 (r3622) +++ cpu/x86/pc/olpc/via/fw.bth Mon Mar 25 23:36:14 2013 (r3623) @@ -479,6 +479,8 @@ fload ${BP}/forth/lib/selstr.fth
fload ${BP}/cpu/x86/pc/olpc/via/padlock.fth \ Via security engine +alias init-audio-noise noop +alias audio-noise random-long fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
fload ${BP}/ofw/inet/loadtcp.fth
Modified: dev/hdaudio/noiseburst.fth ============================================================================== --- dev/hdaudio/noiseburst.fth Thu Mar 21 07:33:20 2013 (r3622) +++ dev/hdaudio/noiseburst.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -620,14 +620,18 @@ [then]
: prepare-signal ( -- out-adr, len in-adr,len ) + init-audio-noise + \ Doing the noise 16 bits at a time does a better job + \ of decorrelating the channels compared to storing + \ a 32-bit "random" number [ifdef] debug-analyzer? debug-analyzer? if pb /pb d# 1000 d# 48000 make-2tones else - pb /pb bounds do random-long i l! /l +loop + pb /pb bounds do audio-noise i w! /w +loop then [else] - pb /pb bounds do random-long i l! /l +loop + pb /pb bounds do audio-noise i w! /w +loop [then] pb /pb -stereo-wmean pb wa1+ /pb -stereo-wmean
Modified: dev/hdaudio/test.fth ============================================================================== --- dev/hdaudio/test.fth Thu Mar 21 07:33:20 2013 (r3622) +++ dev/hdaudio/test.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -227,6 +227,7 @@ : automatic-test ( -- ) analysis-parameters " set-analysis-parameters" $call-analyzer acoustic-test + [ifdef] reset-audio reset-audio [then] loopback-test ; : selftest ( -- error? )
Added: forth/lib/lfsr-memtest.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ forth/lib/lfsr-memtest.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -0,0 +1,143 @@ +\ See license at end of file +purpose: Linear feedback shift register memory tests + +[ifdef] arm-assembler +code lfsr-fill ( adr seed polynomial -- adr' ) + \ tos:polynomial + ldmia sp!,{r0,r1} \ r0:seed r1:adr + mov r2,r0 \ r2:lfsr + begin + str r2,[r1],#4 + movs r2,r2,lsr #1 + eorcs r2,r2,tos + cmp r2,r0 + = until + mov tos,r1 +c; +code random-fill ( adr len data index polynomial -- ) + ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr + + movs r3,r3,lsr #2 \ Convert to longword count + nxteq + + sub r0,r3,#1 \ r0:remaining count + + \ r3:address-lfsr r4:data-lfsr r5:data-poly + set r5,#0x80200003 \ 32-bit polynomial + + begin + \ Compute new data value with an LFSR step + movs r2,r2,lsr #1 + eorcs r2,r2,r5 + + \ Compute new address index, discarding values >= len + begin + movs r1,r1,lsr #1 + eorcs r1,r1,tos + cmp r1,r3 + u< until + + \ Write the "random" value to the "random" address (adr[index]) + str r2,[r4,r1,lsl #2] + + decs r0,#1 + 0= until + + pop tos,sp +c; +code random-check ( adr len data index remain polynomial -- false | adr len data index remain true ) + ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr + + cmp r0,#0 + moveq tos,#0 \ Return false + nxteq + + mov r7,r3,lsr #2 \ Convert to longword count + + set r5,#0x80200003 \ 32-bit polynomial + + begin + \ Compute new data value with an LFSR step + movs r2,r2,lsr #1 + eorcs r2,r2,r5 + + \ Compute new address index, discarding values >= len + begin + movs r1,r1,lsr #1 + eorcs r1,r1,tos + cmp r1,r7 + u< until + + \ Read the value at the "random" address (adr[index]) + ldr r6,[r4,r1,lsl #2] + + \ Compare it to the calculated value + cmp r6,r2 + + decne r0,#1 + stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results + mvnne tos,#0 \ True on top of stack + nxtne + + decs r0,#1 + 0= until + + mov tos,#0 +c; +[then] +: round-up-log2 ( n -- log2 ) + dup log2 ( n log2 ) + tuck 1 swap lshift ( log2 n 2^log2 ) + > - ( log2' ) +; + +defer .lfsr-mem-error +: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain ) + push-hex + ." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr ) + ." - expected " 3 pick 8 u.r ( adr len data index remain err-adr ) + ." got " l@ 8 u.r cr + pop-base +; +' (.lfsr-mem-error) to .lfsr-mem-error + +: random-test ( adr len -- ) + dup /l <= if 2drop exit then ( adr len #bits ) + dup /l / round-up-log2 ( adr len #bits ) + polynomials swap la+ l@ ( adr len polynomial ) + + 3dup 1 1 rot random-fill ( adr len polynomial ) + + >r ( adr len r: polynomial ) + 1 1 third /l / 1- ( adr len data index remain r: polynomial ) + begin ( adr len data index remain r: polynomial ) + r@ random-check ( false | adr len data index remain true r: polynomial ) + while ( adr len data index remain r: polynomial ) + .lfsr-mem-error ( adr len data index remain r: polynomial ) + repeat ( r: polynomial ) + r> drop +; + +\ LICENSE_BEGIN +\ Copyright (c) 2010 FirmWorks +\ +\ 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 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. +\ +\ LICENSE_END
Modified: forth/lib/lfsr.fth ============================================================================== --- forth/lib/lfsr.fth Thu Mar 21 07:33:20 2013 (r3622) +++ forth/lib/lfsr.fth Mon Mar 25 23:36:14 2013 (r3623) @@ -1,12 +1,7 @@ \ See license at end of file purpose: Linear feedback shift register code and related memory tests
-0 value lfsr-state - 0 value lfsr-poly -: lfsr-step ( state -- state' ) - dup 2/ swap 1 and if lfsr-poly xor then -;
[ifdef] arm-assembler code lfsr-step ( state -- state' ) @@ -17,89 +12,6 @@ eor tos,tos,r0 then c; -code lfsr-fill ( adr seed polynomial -- adr' ) - \ tos:polynomial - ldmia sp!,{r0,r1} \ r0:seed r1:adr - mov r2,r0 \ r2:lfsr - begin - str r2,[r1],#4 - movs r2,r2,lsr #1 - eorcs r2,r2,tos - cmp r2,r0 - = until - mov tos,r1 -c; -code random-fill ( adr len data index polynomial -- ) - ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr - - movs r3,r3,lsr #2 \ Convert to longword count - nxteq - - sub r0,r3,#1 \ r0:remaining count - - \ r3:address-lfsr r4:data-lfsr r5:data-poly - set r5,#0x80200003 \ 32-bit polynomial - - begin - \ Compute new data value with an LFSR step - movs r2,r2,lsr #1 - eorcs r2,r2,r5 - - \ Compute new address index, discarding values >= len - begin - movs r1,r1,lsr #1 - eorcs r1,r1,tos - cmp r1,r3 - u< until - - \ Write the "random" value to the "random" address (adr[index]) - str r2,[r4,r1,lsl #2] - - decs r0,#1 - 0= until - - pop tos,sp -c; -code random-check ( adr len data index remain polynomial -- false | adr len data index remain true ) - ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr - - cmp r0,#0 - moveq tos,#0 \ Return false - nxteq - - mov r7,r3,lsr #2 \ Convert to longword count - - set r5,#0x80200003 \ 32-bit polynomial - - begin - \ Compute new data value with an LFSR step - movs r2,r2,lsr #1 - eorcs r2,r2,r5 - - \ Compute new address index, discarding values >= len - begin - movs r1,r1,lsr #1 - eorcs r1,r1,tos - cmp r1,r7 - u< until - - \ Read the value at the "random" address (adr[index]) - ldr r6,[r4,r1,lsl #2] - - \ Compare it to the calculated value - cmp r6,r2 - - decne r0,#1 - stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results - mvnne tos,#0 \ True on top of stack - nxtne - - decs r0,#1 - 0= until - - mov tos,#0 -c; -[then] 0 [if] \ This is for testing the period of various polynomials code lfsr-period ( polynomial -- period ) \ tos:polynomial @@ -127,6 +39,11 @@ ax push c; [then] +[ifndef] lfsr-step +: lfsr-step ( state -- state' ) + dup 2/ swap 1 and if lfsr-poly xor then +; +[then]
0 [if] \ Given a list of bit numbers for the polynomial taps, compute the mask value @@ -146,7 +63,8 @@ \ Polynomials for maximal length LFSRs for different bit lengths \ The values come from the Wikipedia article for Linear Feedback Shift Register and from \ http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf -create polynomials \ #bits period +create lfsr-polynomials + \ #bits period h# 0 , \ 0 0 h# 1 , \ 1 1 h# 3 , \ 2 3 @@ -181,38 +99,6 @@ h# 48000000 , \ 31 7fffffff h# 80200003 , \ 32 ffffffff
-: round-up-log2 ( n -- log2 ) - dup log2 ( n log2 ) - tuck 1 swap lshift ( log2 n 2^log2 ) - > - ( log2' ) -; - -defer .lfsr-mem-error -: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain ) - push-hex - ." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr ) - ." - expected " 3 pick 8 u.r ( adr len data index remain err-adr ) - ." got " l@ 8 u.r cr - pop-base -; -' (.lfsr-mem-error) to .lfsr-mem-error -: random-test ( adr len -- ) - dup /l <= if 2drop exit then ( adr len #bits ) - dup /l / round-up-log2 ( adr len #bits ) - polynomials swap la+ l@ ( adr len polynomial ) - - 3dup 1 1 rot random-fill ( adr len polynomial ) - - >r ( adr len r: polynomial ) - 1 1 third /l / 1- ( adr len data index remain r: polynomial ) - begin ( adr len data index remain r: polynomial ) - r@ random-check ( false | adr len data index remain true r: polynomial ) - while ( adr len data index remain r: polynomial ) - .lfsr-mem-error ( adr len data index remain r: polynomial ) - repeat ( r: polynomial ) - r> drop -; - \ LICENSE_BEGIN \ Copyright (c) 2010 FirmWorks \
openfirmware@openfirmware.info