mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
clock: Add clock_ns_to_ticks() function
Add a clock_ns_to_ticks() function which does the opposite of clock_ticks_to_ns(): given a duration in nanoseconds, it returns the number of clock ticks that would happen in that time. This is useful for devices that have a free running counter register whose value can be calculated when it is read. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Luc Michel <luc@lmichel.fr> Reviewed-by: Hao Wu <wuhaotsh@google.com> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-id: 20210219144617.4782-4-peter.maydell@linaro.org
This commit is contained in:
parent
e4341623a3
commit
cd3a53b727
2 changed files with 53 additions and 0 deletions
|
@ -360,6 +360,18 @@ rather than simply passing it to a QEMUTimer function like
|
||||||
``timer_mod_ns()`` then you should be careful to avoid overflow
|
``timer_mod_ns()`` then you should be careful to avoid overflow
|
||||||
in those calculations, of course.)
|
in those calculations, of course.)
|
||||||
|
|
||||||
|
Obtaining tick counts
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
For calculations where you need to know the number of ticks in
|
||||||
|
a given duration, use ``clock_ns_to_ticks()``. This function handles
|
||||||
|
possible non-whole-number-of-nanoseconds periods and avoids
|
||||||
|
potential rounding errors. It will return '0' if the clock is stopped
|
||||||
|
(i.e. it has period zero). If the inputs imply a tick count that
|
||||||
|
overflows a 64-bit value (a very long duration for a clock with a
|
||||||
|
very short period) the output value is truncated, so effectively
|
||||||
|
the 64-bit output wraps around.
|
||||||
|
|
||||||
Changing a clock period
|
Changing a clock period
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,47 @@ static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks)
|
||||||
return ns_low >> 32 | ns_high << 32;
|
return ns_low >> 32 | ns_high << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clock_ns_to_ticks:
|
||||||
|
* @clk: the clock to query
|
||||||
|
* @ns: duration in nanoseconds
|
||||||
|
*
|
||||||
|
* Returns the number of ticks this clock would make in the given
|
||||||
|
* number of nanoseconds. Because a clock can have a period which
|
||||||
|
* is not a whole number of nanoseconds, it is important to use this
|
||||||
|
* function rather than attempting to obtain a "period in nanoseconds"
|
||||||
|
* value and then dividing the duration by that value.
|
||||||
|
*
|
||||||
|
* If the clock is stopped (ie it has period zero), returns 0.
|
||||||
|
*
|
||||||
|
* For some inputs the result could overflow a 64-bit value (because
|
||||||
|
* the clock's period is short and the duration is long). In these
|
||||||
|
* cases we truncate the result to a 64-bit value. This is on the
|
||||||
|
* assumption that generally the result is going to be used to report
|
||||||
|
* a 32-bit or 64-bit guest register value, so wrapping either cannot
|
||||||
|
* happen or is the desired behaviour.
|
||||||
|
*/
|
||||||
|
static inline uint64_t clock_ns_to_ticks(const Clock *clk, uint64_t ns)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* ticks = duration_in_ns / period_in_ns
|
||||||
|
* = ns / (period / 2^32)
|
||||||
|
* = (ns * 2^32) / period
|
||||||
|
* The hi, lo inputs to divu128() are (ns << 32) as a 128 bit value.
|
||||||
|
*/
|
||||||
|
uint64_t lo = ns << 32;
|
||||||
|
uint64_t hi = ns >> 32;
|
||||||
|
if (clk->period == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Ignore divu128() return value as we've caught div-by-zero and don't
|
||||||
|
* need different behaviour for overflow.
|
||||||
|
*/
|
||||||
|
divu128(&lo, &hi, clk->period);
|
||||||
|
return lo;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clock_is_enabled:
|
* clock_is_enabled:
|
||||||
* @clk: a clock
|
* @clk: a clock
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue