Mercurial > nand-ecoscentric
diff packages/kernel/current/tests/clockcnv.cxx @ 64:c38311975d4f ecos-sw-2000-01-28
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
| author | jlarmour |
|---|---|
| date | Fri, 28 Jan 2000 04:59:39 +0000 |
| parents | |
| children | bf00f99aec69 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/kernel/current/tests/clockcnv.cxx @@ -0,0 +1,269 @@ +//========================================================================== +// +// clockcnv.cxx +// +// Clock Converter test +// +//========================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.0 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://sourceware.cygnus.com/ecos +// +// Software distributed under the License is distributed on an +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2000-01-24 +// Description: Tests the Kernel Real Time Clock Converter subsystem +// +//####DESCRIPTIONEND#### + +#include <pkgconf/kernel.h> + +#include <cyg/kernel/clock.hxx> +#include <cyg/kernel/thread.hxx> + +#include <cyg/infra/testcase.h> + +#include <cyg/kernel/clock.inl> +#include <cyg/kernel/thread.inl> + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK + +externC void diag_printf(const char *, ...); + +static void null_printf(const char *, ...) +{ /* nothing */ } + +#define PRINTF0 diag_printf +#define nPRINTF0 null_printf + +#define nPRINTF1 diag_printf +#define PRINTF1 null_printf + +#define nPRINTF2 diag_printf +#define PRINTF2 null_printf + + +#define NTHREADS 1 +#include "testaux.hxx" + +static struct { cyg_uint32 ns; double scale; } ns_tickers[] = { + { 70000000, 7.0 }, // 7cS + { 50000000, 5.0 }, // 5cS + { 45000000, 4.5 }, // 4.5cS + { 30000000, 3.0 }, // 3cS + { 20000000, 2.0 }, // 2cS + { 10000000, 1.0 }, // 1cS - no change + { 5000000, 0.5 }, // 1/2 a cS + { 4900000, 0.49 }, // a bit below + { 3333333, 0.3333333 }, // 1/3 cS + { 1250000, 0.125 }, // 800Hz + { 1000000, 0.1 }, // 1000Hz + { 909090, 0.0909090 }, // 1100Hz + { 490000, 0.049 }, // 490uS + { 333333, 0.0333333 }, // 1/30 cS, 1/3mS + { 49000, 0.0049 }, // 49uS + { 33333, 0.0033333 }, // 1/30 mS + { 4900, 0.00049 }, // 4.9uS + // now some outlandish ones + { 170, 0.000017 }, // 170nS + { 11, 0.0000011 }, // 11nS + { 1000000000u, 100.0 }, // one second + { 1234567777u, 123.4567777 }, // 1.234... seconds + { 4294967291u, 429.4967291 }, // 4.3 seconds, nearly maxint. + // now some which are prime in the nS per tick field + { 909091, 0.0909091 }, // also 1100Hz - but 909091 is a prime! + // and some eye-pleasing primes from the www - if they're not actually + // prime, don't blame me. http://www.rsok.com/~jrm/printprimes.html + { 1000003, 0.1000003 }, + { 1477771, 0.1477771 }, + { 2000003, 0.2000003 }, + { 2382001, 0.2382001 }, + { 3333133, 0.3333133 }, + { 3999971, 0.3999971 }, + { 5555591, 0.5555591 }, + { 6013919, 0.6013919 }, + // That's enough +}; + +static void entry0( CYG_ADDRWORD data ) +{ + // First just try it with the clock as default: + Cyg_Clock *rtc = Cyg_Clock::real_time_clock; + + Cyg_Clock::converter cv, rcv; + Cyg_Clock::cyg_resolution res; + + unsigned int counter = 0; + unsigned int skipped = 0; + + unsigned int i; + for ( i = 0; i < sizeof( ns_tickers )/sizeof( ns_tickers[0] ); i++ ) { + + unsigned int lcounter = 0; + unsigned int lskipped = 0; + + rtc->get_other_to_clock_converter( ns_tickers[i].ns, &cv ); + rtc->get_clock_to_other_converter( ns_tickers[i].ns, &rcv ); + + PRINTF1( "ns per tick: %d\n", ns_tickers[i].ns ); + PRINTF1( " converter: * %d / %d * %d / %d\n", + (int)cv.mul1, (int)cv.div1, (int)cv.mul2,(int) cv.div2 ); + PRINTF1( " reverser: * %d / %d * %d / %d\n", + (int)rcv.mul1, (int)rcv.div1, (int)rcv.mul2, (int)rcv.div2 ); + + double d = 1.0; + d *= (double)cv.mul1; + d /= (double)cv.div1; + d *= (double)cv.mul2; + d /= (double)cv.div2; + d *= (double)rcv.mul1; + d /= (double)rcv.div1; + d *= (double)rcv.mul2; + d /= (double)rcv.div2; + PRINTF1( " composite product %d.%d\n", + (int)d, ((int)(d * 1000000) % 1000000 ) ); + d -= 1.0; + CYG_TEST_CHECK( d < +0.0001, "Overflow in composite product" ); + CYG_TEST_CHECK( d > -0.0001, "Underflow in composite product" ); + + res = rtc->get_resolution(); + + double factor_other_to_clock; + double factor_clock_to_other; + + // res.dividend/res.divisor is the number of nS in a system + // clock tick. So: + d = (double)res.dividend/(double)res.divisor; + + factor_other_to_clock = ns_tickers[i].scale * 1.0e7 / d ; + factor_clock_to_other = d / (ns_tickers[i].scale * 1.0e7); + + unsigned int j; + for ( j = 1; j < 100; j++ ) { + cyg_uint64 delay; + if (cyg_test_is_simulator) + j += 30; // test fewer values + /* tr.b..m..k.. */ + for ( delay = j; delay < 1000000000000ll; delay *= 10 ) { + // get the converted result + cyg_uint64 result = Cyg_Clock::convert( delay, &cv ); + + counter++; lcounter++; + if ( (double)delay * (double)cv.mul1 > 1.6e+19 || + (double)delay * (double)rcv.mul1 > 1.6e+19 ) { + // in silly territory now, give up. + // (that's MAXINT squared, approx.) + skipped++; lskipped++; + continue; // so the counter is accurate + } + + PRINTF2( "delay %x%08x to result %x%08x\n", + (int)(delay >> 32), (int)delay, + (int)(result >> 32), (int)result ); + + // get what it should be in double maths + double delta = factor_other_to_clock * (double)delay; + if ( delta > 1000.0 ) { + delta = (double)result - delta; + delta /= (double)result; + CYG_TEST_CHECK( delta <= +0.01, + "Proportional overflow in conversion to" ); + CYG_TEST_CHECK( delta >= -0.01, + "Proportional underflow in conversion to" ); + } + else { + cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION + cyg_uint64 hi = lo + 1; + CYG_TEST_CHECK( hi >= result, + "Range overflow in conversion to" ); + CYG_TEST_CHECK( lo <= result, + "Range underflow in conversion to" ); + } + + // get the converted result + result = Cyg_Clock::convert( delay, &rcv ); + + PRINTF2( "delay %x%08x from result %x%08x\n", + (int)(delay >> 32), (int)delay, + (int)(result >> 32), (int)result ); + + // get what it should be in double maths + delta = factor_clock_to_other * (double)delay; + if ( delta > 1000.0 ) { + delta = (double)result - delta; + delta /= (double)result; + CYG_TEST_CHECK( delta <= +0.01, + "Proportional overflow in conversion from" ); + CYG_TEST_CHECK( delta >= -0.01, + "Proportional underflow in conversion from" ); + } + else { + cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION + cyg_uint64 hi = lo + 1; + CYG_TEST_CHECK( hi >= result, + "Range overflow in conversion from" ); + CYG_TEST_CHECK( lo <= result, + "Range underflow in conversion from" ); + } + + if (cyg_test_is_simulator) + break; + } + } + PRINTF0( "INFO:<%d nS/tick: tested %d values, skipped %d because of overflow>\n", + ns_tickers[i].ns, lcounter, lskipped ); + } + + PRINTF0( "INFO:<tested %d values, total skipped %d because of overflow>\n", + counter, skipped ); + + CYG_TEST_PASS_FINISH("ClockCnv OK"); +} + +void clockcnv_main( void ) +{ + CYG_TEST_INIT(); + new_thread(entry0, (CYG_ADDRWORD)&thread_obj[0]); + Cyg_Scheduler::start(); +} + +externC void +cyg_start( void ) +{ + clockcnv_main(); +} + +#else // def CYGVAR_KERNEL_COUNTERS_CLOCK + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( "Kernel real-time clock disabled"); +} + +#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK + +// EOF clockcnv.cxx
