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