16 min read | Intermediate Level
What You'll Learn
- Understand power gating concepts and when to use power shutoff
- Create power switches using the create_power_switch command
- Define switch control logic and on/off states
- Implement complete power gating strategies for domains
What is Power Shutoff (Power Gating)?
Power shutoff, also called power gating, is a technique that completely disconnects power supply from a circuit block when it's not in use. By turning off the power, you eliminate all leakage current, achieving zero power consumption in the gated domain.
How Power Gating Works
Power switches (also called power gates or header/footer switches) are inserted between the power supply and the domain:
Always-On Supply (VDD)
|
[Power Switch] ← Control Signal (enable/disable)
|
Switched Supply (VDD_SW) → Powers the domain
|
[Domain Logic]
|
Ground (VSS)
When the control signal is asserted, the switch conducts and the domain receives power. When de-asserted, the switch opens and the domain is completely unpowered.
Power switches are physical transistors (typically PMOS header switches or NMOS footer switches) that act as controllable resistors between supply rails. Modern designs use header switches (between VDD and domain) more commonly than footer switches due to better noise immunity.
Power Gating Impact
In a typical mobile SoC, the GPU might be idle 80-90% of the time during normal usage (web browsing, messaging). Without power gating, the GPU would consume 200-300mW of leakage power continuously. With power gating, idle GPU power drops to near-zero, extending battery life by hours. This is why virtually all modern smartphone processors implement aggressive power gating across dozens of domains.
When to Use Power Shutoff
Power gating is beneficial when:
- Long Idle Periods: Domain is inactive for milliseconds or longer
- High Leakage: Domain has significant leakage power (advanced nodes, large blocks)
- Acceptable Wake Latency: Application can tolerate power-up delay (microseconds to milliseconds)
- Frequent Sleep Cycles: Domain cycles between active and idle regularly
Power Gating Overhead
Power gating has costs that must be considered:
| Overhead Type | Impact | Typical Value |
|---|---|---|
| Area | Power switch transistors | 5-15% area overhead |
| Wake Latency | Time to power up domain | 1-100 microseconds |
| Energy | Charging domain capacitance | nJ to µJ per wake event |
| Complexity | Isolation, retention, control | Design/verification effort |
Power gating is worthwhile when idle time exceeds the "break-even point"—the time needed to recover the energy spent powering down and up. For typical designs, break-even is 10-100 microseconds, making power gating effective for idle periods longer than ~100µs.
Quick Check
Q: Why does power gating eliminate leakage but clock gating doesn't?
Show Answer
Clock gating stops the clock to sequential logic, preventing dynamic switching power but leaving the circuit powered (leakage continues). Power gating disconnects the supply voltage entirely, eliminating both dynamic and leakage power. At advanced nodes where leakage dominates (40-50% of total power), power gating is far more effective for idle blocks.
Syntax: create_power_switch
The create_power_switch command defines a power switch in UPF.
Basic Form
create_power_switch switch_name -domain domain_name \
-input_supply_port {port_name supply_net} \
-output_supply_port {port_name supply_net} \
-control_port {port_name signal} \
-on_state {state_name input_port {control_expr}} \
[options]
Key Parameters
- switch_name - Unique identifier for the power switch (required)
- -domain domain_name - Power domain controlled by this switch (required)
- -input_supply_port {name net} - Input connection (always-on supply) (required)
- -output_supply_port {name net} - Output connection (switched supply to domain) (required)
- -control_port {name signal} - Control signal(s) (required, repeatable)
- -on_state {name input {expr}} - Define when switch is ON (required, repeatable)
- -off_state {name {expr}} - Define when switch is OFF (optional)
Usage Variations
1. Basic Power Switch (Single Control):
create_power_switch PSW_GPU -domain PD_GPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_GPU} \
-control_port {ctrl pwr_en_gpu} \
-on_state {on in {ctrl}}
2. Power Switch with Explicit OFF State:
create_power_switch PSW_CPU -domain PD_CPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CPU} \
-control_port {ctrl pwr_en_cpu} \
-on_state {on in {ctrl}} \
-off_state {off {!ctrl}}
3. Multiple Control Signals (AND logic):
create_power_switch PSW_DSP -domain PD_DSP \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_DSP} \
-control_port {en pwr_enable} \
-control_port {ack pwr_ack} \
-on_state {on in {en && ack}}
Creating a Basic Power Switch
Let's create a complete power gating example for a GPU domain.
# ===================================================================
# Power-Gated GPU Domain
# ===================================================================
# Create always-on top domain
create_power_domain PD_TOP -include_scope
# Create GPU domain (will be power-gated)
create_power_domain PD_GPU -elements {gpu_inst}
# Supply nets
create_supply_net VDD -domain PD_TOP # Always-on supply
create_supply_net VSS -domain PD_TOP
create_supply_net VDD_GPU -domain PD_GPU # Switched supply
create_supply_net VSS -domain PD_GPU
# Supply sets
create_supply_set SS_TOP \
-function {power VDD} \
-function {ground VSS}
create_supply_set SS_GPU \
-function {power VDD_GPU} \
-function {ground VSS}
associate_supply_set SS_TOP -handle PD_TOP
associate_supply_set SS_GPU -handle PD_GPU
# Power states
add_power_state VDD -state {ON 1.2}
add_power_state VDD_GPU \
-state {ACTIVE 1.0} \
-state {OFF off}
# Power switch: Controls VDD → VDD_GPU
create_power_switch PSW_GPU -domain PD_GPU \
-input_supply_port {vin VDD} \
-output_supply_port {vout VDD_GPU} \
-control_port {ctrl gpu_power_enable} \
-on_state {on vin {ctrl}}
# ===================================================================
# Result:
# - When gpu_power_enable = 1: Switch ON, VDD → VDD_GPU (GPU powered)
# - When gpu_power_enable = 0: Switch OFF, VDD_GPU disconnected (GPU off)
# ===================================================================
Understanding the Ports
- input_supply_port {vin VDD}: Switch input connected to always-on VDD
- output_supply_port {vout VDD_GPU}: Switch output drives domain supply VDD_GPU
- control_port {ctrl gpu_power_enable}: Control signal from power management controller
The port names (vin, vout, ctrl) are local to the switch definition and don't need to match RTL signal names.
UPF power switches are abstract specifications. Physical design tools map these to actual power switch cells from your technology library during implementation. The UPF describes the logical behavior; the library cells provide the physical transistors.
Control Logic and On/Off States
The -on_state and -off_state options define switch behavior based on control signals.
On-State Definition
The -on_state specifies when the switch conducts:
-on_state {state_name input_port {control_expression}}
- state_name: Descriptive name (e.g., "on", "enabled")
- input_port: Which input port provides power (typically "in" or "vin")
- control_expression: Boolean expression of control signals
Control Expression Examples
# Simple enable (switch on when ctrl = 1)
-on_state {on in {ctrl}}
# Active-low enable (switch on when ctrl_n = 0)
-on_state {on in {!ctrl_n}}
# Two-signal AND (switch on when both high)
-on_state {on in {enable && ready}}
# Two-signal OR (switch on when either high)
-on_state {on in {enable || override}}
# Complex expression
-on_state {on in {enable && !shutdown && (mode1 || mode2)}}
Off-State Definition
The -off_state is optional and typically defined as the complement of on-state:
create_power_switch PSW_CPU -domain PD_CPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CPU} \
-control_port {ctrl pwr_en} \
-on_state {on in {ctrl}} \
-off_state {off {!ctrl}}
If you only define -on_state, the off state is implicitly the negation of all on-states. Explicitly defining -off_state improves clarity and helps tools verify correct behavior.
Quick Check
Q: What happens to VDD_GPU when the power switch is OFF?
Show Answer
When the switch is OFF, VDD_GPU is disconnected from VDD and floats to an undefined voltage (eventually decaying to ground through leakage). All logic in the GPU domain loses power, flip-flops lose state, and outputs go to unknown ('X' in simulation). This is why isolation cells are required at domain outputs to prevent X-propagation to always-on logic.
Multiple Control Signals
Complex power control may require multiple signals with AND/OR logic.
AND Logic (All Signals Required)
# Power switch requires both enable AND acknowledgment
create_power_switch PSW_MODEM -domain PD_MODEM \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_MODEM} \
-control_port {en power_enable} \
-control_port {ack power_ready} \
-on_state {on in {en && ack}}
This implements a handshake protocol: power management controller asserts power_enable, hardware responds with power_ready, and switch turns on only when both are high.
OR Logic (Any Signal Sufficient)
# Power switch enabled by software OR hardware override
create_power_switch PSW_PERIPH -domain PD_PERIPH \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_PERIPH} \
-control_port {sw sw_enable} \
-control_port {hw hw_override} \
-on_state {on in {sw || hw}}
This allows either software control or hardware emergency override to power on the domain.
Handshake Power Control
Modern SoCs use handshake protocols for safe power gating: (1) Software requests power-down via enable signal, (2) Hardware saves critical state and asserts acknowledgment, (3) Power switch turns off only after acknowledgment, (4) Reverse process for power-up with acknowledgment confirming stable supply before releasing reset. This prevents data corruption and ensures clean transitions.
Header vs Footer Switches
Power switches can be placed in two locations:
Header Switch (High-Side)
VDD (Always-On)
|
[Header Switch] ← PMOS transistor, control = enable
|
VDD_SW (Switched)
|
[Domain Logic]
|
VSS (Ground)
# Header switch (most common)
create_power_switch PSW_HEADER -domain PD_CPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CPU} \
-control_port {ctrl enable} \
-on_state {on in {ctrl}}
Footer Switch (Low-Side)
VDD (Power)
|
[Domain Logic]
|
VSS_SW (Switched)
|
[Footer Switch] ← NMOS transistor, control = enable
|
VSS (Always-On Ground)
# Footer switch
create_power_switch PSW_FOOTER -domain PD_GPU \
-input_supply_port {in VSS} \
-output_supply_port {out VSS_GPU} \
-control_port {ctrl enable} \
-on_state {on in {ctrl}}
Header vs Footer Comparison
| Aspect | Header Switch | Footer Switch |
|---|---|---|
| Location | Between VDD and domain | Between domain and VSS |
| Transistor | PMOS (better for high-side) | NMOS (better for low-side) |
| Noise Immunity | Better (stable ground) | Lower (bouncing ground) |
| Usage | More common in modern designs | Used for specific cases |
Most modern designs use header switches because a stable ground reference (VSS) improves noise immunity and reduces ground bounce. Footer switches create a "virtual ground" that can bounce during switching, potentially causing glitches in adjacent logic.
Coarse vs Fine-Grained Power Gating
Power gating can be applied at different granularities.
Coarse-Grained (Block-Level)
# Gate entire GPU as one domain
create_power_domain PD_GPU -elements {gpu_subsystem}
create_power_switch PSW_GPU -domain PD_GPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_GPU} \
-control_port {ctrl gpu_enable} \
-on_state {on in {ctrl}}
Benefits: Simple control, low overhead
Drawbacks: All-or-nothing (can't gate parts independently)
Fine-Grained (Per-Core, Per-Unit)
# Gate each GPU shader core independently
create_power_domain PD_GPU_CORE0 -elements {gpu_subsystem/core_0}
create_power_domain PD_GPU_CORE1 -elements {gpu_subsystem/core_1}
create_power_domain PD_GPU_CORE2 -elements {gpu_subsystem/core_2}
create_power_domain PD_GPU_CORE3 -elements {gpu_subsystem/core_3}
create_power_switch PSW_CORE0 -domain PD_GPU_CORE0 ...
create_power_switch PSW_CORE1 -domain PD_GPU_CORE1 ...
create_power_switch PSW_CORE2 -domain PD_GPU_CORE2 ...
create_power_switch PSW_CORE3 -domain PD_GPU_CORE3 ...
Benefits: Maximum power savings (gate individual units)
Drawbacks: Higher control complexity, more switches, more area
Choose granularity based on usage patterns. If cores are typically all-on or all-off together, coarse-grained gating suffices. If workloads use variable core counts (1 core for light tasks, 4 for heavy), fine-grained gating enables better power scaling.
Complete Power Gating Example
# ===================================================================
# Complete Power Gating Implementation
# ===================================================================
# TOP DOMAIN: Always-on
create_power_domain PD_TOP -include_scope
create_supply_net VDD -domain PD_TOP
create_supply_net VSS -domain PD_TOP
create_supply_set SS_TOP \
-function {power VDD} \
-function {ground VSS}
associate_supply_set SS_TOP -handle PD_TOP
add_power_state VDD -state {ON 1.2}
add_power_state VSS -state {ON 0.0}
# CPU DOMAIN: Power-gated with retention
create_power_domain PD_CPU -elements {cpu_subsystem}
create_supply_net VDD_CPU -domain PD_CPU
create_supply_net VDD_CPU_RET -domain PD_CPU
create_supply_net VSS -domain PD_CPU
create_supply_set SS_CPU_ACTIVE \
-function {power VDD_CPU} \
-function {ground VSS}
create_supply_set SS_CPU_RET \
-function {power VDD_CPU_RET} \
-function {ground VSS}
associate_supply_set SS_CPU_ACTIVE -handle PD_CPU
add_power_state VDD_CPU \
-state {ACTIVE 1.0} \
-state {OFF off}
add_power_state VDD_CPU_RET \
-state {RETENTION 0.6}
# CPU power switch with handshake control
create_power_switch PSW_CPU -domain PD_CPU \
-input_supply_port {vin VDD} \
-output_supply_port {vout VDD_CPU} \
-control_port {enable cpu_pwr_enable} \
-control_port {ack cpu_pwr_ack} \
-on_state {on vin {enable && ack}} \
-off_state {off {!enable || !ack}}
# GPU DOMAIN: Power-gated (no retention)
create_power_domain PD_GPU -elements {gpu_subsystem}
create_supply_net VDD_GPU -domain PD_GPU
create_supply_net VSS -domain PD_GPU
create_supply_set SS_GPU \
-function {power VDD_GPU} \
-function {ground VSS}
associate_supply_set SS_GPU -handle PD_GPU
add_power_state VDD_GPU \
-state {ACTIVE 0.9} \
-state {OFF off}
# GPU power switch with simple enable control
create_power_switch PSW_GPU -domain PD_GPU \
-input_supply_port {vin VDD} \
-output_supply_port {vout VDD_GPU} \
-control_port {ctrl gpu_pwr_enable} \
-on_state {on vin {ctrl}} \
-off_state {off {!ctrl}}
# ===================================================================
# Power Management Sequence (CPU with retention):
# 1. Power Down:
# - Assert cpu_retention_enable (switch FFs to VDD_CPU_RET)
# - De-assert cpu_pwr_enable
# - Wait for cpu_pwr_ack to drop
# - VDD_CPU turns OFF (PSW_CPU opens)
# - Retention cells maintain state using VDD_CPU_RET
# 2. Power Up:
# - Assert cpu_pwr_enable
# - Wait for cpu_pwr_ack (VDD_CPU stable)
# - De-assert cpu_retention_enable (switch FFs back to VDD_CPU)
# - Release reset, resume execution
# ===================================================================
Common Beginner Mistakes
Mistake #1: Creating power switch without defining supply states
# WRONG: Power states not defined
create_power_switch PSW_GPU -domain PD_GPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_GPU} \
-control_port {ctrl enable} \
-on_state {on in {ctrl}}
# CORRECT: Define states before switch
add_power_state VDD -state {ON 1.2}
add_power_state VDD_GPU -state {ACTIVE 0.9} -state {OFF off}
create_power_switch PSW_GPU -domain PD_GPU ...
Why? Power switches control state transitions. The supply nets must have defined states (ACTIVE and OFF) before creating the switch that controls those transitions.
Mistake #2: Using same net for input and output
# WRONG: Input and output both VDD
create_power_switch PSW_CPU -domain PD_CPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD} \ # Should be VDD_CPU
-control_port {ctrl enable} \
-on_state {on in {ctrl}}
# CORRECT: Separate input (always-on) and output (switched)
create_power_switch PSW_CPU -domain PD_CPU \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CPU} \
-control_port {ctrl enable} \
-on_state {on in {ctrl}}
Why? The switch connects two different nets: input from always-on supply (VDD), output to switched domain supply (VDD_CPU). Using the same net for both defeats the purpose of power gating.
Mistake #3: Forgetting isolation for power-gated domains
Problem: Creating power switch without isolation strategy causes X-propagation when domain is off.
Solution: Always pair power switches with isolation strategies (covered in next article). Isolation cells prevent unknowns from powered-off domains reaching always-on logic.
Practice Exercise
Challenge: Implement Power Gating for Multi-Core CPU
Create UPF for a 4-core CPU with per-core power gating:
- PD_TOP: Always-on (VDD = 1.2V)
- PD_CORE0-3: Individual cores, power-gatable (VDD_CORE0-3 = 1.0V active, OFF when gated)
- Each core has independent enable control:
core0_enable,core1_enable, etc.
Write the complete UPF including domains, supplies, states, and switches.
Hint
You'll need 5 domains (PD_TOP + 4 cores), 6 supply nets (VDD + VSS + VDD_CORE0-3), and 4 power switches. Each switch uses independent enable signal. Remember to define power states before creating switches.
Solution
# ===================================================================
# Per-Core Power Gating for Quad-Core CPU
# ===================================================================
# TOP DOMAIN: Always-on
create_power_domain PD_TOP -include_scope
create_supply_net VDD -domain PD_TOP
create_supply_net VSS -domain PD_TOP
create_supply_set SS_TOP \
-function {power VDD} \
-function {ground VSS}
associate_supply_set SS_TOP -handle PD_TOP
add_power_state VDD -state {ON 1.2}
add_power_state VSS -state {ON 0.0}
# CORE 0 DOMAIN
create_power_domain PD_CORE0 -elements {cpu_cluster/core_0}
create_supply_net VDD_CORE0 -domain PD_CORE0
create_supply_net VSS -domain PD_CORE0
create_supply_set SS_CORE0 \
-function {power VDD_CORE0} \
-function {ground VSS}
associate_supply_set SS_CORE0 -handle PD_CORE0
add_power_state VDD_CORE0 \
-state {ACTIVE 1.0} \
-state {OFF off}
create_power_switch PSW_CORE0 -domain PD_CORE0 \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CORE0} \
-control_port {ctrl core0_enable} \
-on_state {on in {ctrl}}
# CORE 1 DOMAIN
create_power_domain PD_CORE1 -elements {cpu_cluster/core_1}
create_supply_net VDD_CORE1 -domain PD_CORE1
create_supply_net VSS -domain PD_CORE1
create_supply_set SS_CORE1 \
-function {power VDD_CORE1} \
-function {ground VSS}
associate_supply_set SS_CORE1 -handle PD_CORE1
add_power_state VDD_CORE1 \
-state {ACTIVE 1.0} \
-state {OFF off}
create_power_switch PSW_CORE1 -domain PD_CORE1 \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CORE1} \
-control_port {ctrl core1_enable} \
-on_state {on in {ctrl}}
# CORE 2 DOMAIN
create_power_domain PD_CORE2 -elements {cpu_cluster/core_2}
create_supply_net VDD_CORE2 -domain PD_CORE2
create_supply_net VSS -domain PD_CORE2
create_supply_set SS_CORE2 \
-function {power VDD_CORE2} \
-function {ground VSS}
associate_supply_set SS_CORE2 -handle PD_CORE2
add_power_state VDD_CORE2 \
-state {ACTIVE 1.0} \
-state {OFF off}
create_power_switch PSW_CORE2 -domain PD_CORE2 \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CORE2} \
-control_port {ctrl core2_enable} \
-on_state {on in {ctrl}}
# CORE 3 DOMAIN
create_power_domain PD_CORE3 -elements {cpu_cluster/core_3}
create_supply_net VDD_CORE3 -domain PD_CORE3
create_supply_net VSS -domain PD_CORE3
create_supply_set SS_CORE3 \
-function {power VDD_CORE3} \
-function {ground VSS}
associate_supply_set SS_CORE3 -handle PD_CORE3
add_power_state VDD_CORE3 \
-state {ACTIVE 1.0} \
-state {OFF off}
create_power_switch PSW_CORE3 -domain PD_CORE3 \
-input_supply_port {in VDD} \
-output_supply_port {out VDD_CORE3} \
-control_port {ctrl core3_enable} \
-on_state {on in {ctrl}}
# ===================================================================
# Usage Scenarios:
# - Single-threaded workload: Only core0_enable = 1 (other cores gated)
# - Dual-threaded: core0_enable and core1_enable = 1
# - Quad-threaded: All enables = 1 (maximum performance)
# - Idle: All enables = 0 (all cores gated, minimum power)
# ===================================================================
Summary
In this tutorial, you learned:
- Power shutoff (gating) eliminates leakage by disconnecting supply voltage, achieving near-zero power in idle domains
create_power_switchdefines switches with input (always-on), output (switched), and control ports-on_statespecifies control logic (boolean expressions) determining when switches conduct- Power gating overhead includes area (5-15%), wake latency (1-100µs), and design complexity, worthwhile for idle times >100µs
- Header switches (high-side, PMOS) are preferred over footer switches for better noise immunity
- Granularity choice (coarse vs fine-grained) depends on usage patterns and power/area tradeoffs