PTIMER
PTIMER is a hardware subsystem that implements a 56-bit programmable interval timer with nanosecond-ish accuracy (it counts in nanoseconds, but cannot be nanosecond accurate due to the clock speed) and controllable speed. It is a foundational component of all Nvidia GPUs and, at least for late 1990s and early 2000s GPU designs, has not changed a huge amount (although some new registers have been added) since the NV1. It is required to, among other things, for the graphics hardware to perform activities that involve waiting a defined amount of time, for the drivers to know when to poll for GPU state changes and many more things. All registers of PTIMER are located within the main GPU MMIO area. In order to use the PTIMER correctly, the PTIMER_NUMERATOR
and PTIMER_DENOMINATOR
registers must be programmed to appropriate values. Then, the PTIMER_ALARM
register must be set in order to set when the alarm is reset. Then, each clock cycle, the PTIMER_TIME_0
(bits 31 through 5) and PTIMER_TIME_1
(bits 28 through 0) will update based on the number of nanoseconds that have passed. This will occur at a rate set by the result of the calculation MCLK * PTIMER_NUMERATOR / PTIMER_DENOMINATOR
(where MCLK is the GPU core clock on NV3, and memory clock on NV4 and later). When PTIMER_TIME_1
[1]
is equal to PTIMER_ALARM
, the PTIMER_INTR_ALARM
interrupt will be fired and PTIMER_TIME_1
will be reset to zero (most likely, PTIMER_TIME_0
is incremented at this time). Disabling this interrupt is possible, but extremely unwise: if you are running under nVIDIA's Resource Manager, the drivers will most likely immediately cease to work, since PFIFO cache errors will never be caught, some I2C communication and several other critical events will not happen. Interrupts for the PTIMER subsystem cannot be turned off by using PMC's PMC_INTERRUPT_ENABLE
register, nor can PTIMER be turned off using the global subsystem status in PMC_ENABLE
.
Registers
PTIMER_INTR (Interrupt Status)
- MMIO offset:
0x9100
- Available in: NV1+
- Read/write
Displays the current interrupt state for the PTIMER subsystem.
- Bit 0 -
PTIMER_INTR_ALARM
- If this bit is set, the PTIMER alarm fired. Clear it when the interrupt has been successfully handled.
If bit 0 of PTIMER_INTR_EN
is not set, disregard the value of this register.
PTIMER_INTR_EN (Interrupt Enable)
- MMIO offset:
0x9140
- Available in: NV1+
- Read/write
Allows enabling and disabling interrupts for the PTIMER subsystem. In this case, there is only one interrupt to enable.
- Bit 0 -
PTIMER_INTR_EN_0_ALARM
. Determines if the alarm interrupt is enabled - if this bit is not set, it will not be fired, effectively making this subsystem rather useless.
PTIMER_NUMERATOR (Time Count Speed Numerator)
- MMIO offset:
0x9200
- Available in: NV1+
- Read/write
Bits 15 through 0 of this register contain the numerator of the fractional speed that the PTIMER_TIME_1
register will increment.
PTIMER_DENOMINATOR (Time Count Speed Denominator)
- MMIO offset:
0x9210
- Available in: NV1+
- Read/write
Bits 15 through 0 of this register contain the denominator of the fractional speed that the PTIMER_TIME_1
register will increment. Presumably it is a bad idea to set this to zero (although it seems the PTIMER_TIME_1
just doesn't count when you do)
PTIMER_TIME_0
- MMIO offset:
0x9400
- Available in: NV1+
- Read/write
- Bits 31 through 5 of this register contain the high 27 bits of the PTIMER count register. This increments whenever
PTIMER_TIME_1
rolls over to zero due to overflow.
PTIMER_TIME_1
- MMIO offset:
0x9410
- Available in: NV1+
- Read/write
- Bits 28 through 0 of this register contain the low 29 bits of the PTIMER count register. This increments every clock cycle by an amount equivalent to the result of the computation
MCLK * PTIMER_NUMERATOR / PTIMER_DENOMINATOR
, where MCLK is the aforementioned core GPU clock.
PTIMER_ALARM
- MMIO offset:
0x9420
- Available in: NV1+
- Read/write
- Contain the value that
PTIMER_TIME_1
needs to hold for thePTIMER_INTR_ALARM
interrupt to be triggered. There is no way to trigger an interrupt based on the value ofPTIMER_TIME_0
Notes
^ The value of PTIMER_TIME_0
is not taken into account for the purposes of triggering the alarm interrupt.