1 //  cycle_count.cpp  ----------------------------------------------------------//
2 
3 //  Copyright 2008 Howard Hinnant
4 //  Copyright 2008 Beman Dawes
5 //  Copyright 2009 Vicente J. Botet Escriba
6 
7 //  Distributed under the Boost Software License, Version 1.0.
8 //  See http://www.boost.org/LICENSE_1_0.txt
9 
10 /*
11 This code was extracted by Vicente J. Botet Escriba from Beman Dawes time2_demo.cpp which
12 was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
13 Many thanks to Howard for making his code available under the Boost license.
14 The original code was modified to conform to Boost conventions and to section
15 20.9 Time utilities [time] of the C++ committee's working paper N2798.
16 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
17 
18 time2_demo contained this comment:
19 
20     Much thanks to Andrei Alexandrescu,
21                    Walter Brown,
22                    Peter Dimov,
23                    Jeff Garland,
24                    Terry Golubiewski,
25                    Daniel Krugler,
26                    Anthony Williams.
27 */
28 
29 #include <boost/chrono/chrono.hpp>
30 #include <boost/type_traits.hpp>
31 
32 #include <iostream>
33 
34 using namespace boost::chrono;
35 
36 
37 template <long long speed>
38 struct cycle_count
39 {
40     typedef typename boost::ratio_multiply<boost::ratio<speed>, boost::mega>::type frequency;  // Mhz
41     typedef typename boost::ratio_divide<boost::ratio<1>, frequency>::type period;
42     typedef long long rep;
43     typedef boost::chrono::duration<rep, period> duration;
44     typedef boost::chrono::time_point<cycle_count> time_point;
45 
nowcycle_count46     static time_point now()
47     {
48         static long long tick = 0;
49         // return exact cycle count
50         return time_point(duration(++tick));  // fake access to clock cycle count
51     }
52 };
53 
54 template <long long speed>
55 struct approx_cycle_count
56 {
57     static const long long frequency = speed * 1000000;  // MHz
58     typedef nanoseconds duration;
59     typedef duration::rep rep;
60     typedef duration::period period;
61     static const long long nanosec_per_sec = period::den;
62     typedef boost::chrono::time_point<approx_cycle_count> time_point;
63 
nowapprox_cycle_count64     static time_point now()
65     {
66         static long long tick = 0;
67         // return cycle count as an approximate number of nanoseconds
68         // compute as if nanoseconds is only duration in the std::lib
69         return time_point(duration(++tick * nanosec_per_sec / frequency));
70     }
71 };
72 
cycle_count_delay()73 void cycle_count_delay()
74 {
75     {
76     typedef cycle_count<400> clock;
77     std::cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
78          << duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
79     nanoseconds delayns(500);
80     clock::duration delay = duration_cast<clock::duration>(delayns);
81     std::cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
82     clock::time_point start = clock::now();
83     clock::time_point stop = start + delay;
84     while (clock::now() < stop)  // no multiplies or divides in this loop
85         ;
86     clock::time_point end = clock::now();
87     clock::duration elapsed = end - start;
88     std::cout << "paused " << elapsed.count() << " cycles ";
89     std::cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
90     }
91     {
92     typedef approx_cycle_count<400> clock;
93     std::cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
94     clock::duration delay = nanoseconds(500);
95     std::cout << "delay = " << delay.count() << " nanoseconds\n";
96     clock::time_point start = clock::now();
97     clock::time_point stop = start + delay;
98     while (clock::now() < stop) // 1 multiplication and 1 division in this loop
99         ;
100     clock::time_point end = clock::now();
101     clock::duration elapsed = end - start;
102     std::cout << "paused " << elapsed.count() << " nanoseconds\n";
103     }
104     {
105     typedef cycle_count<1500> clock;
106     std::cout << "\nSimulated " << clock::frequency::num / boost::mega::num << "MHz clock which has a tick period of "
107          << duration<double, boost::nano>(clock::duration(1)).count() << " nanoseconds\n";
108     nanoseconds delayns(500);
109     clock::duration delay = duration_cast<clock::duration>(delayns);
110     std::cout << "delay = " << delayns.count() << " nanoseconds which is " << delay.count() << " cycles\n";
111     clock::time_point start = clock::now();
112     clock::time_point stop = start + delay;
113     while (clock::now() < stop)  // no multiplies or divides in this loop
114         ;
115     clock::time_point end = clock::now();
116     clock::duration elapsed = end - start;
117     std::cout << "paused " << elapsed.count() << " cycles ";
118     std::cout << "which is " << duration_cast<nanoseconds>(elapsed).count() << " nanoseconds\n";
119     }
120     {
121     typedef approx_cycle_count<1500> clock;
122     std::cout << "\nSimulated " << clock::frequency / 1000000 << "MHz clock modeled with nanoseconds\n";
123     clock::duration delay = nanoseconds(500);
124     std::cout << "delay = " << delay.count() << " nanoseconds\n";
125     clock::time_point start = clock::now();
126     clock::time_point stop = start + delay;
127     while (clock::now() < stop) // 1 multiplication and 1 division in this loop
128         ;
129     clock::time_point end = clock::now();
130     clock::duration elapsed = end - start;
131     std::cout << "paused " << elapsed.count() << " nanoseconds\n";
132     }
133 }
134 
main()135 int main()
136 {
137     cycle_count_delay();
138     return 0;
139 }
140 
141