1
/***************************************************************************
5
Support functions for working with attotime data.
7
****************************************************************************
12
Redistribution and use in source and binary forms, with or without
13
modification, are permitted provided that the following conditions are
16
* Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
18
* Redistributions in binary form must reproduce the above copyright
19
notice, this list of conditions and the following disclaimer in
20
the documentation and/or other materials provided with the
22
* Neither the name 'MAME' nor the names of its contributors may be
23
used to endorse or promote products derived from this software
24
without specific prior written permission.
26
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
27
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
30
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
POSSIBILITY OF SUCH DAMAGE.
38
****************************************************************************
40
Attotime is an attosecond-accurate timing system implemented as
43
1 second = 1e0 seconds
44
1 millisecond = 1e-3 seconds
45
1 microsecond = 1e-6 seconds
46
1 nanosecond = 1e-9 seconds
47
1 picosecond = 1e-12 seconds
48
1 femtosecond = 1e-15 seconds
49
1 attosecond = 1e-18 seconds
51
This may seem insanely accurate, but it has its uses when multiple
52
clocks in the system are run by independent crystals. It is also
53
useful to compute the attotime for something small, say 1 clock tick,
54
and still have it be accurate and useful for scaling.
56
Attotime consists of a 32-bit seconds count and a 64-bit attoseconds
57
count. Because the lower bits are kept as attoseconds and not as a
58
full 64-bit value, there is headroom to make some operations simpler.
60
***************************************************************************/
64
#ifndef __ATTOTIME_H__
65
#define __ATTOTIME_H__
73
//**************************************************************************
75
//**************************************************************************
77
// core components of the attotime structure
78
typedef INT64 attoseconds_t;
79
typedef INT32 seconds_t;
82
const attoseconds_t ATTOSECONDS_PER_SECOND_SQRT = 1000000000;
83
const attoseconds_t ATTOSECONDS_PER_SECOND = ATTOSECONDS_PER_SECOND_SQRT * ATTOSECONDS_PER_SECOND_SQRT;
84
const attoseconds_t ATTOSECONDS_PER_MILLISECOND = ATTOSECONDS_PER_SECOND / 1000;
85
const attoseconds_t ATTOSECONDS_PER_MICROSECOND = ATTOSECONDS_PER_SECOND / 1000000;
86
const attoseconds_t ATTOSECONDS_PER_NANOSECOND = ATTOSECONDS_PER_SECOND / 1000000000;
88
const seconds_t ATTOTIME_MAX_SECONDS = 1000000000;
92
//**************************************************************************
94
//**************************************************************************
96
// convert between a double and attoseconds
97
#define ATTOSECONDS_TO_DOUBLE(x) ((double)(x) * 1e-18)
98
#define DOUBLE_TO_ATTOSECONDS(x) ((attoseconds_t)((x) * 1e18))
100
// convert between hertz (as a double) and attoseconds
101
#define ATTOSECONDS_TO_HZ(x) ((double)ATTOSECONDS_PER_SECOND / (double)(x))
102
#define HZ_TO_ATTOSECONDS(x) ((attoseconds_t)(ATTOSECONDS_PER_SECOND / (x)))
104
// macros for converting other seconds types to attoseconds
105
#define ATTOSECONDS_IN_SEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_SECOND)
106
#define ATTOSECONDS_IN_MSEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_MILLISECOND)
107
#define ATTOSECONDS_IN_USEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_MICROSECOND)
108
#define ATTOSECONDS_IN_NSEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_NANOSECOND)
112
//**************************************************************************
114
//***************************************************************************/
116
// the attotime structure itself
120
// construction/destruction
125
attotime(seconds_t secs, attoseconds_t attos)
127
attoseconds(attos) { }
130
bool is_zero() const { return (seconds == 0 && attoseconds == 0); }
131
bool is_never() const { return (seconds >= ATTOTIME_MAX_SECONDS); }
133
// conversion to other forms
134
double as_double() const { return double(seconds) + ATTOSECONDS_TO_DOUBLE(attoseconds); }
135
attoseconds_t as_attoseconds() const;
136
UINT64 as_ticks(UINT32 frequency) const;
137
const char *as_string(int precision = 9) const;
139
// conversion from other forms
140
static attotime from_double(double _time);
141
static attotime from_ticks(UINT64 ticks, UINT32 frequency);
142
static attotime from_seconds(INT32 seconds) { return attotime(seconds, 0); }
143
static attotime from_msec(INT64 msec) { return attotime(msec / 1000, (msec % 1000) * (ATTOSECONDS_PER_SECOND / 1000)); }
144
static attotime from_usec(INT64 usec) { return attotime(usec / 1000000, (usec % 1000000) * (ATTOSECONDS_PER_SECOND / 1000000)); }
145
static attotime from_nsec(INT64 nsec) { return attotime(nsec / 1000000000, (nsec % 1000000000) * (ATTOSECONDS_PER_SECOND / 1000000000)); }
146
static attotime from_hz(double frequency) { return attotime(0, double(ATTOSECONDS_PER_SECOND) / frequency); }
149
attotime &operator+=(const attotime &right);
150
attotime &operator-=(const attotime &right);
151
attotime &operator*=(UINT32 factor);
152
attotime &operator/=(UINT32 factor);
156
attoseconds_t attoseconds;
159
static const attotime never;
160
static const attotime zero;
165
//**************************************************************************
167
//**************************************************************************
169
//-------------------------------------------------
170
// operator+ - handle addition between two
172
//-------------------------------------------------
174
inline attotime operator+(const attotime &left, const attotime &right)
178
// if one of the items is never, return never
179
if (left.seconds >= ATTOTIME_MAX_SECONDS || right.seconds >= ATTOTIME_MAX_SECONDS)
180
return attotime::never;
182
// add the seconds and attoseconds
183
result.attoseconds = left.attoseconds + right.attoseconds;
184
result.seconds = left.seconds + right.seconds;
186
// normalize and return
187
if (result.attoseconds >= ATTOSECONDS_PER_SECOND)
189
result.attoseconds -= ATTOSECONDS_PER_SECOND;
194
if (result.seconds >= ATTOTIME_MAX_SECONDS)
195
return attotime::never;
199
inline attotime &attotime::operator+=(const attotime &right)
201
// if one of the items is never, return never
202
if (this->seconds >= ATTOTIME_MAX_SECONDS || right.seconds >= ATTOTIME_MAX_SECONDS)
203
return *this = never;
205
// add the seconds and attoseconds
206
attoseconds += right.attoseconds;
207
seconds += right.seconds;
209
// normalize and return
210
if (this->attoseconds >= ATTOSECONDS_PER_SECOND)
212
this->attoseconds -= ATTOSECONDS_PER_SECOND;
217
if (this->seconds >= ATTOTIME_MAX_SECONDS)
218
return *this = never;
223
//-------------------------------------------------
224
// operator- - handle subtraction between two
226
//-------------------------------------------------
228
inline attotime operator-(const attotime &left, const attotime &right)
232
// if time1 is never, return never
233
if (left.seconds >= ATTOTIME_MAX_SECONDS)
234
return attotime::never;
236
// add the seconds and attoseconds
237
result.attoseconds = left.attoseconds - right.attoseconds;
238
result.seconds = left.seconds - right.seconds;
240
// normalize and return
241
if (result.attoseconds < 0)
243
result.attoseconds += ATTOSECONDS_PER_SECOND;
249
inline attotime &attotime::operator-=(const attotime &right)
251
// if time1 is never, return never
252
if (this->seconds >= ATTOTIME_MAX_SECONDS)
253
return *this = never;
255
// add the seconds and attoseconds
256
attoseconds -= right.attoseconds;
257
seconds -= right.seconds;
259
// normalize and return
260
if (this->attoseconds < 0)
262
this->attoseconds += ATTOSECONDS_PER_SECOND;
269
//-------------------------------------------------
270
// operator* - handle multiplication/division by
271
// an integral factor; defined in terms of the
272
// assignment operators
273
//-------------------------------------------------
275
inline attotime operator*(const attotime &left, UINT32 factor)
277
attotime result = left;
282
inline attotime operator*(UINT32 factor, const attotime &right)
284
attotime result = right;
289
inline attotime operator/(const attotime &left, UINT32 factor)
291
attotime result = left;
297
//-------------------------------------------------
298
// operator== - handle comparisons between
300
//-------------------------------------------------
302
inline bool operator==(const attotime &left, const attotime &right)
304
return (left.seconds == right.seconds && left.attoseconds == right.attoseconds);
307
inline bool operator!=(const attotime &left, const attotime &right)
309
return (left.seconds != right.seconds || left.attoseconds != right.attoseconds);
312
inline bool operator<(const attotime &left, const attotime &right)
314
return (left.seconds < right.seconds || (left.seconds == right.seconds && left.attoseconds < right.attoseconds));
317
inline bool operator<=(const attotime &left, const attotime &right)
319
return (left.seconds < right.seconds || (left.seconds == right.seconds && left.attoseconds <= right.attoseconds));
322
inline bool operator>(const attotime &left, const attotime &right)
324
return (left.seconds > right.seconds || (left.seconds == right.seconds && left.attoseconds > right.attoseconds));
327
inline bool operator>=(const attotime &left, const attotime &right)
329
return (left.seconds > right.seconds || (left.seconds == right.seconds && left.attoseconds >= right.attoseconds));
333
//-------------------------------------------------
334
// min - return the minimum of two attotimes
335
//-------------------------------------------------
337
inline attotime min(const attotime &left, const attotime &right)
339
if (left.seconds > right.seconds)
341
if (left.seconds < right.seconds)
343
if (left.attoseconds > right.attoseconds)
349
//-------------------------------------------------
350
// max - return the maximum of two attotimes
351
//-------------------------------------------------
353
inline attotime max(const attotime &left, const attotime &right)
355
if (left.seconds > right.seconds)
357
if (left.seconds < right.seconds)
359
if (left.attoseconds > right.attoseconds)
365
//-------------------------------------------------
366
// as_attoseconds - convert to an attoseconds
367
// value, clamping to +/- 1 second
368
//-------------------------------------------------
370
inline attoseconds_t attotime::as_attoseconds() const
372
// positive values between 0 and 1 second
376
// negative values between -1 and 0 seconds
377
else if (seconds == -1)
378
return attoseconds - ATTOSECONDS_PER_SECOND;
380
// out-of-range positive values
381
else if (seconds > 0)
382
return ATTOSECONDS_PER_SECOND;
384
// out-of-range negative values
386
return -ATTOSECONDS_PER_SECOND;
390
//-------------------------------------------------
391
// as_ticks - convert to ticks at the given
393
//-------------------------------------------------
395
inline UINT64 attotime::as_ticks(UINT32 frequency) const
397
UINT32 fracticks = (attotime(0, attoseconds) * frequency).seconds;
398
return mulu_32x32(seconds, frequency) + fracticks;
402
//-------------------------------------------------
403
// from_ticks - create an attotime from a tick
404
// count at the given frequency
405
//-------------------------------------------------
407
inline attotime attotime::from_ticks(UINT64 ticks, UINT32 frequency)
409
attoseconds_t attos_per_tick = HZ_TO_ATTOSECONDS(frequency);
411
if (ticks < frequency)
412
return attotime(0, ticks * attos_per_tick);
415
INT32 secs = divu_64x32_rem(ticks, frequency, &remainder);
416
return attotime(secs, (UINT64)remainder * attos_per_tick);
420
//-------------------------------------------------
421
// from_double - create an attotime from floating
422
// point count of seconds
423
//-------------------------------------------------
425
inline attotime attotime::from_double(double _time)
427
seconds_t secs = floor(_time);
428
_time -= double(secs);
429
attoseconds_t attos = DOUBLE_TO_ATTOSECONDS(_time);
430
return attotime(secs, attos);
434
#endif // __ATTOTIME_H__