UPF Power States and the Power State Table
Defining legal supply combinations and their strategy
The earlier UPF lesson described the building blocks: domains, supplies, isolation and retention. This lesson is the control layer on top: declaring which supply combinations are legal, naming them as power states, and listing the allowed combinations in a power state table, which is what makes a multi-domain design verifiable instead of a pile of switches.
Power states are built from supply states. Each supply net sits in a small set of states: a real voltage with a value (FULL_ON at, say, 0.9 V), or OFF. A power state of a domain is a named, meaningful combination of those supply states, for example RUN (primary on), SLEEP (primary off but retention supply on), or a low-voltage RUN_LV. Naming them lets tools and reviewers reason about intent instead of raw nets, as in the code below.
# UPF: define supply states, then domain power states
add_power_state VDD_SW -state {ON {-supply_expr {power == FULL_ON}}}
add_power_state VDD_SW -state {OFF {-supply_expr {power == OFF}}}
add_power_state PD_cpu -domain \
-state {RUN {-logic_expr {VDD_SW == ON}}} \
-state {SLEEP {-logic_expr {VDD_SW == OFF && VDD_RET == ON}}}The Power State Table (PST)
A chip has several domains, but not every combination of their states can occur at once. The PST enumerates only the legal system-level combinations: the rows are scenarios (full-on, low-power, deep-sleep), the columns are the supplies, and each cell is the state that supply is in for that scenario. Anything not in the table is illegal by construction, which is exactly what verification and analysis need to bound the problem.
| Scenario | VDD_soc (always-on) | VDD_SW (switched CPU) | VDD_RET (retention) |
|---|---|---|---|
| Active | ON 0.90 V | ON 0.90 V | ON |
| CPU low-V | ON 0.90 V | ON 0.72 V | ON |
| CPU retention | ON 0.90 V | OFF | ON |
| Deep sleep | OFF | OFF | ON |
The PST drives the protection strategy. Any row where one domain is OFF while a domain it drives is ON is exactly where isolation cells are required, so the floating output is clamped to a known value. Any row where a domain goes OFF but must restore its context (the CPU retention row) is where retention registers and a separate retention supply are required. Every downstream tool then consumes the table: verification confirms isolation and level shifters exist on every crossing the PST makes possible and flags missing or redundant cells; implementation inserts those cells to satisfy every legal state, not just the active one; and power analysis treats each row as a distinct scenario so you budget power per state instead of one lumped number.
the senior framing: the PST is the contract for the whole low-power design. It defines the legal states, and isolation, level-shifter, and retention requirements all fall out of reading which domains are on or off together in each row. If you can derive the protection cells from a PST row, you understand UPF, not just its keywords.
the PST must be complete and honest. A real operating mode that is missing from the table will not get its isolation or retention inserted or verified, so the bug ships silently. And every legal voltage in the table is a separate timing and power corner: a low-voltage RUN row still has to be signed off, not assumed safe.