Why Learn Hierarchical UPF? In complex SoC designs with hundreds of IP blocks, a monolithic UPF file becomes unmanageable and prevents IP reuse. Hierarchical UPF enables modular power intent specification, allowing design teams to work in parallel and integrate third-party IP blocks seamlessly. In this tutorial, you'll master the strategies and commands for organizing UPF across multiple hierarchy levels in large-scale chip designs.

15 min read | Advanced Level

What You'll Learn

  • Distinguish between top-down and bottom-up UPF specification approaches
  • Use the load_upf command to integrate hierarchical UPF files
  • Apply scope management techniques for hierarchical power domains
  • Organize UPF files for IP reuse and team collaboration

The Hierarchical UPF Challenge

Modern SoC designs integrate hundreds of IP blocks from different sources: in-house developed subsystems, licensed third-party IP, and vendor-supplied blocks. Each subsystem may have complex internal power management with multiple voltage domains, power states, and control strategies.

Consider a mobile application processor integrating:

  • CPU cluster: 12 cores with per-core power gating
  • GPU subsystem: 64 execution units with voltage scaling
  • Video codec: Encoder and decoder with retention
  • AI accelerator: Custom IP with multi-voltage design
  • Memory controller: DDR4/LPDDR5 with power-down modes

Attempting to capture all power intent in a single monolithic UPF file creates serious problems:

  • File sizes exceed 5,000+ lines, becoming unmanageable
  • IP blocks cannot be reused - power intent tied to specific instance names
  • Teams cannot work in parallel - everyone modifies the same file
  • Vendor IP arrives with proprietary UPF that must be manually merged
  • Changes to one subsystem risk breaking others

Hierarchical UPF solves these problems by allowing each subsystem to define its own power intent in separate files, which are then composed at integration using scoping and supply mapping.

Hierarchical UPF in Modern SoCs

Modern smartphone processors use hierarchical UPF extensively. A typical design has 20-30 major IP blocks, each with its own UPF file. The CPU vendor provides a complete UPF specification for their processor cluster. The GPU comes with vendor-supplied UPF. The integration team maintains top-level UPF for interconnect and system-level power management. This modular approach enables concurrent development and reduces integration time from months to weeks.

Top-Down vs. Bottom-Up UPF Approaches

Two fundamental strategies exist for hierarchical UPF organization: top-down specification and bottom-up composition.

Top-Down UPF Specification

In the top-down approach, a single UPF file at the chip's top level defines power intent for all hierarchy levels. The integrator has complete visibility and control over the entire power architecture.


# top_level.upf - Top-down approach
# Define all power domains from top level

# Top-level domain
create_power_domain PD_TOP -include_scope

# CPU subsystem domains (defined from top)
create_power_domain PD_CPU -elements {cpu_subsystem}
create_power_domain PD_CORE0 -elements {cpu_subsystem/core_0}
create_power_domain PD_CORE1 -elements {cpu_subsystem/core_1}
create_power_domain PD_L2 -elements {cpu_subsystem/l2_cache}

# GPU subsystem domains (defined from top)
create_power_domain PD_GPU -elements {gpu_subsystem}
create_power_domain PD_GPU_CORE -elements {gpu_subsystem/gpu_core}
create_power_domain PD_GPU_MEM -elements {gpu_subsystem/gpu_memory}

# Video codec domains (defined from top)
create_power_domain PD_VIDEO -elements {video_codec}
create_power_domain PD_VIDEO_DEC -elements {video_codec/decoder}
create_power_domain PD_VIDEO_ENC -elements {video_codec/encoder}

# All supply networks and power switches defined here
create_supply_net VDD
create_supply_net VDD_CPU
create_supply_net VDD_GPU
# ... hundreds more lines ...

Advantages of Top-Down:

  • Complete visibility of entire power architecture in one place
  • Easier to ensure global consistency across all domains
  • Simpler debugging with single file
  • No scope management complexity

Disadvantages of Top-Down:

  • Monolithic files become unmanageable (thousands of lines)
  • No IP reuse - power intent tied to specific instance names
  • Parallel development blocked - all teams must coordinate edits
  • Changes to one subsystem require modifying entire file
  • Version control conflicts when multiple engineers work simultaneously

Bottom-Up UPF Specification

In the bottom-up approach, each hierarchical block defines its own UPF file with local power intent. These files are loaded and composed at the top level using the load_upf command.


# cpu_subsystem.upf - CPU team's independent UPF file
# Defines power intent relative to cpu_subsystem scope

# Primary power domain (relative to this scope)
create_power_domain PD_CPU -include_scope

# Sub-domains within CPU subsystem
create_power_domain PD_CORE0 -elements {core_0}
create_power_domain PD_CORE1 -elements {core_1}
create_power_domain PD_L2 -elements {l2_cache}

# Supply networks local to CPU subsystem
create_supply_net VDD_CPU
create_supply_net VSS
create_supply_net VDD_CORE0
create_supply_net VDD_CORE1

# Power switches for CPU cores
create_power_switch PSW_CORE0 -domain PD_CORE0 \
  -input_supply_port {vin VDD_CPU} \
  -output_supply_port {vout VDD_CORE0} \
  -control_port {ctrl core0_power_enable} \
  -on_state {on vin {ctrl}}

# ... rest of CPU-specific power intent ...

# gpu_subsystem.upf - GPU team's independent UPF file

create_power_domain PD_GPU -include_scope
create_power_domain PD_GPU_CORE -elements {gpu_core}
create_power_domain PD_GPU_MEM -elements {gpu_memory}

# GPU uses multiple voltage states for DVFS
create_supply_net VDD_GPU
add_power_state VDD_GPU \
  -state {HIGH 1.0} \
  -state {MED 0.9} \
  -state {LOW 0.8} \
  -state {OFF off}

# ... GPU-specific power management ...

# top_level.upf - Top-level integration file
# Loads subsystem UPF files and connects supplies

create_power_domain PD_TOP -include_scope

# Load CPU subsystem UPF into its scope
load_upf cpu_subsystem.upf -scope cpu_subsystem

# Load GPU subsystem UPF into its scope
load_upf gpu_subsystem.upf -scope gpu_subsystem

# Load video codec UPF
load_upf video_codec.upf -scope video_codec

# Define top-level supply networks
create_supply_net VDD -domain PD_TOP
create_supply_net VSS -domain PD_TOP

# Connect top-level supplies to subsystem supplies
set_domain_supply_net PD_TOP -primary_power_net VDD
set_domain_supply_net PD_TOP -primary_ground_net VSS

Advantages of Bottom-Up:

  • Modular organization - each subsystem in separate file
  • IP reuse - UPF files travel with IP blocks
  • Parallel development - teams work independently
  • Easier maintenance - changes localized to affected subsystem
  • Scalable to large SoCs with 100+ blocks
  • Vendor IP integration without manual merging

Disadvantages of Bottom-Up:

  • Scope management complexity
  • Harder to visualize global power architecture
  • Potential naming conflicts between subsystems
  • Debugging requires tracking across multiple files
  • Supply mapping adds integration overhead

Most production SoCs use a hybrid approach: bottom-up for major IP blocks and subsystems, top-down for interconnect and glue logic. This balances modularity with control.

Quick Check

Q: When would you choose top-down UPF over bottom-up?

Show Answer

Top-down UPF is appropriate for small to medium designs (< 1000 lines total UPF) where all blocks are developed in-house by a single team, no IP reuse is planned, and having complete visibility in one file outweighs maintenance concerns. For large SoCs, multi-team projects, or designs using third-party IP, bottom-up or hybrid approaches are strongly preferred.

The load_upf Command

The load_upf command is the foundation of hierarchical UPF, loading a UPF file and applying it within a specified scope.

Syntax


load_upf  \
  -scope  \
  [-supply_map ] \
  [-replace] \
  [-relative]

Parameters

  • filename: Path to UPF file to load
  • -scope: Hierarchical instance to apply UPF to
  • -supply_map: File mapping subsystem supply names to top-level names
  • -replace: Replace existing UPF for this scope (useful for updates)
  • -relative: Interpret paths relative to load location

Basic load_upf Example


# Load CPU subsystem UPF
load_upf cpu_subsystem.upf -scope cpu_subsystem

# Load GPU subsystem UPF with supply mapping
load_upf gpu_subsystem.upf \
  -scope gpu_subsystem \
  -supply_map gpu_supply_map.txt

# Load video codec UPF with replacement
# (useful when updating IP with new power intent)
load_upf video_codec_v2.upf \
  -scope video_codec \
  -replace

Supply Mapping

When a subsystem's internal supply names don't match the top-level supply names, use a supply map file to translate names during load.


# gpu_supply_map.txt - Maps GPU internal names to top-level names
# Format:  

VDD_GPU_INTERNAL     VDD_GPU
VSS_GPU_INTERNAL     VSS
VDD_GPU_CORE_INTERNAL VDD_GPU_CORE
VDD_GPU_MEM_INTERNAL  VDD_GPU_MEM

# top_level.upf
# Apply supply mapping when loading GPU UPF
load_upf gpu_subsystem.upf \
  -scope gpu_subsystem \
  -supply_map gpu_supply_map.txt

# Now GPU's VDD_GPU_INTERNAL references top-level VDD_GPU

Supply mapping is essential for third-party IP blocks that use different naming conventions than your design. It enables integration without modifying the vendor's UPF file, preserving IP integrity and enabling future updates.

Scope Management in Hierarchical UPF

Scope determines the hierarchical context for UPF commands. Proper scope management is critical for hierarchical UPF organization.

set_scope Command


set_scope 

Changes the current scope for subsequent UPF commands. Use . to return to the top level, and .. to move up one level.


# Start at top level
create_power_domain PD_TOP -include_scope

# Create CPU domain
create_power_domain PD_CPU -elements {cpu_subsystem}

# Enter CPU subsystem scope
set_scope cpu_subsystem

# Now in cpu_subsystem scope - create domains relative to here
create_power_domain PD_CORE0 -elements {core_0}
create_power_domain PD_CORE1 -elements {core_1}
create_power_domain PD_L2 -elements {l2_cache}

# Return to top level
set_scope .

# Create GPU domain at top level
create_power_domain PD_GPU -elements {gpu_subsystem}

# Enter GPU scope
set_scope gpu_subsystem

# Create GPU sub-domains
create_power_domain PD_GPU_CORE -elements {gpu_core}
create_power_domain PD_GPU_MEM -elements {gpu_memory}

# Return to top level
set_scope .

Absolute vs. Relative Paths

Hierarchical paths can be absolute (from top) or relative (from current scope).


# Absolute path (from top level, starts with /)
create_power_domain PD_CORE0 -elements {/cpu_subsystem/core_0}

# Relative path (from current scope, no leading /)
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}  # Relative to cpu_subsystem

Best Practice: Subsystem UPF files should use relative paths to enable IP reuse. The same UPF file should work regardless of the instance name at the top level.

Quick Check

Q: If you're in the cpu_cluster/cpu_core_0 scope and execute set_scope .., what scope are you in?

Show Answer

You're in the cpu_cluster scope. The .. moves up one level in the hierarchy, while . returns to the top level.

UPF File Organization Strategies

Several strategies exist for organizing UPF files in hierarchical designs. The choice depends on design size, team structure, and IP reuse requirements.

Strategy 1: One File Per IP Block

Each reusable IP block has its own UPF file that travels with the RTL.

File structure:
ip_blocks/
  cpu_cortex_a78/
    rtl/
    upf/
      cpu_cortex_a78.upf
  gpu_mali_g78/
    rtl/
    upf/
      gpu_mali_g78.upf
  video_codec_h265/
    rtl/
    upf/
      video_codec.upf

soc_top/
  upf/
    top_level.upf
    supply_maps/
      cpu_supply_map.txt
      gpu_supply_map.txt

Advantages: IP portability, clear ownership, easy reuse across projects

Disadvantages: Requires supply mapping for integration

Strategy 2: Hierarchical Layer Files

Separate UPF files for each hierarchy level, with clear naming convention.

upf/
  l0_top.upf              # Top level
  l1_cpu_cluster.upf      # CPU cluster
  l1_gpu_subsystem.upf    # GPU subsystem
  l1_video_codec.upf      # Video codec
  l2_cpu_core.upf         # Individual CPU core
  l2_gpu_core.upf         # GPU core
  l2_gpu_memory.upf       # GPU memory

Advantages: Clear hierarchy visualization, systematic naming

Disadvantages: Less portable for IP reuse

Strategy 3: Functional Separation

Separate UPF files by function: domains, supplies, power management, constraints.

upf/
  domains.upf           # All create_power_domain commands
  supplies.upf          # All supply networks and ports
  power_switches.upf    # All power gating
  level_shifters.upf    # All level shifters
  isolation.upf         # All isolation strategies
  retention.upf         # All retention strategies
  power_states.upf      # All power state definitions

# top_level.upf loads all these files

Advantages: Easy to find specific type of specification, good for debugging

Disadvantages: Doesn't support IP reuse, load order dependencies

Load Order Matters: UPF files must be loaded in dependency order. Domains must exist before you can create supply sets for them. Supplies must exist before you can create power switches. Always load in this order: 1) Domains, 2) Supplies, 3) Power management (switches, level shifters, isolation, retention), 4) Power states.

Complete Hierarchical Organization Example


# top_level.upf - Main integration file for mobile SoC

# Top-level scope
create_power_domain PD_TOP -include_scope

# Load subsystem UPF files with appropriate supply mappings
# CPU cluster (4x Cortex-A78 cores)
load_upf ../ip_blocks/cpu_cortex_a78/upf/cpu_cluster.upf \
  -scope cpu_cluster \
  -supply_map supply_maps/cpu_supply_map.txt

# GPU subsystem (Mali-G78)
load_upf ../ip_blocks/gpu_mali_g78/upf/gpu_subsystem.upf \
  -scope gpu_subsystem \
  -supply_map supply_maps/gpu_supply_map.txt

# Video codec (H.265 encoder/decoder)
load_upf ../ip_blocks/video_codec_h265/upf/video_codec.upf \
  -scope video_codec \
  -supply_map supply_maps/video_supply_map.txt

# AI accelerator (custom IP)
load_upf ../ip_blocks/ai_accelerator/upf/ai_accelerator.upf \
  -scope ai_accel \
  -supply_map supply_maps/ai_supply_map.txt

# Memory subsystem (DDR4 controller + LPDDR5)
load_upf memory_subsystem.upf -scope memory_subsystem

# Interconnect fabric (NoC)
load_upf noc_interconnect.upf -scope noc

# Define top-level supply networks
create_supply_net VDD_SYS     # System supply: 1.8V always-on
create_supply_net VDD_CPU     # CPU supply: 0.8V-1.1V (DVFS)
create_supply_net VDD_GPU     # GPU supply: 0.7V-0.9V (DVFS)
create_supply_net VDD_VIDEO   # Video supply: 0.9V
create_supply_net VDD_AI      # AI accelerator: 0.85V
create_supply_net VDD_MEM     # Memory: 1.1V
create_supply_net VSS         # Ground

# Create supply sets for top level
create_supply_set SS_TOP \
  -function {power VDD_SYS} \
  -function {ground VSS}

associate_supply_set SS_TOP -handle PD_TOP

# Isolation between major subsystems
set_isolation ISO_CPU_TO_NOC -domain cpu_cluster \
  -isolation_supply_set SS_TOP \
  -clamp_value 0 \
  -isolation_signal cpu_iso_enable \
  -location parent

set_isolation ISO_GPU_TO_NOC -domain gpu_subsystem \
  -isolation_supply_set SS_TOP \
  -clamp_value 0 \
  -isolation_signal gpu_iso_enable \
  -location parent

# Level shifters at subsystem boundaries
set_level_shifter LS_CPU_OUTPUTS -domain cpu_cluster \
  -applies_to outputs \
  -location parent

set_level_shifter LS_GPU_OUTPUTS -domain gpu_subsystem \
  -applies_to outputs \
  -location parent

Hierarchical UPF in Production

A recent mobile processor design used hierarchical UPF to integrate IP from four different sources. The CPU vendor provided a 1,200-line UPF file. The GPU vendor provided a 900-line UPF file. The modem team developed their UPF in parallel with RTL. Using bottom-up hierarchical UPF with supply mapping, the integration team loaded all subsystem UPF files without modification. When the CPU vendor released a new revision, the integrator simply replaced the CPU UPF file - no changes to other subsystems. This reduced integration time by 4 months compared to a monolithic UPF approach.

Common Beginner Mistakes

Mistake #1: Incorrect load order


# WRONG: Loading power management before domains exist
load_upf power_switches.upf    # Error: domains don't exist yet
load_upf domains.upf

# CORRECT: Load domains first, then power management
load_upf domains.upf
load_upf supplies.upf
load_upf power_switches.upf

Why? Power switches reference domains and supplies. Those must exist before power switches can be created.

Mistake #2: Using absolute paths in subsystem UPF files


# WRONG: Absolute path in cpu_subsystem.upf (breaks reusability)
create_power_domain PD_CORE0 -elements {/top/cpu_subsystem/core_0}
# This won't work if CPU is instantiated as "cpu_cluster"

# CORRECT: Use relative paths for IP reuse
create_power_domain PD_CORE0 -elements {core_0}
# Works regardless of instance name at top level

Why? Absolute paths hardcode the hierarchy, preventing IP reuse. Relative paths make the UPF portable.

Mistake #3: Forgetting supply mappings


# WRONG: Loading GPU UPF without supply mapping
load_upf gpu_subsystem.upf -scope gpu_subsystem
# Error: GPU's VDD_GPU_INTERNAL doesn't exist at top level

# CORRECT: Provide supply mapping
load_upf gpu_subsystem.upf \
  -scope gpu_subsystem \
  -supply_map gpu_supply_map.txt

Why? Third-party IP uses its own supply naming. Supply mapping translates those names to your top-level supplies.

Mistake #4: Staying in subsystem scope


# WRONG: Not returning to top scope
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
# Still in cpu_subsystem scope!
create_power_domain PD_GPU -elements {gpu_subsystem}  # Error!

# CORRECT: Return to top scope before creating GPU domain
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
set_scope .  # Return to top
create_power_domain PD_GPU -elements {gpu_subsystem}

Why? Scope persists until explicitly changed. Always return to the intended scope level.

Practice Exercise

Challenge: Design Hierarchical UPF Structure

You're integrating a wireless connectivity subsystem into your SoC. The subsystem includes WiFi, Bluetooth, and NFC blocks, each from different vendors with their own UPF files. The subsystem has a shared RF front-end that must remain powered during sleep.

Given:

  • WiFi UPF: wifi_ip.upf (uses VDD_WIFI_INTERNAL, VSS_WIFI_INTERNAL)
  • Bluetooth UPF: bluetooth_ip.upf (uses VDD_BT_INTERNAL, VSS_BT_INTERNAL)
  • NFC UPF: nfc_ip.upf (uses VDD_NFC_INTERNAL, VSS_NFC_INTERNAL)
  • Top-level supplies: VDD_WIRELESS, VDD_RF_ALWAYS_ON, VSS
  • Instance names: wireless_subsystem/wifi, wireless_subsystem/bluetooth, wireless_subsystem/nfc

Task: Create:

  1. A subsystem-level UPF file (wireless_subsystem.upf) that loads the three vendor IP files
  2. Supply mapping files for each IP block
  3. A top-level integration snippet that loads the wireless subsystem
  4. Proper power domain hierarchy and always-on RF domain
Hint 1

Start by creating the three supply mapping files. Each should map the vendor's internal supply names to the wireless subsystem's supply names (VDD_WIRELESS, VSS).

Hint 2

In wireless_subsystem.upf, create a PD_WIRELESS domain with -include_scope, then use load_upf for each vendor IP with appropriate -scope and -supply_map parameters.

Hint 3

Create a separate power domain for the RF front-end (PD_RF) with a single power state (no OFF state) to ensure it's always powered.

Solution

# wifi_supply_map.txt
VDD_WIFI_INTERNAL  VDD_WIRELESS
VSS_WIFI_INTERNAL  VSS

# bluetooth_supply_map.txt
VDD_BT_INTERNAL  VDD_WIRELESS
VSS_BT_INTERNAL  VSS

# nfc_supply_map.txt
VDD_NFC_INTERNAL  VDD_WIRELESS
VSS_NFC_INTERNAL  VSS

# wireless_subsystem.upf - Subsystem integration file

# Primary wireless domain
create_power_domain PD_WIRELESS -include_scope

# Always-on RF front-end domain
create_power_domain PD_RF -elements {rf_frontend}

# Load vendor IP UPF files with supply mapping
load_upf wifi_ip.upf \
  -scope wifi \
  -supply_map wifi_supply_map.txt

load_upf bluetooth_ip.upf \
  -scope bluetooth \
  -supply_map bluetooth_supply_map.txt

load_upf nfc_ip.upf \
  -scope nfc \
  -supply_map nfc_supply_map.txt

# Define wireless subsystem supplies
create_supply_net VDD_WIRELESS
create_supply_net VDD_RF_ALWAYS_ON
create_supply_net VSS

# Supply sets for wireless domain
create_supply_set SS_WIRELESS \
  -function {power VDD_WIRELESS} \
  -function {ground VSS}

associate_supply_set SS_WIRELESS -handle PD_WIRELESS

# Supply set for always-on RF domain
create_supply_set SS_RF_ALWAYS_ON \
  -function {power VDD_RF_ALWAYS_ON} \
  -function {ground VSS}

associate_supply_set SS_RF_ALWAYS_ON -handle PD_RF

# Define power states for RF (always on)
add_power_state VDD_RF_ALWAYS_ON -state {ON 0.9}
# Note: No OFF state - RF is always powered

# Define power states for wireless (can be gated)
add_power_state VDD_WIRELESS \
  -state {ON 1.0} \
  -state {OFF off}

# Power switch for wireless domain (RF stays on)
create_power_switch PSW_WIRELESS -domain PD_WIRELESS \
  -input_supply_port {vin VDD_RF_ALWAYS_ON} \
  -output_supply_port {vout VDD_WIRELESS} \
  -control_port {ctrl wireless_power_enable} \
  -on_state {on vin {ctrl}}

# Isolation for wireless outputs (using always-on supply)
set_isolation ISO_WIRELESS -domain PD_WIRELESS \
  -isolation_supply_set SS_RF_ALWAYS_ON \
  -clamp_value 0 \
  -isolation_signal wireless_iso_enable \
  -location parent

# top_level.upf - Top-level integration snippet

# Load wireless subsystem
load_upf wireless_subsystem.upf \
  -scope wireless_subsystem \
  -supply_map wireless_supply_map.txt

# wireless_supply_map.txt contents:
# VDD_WIRELESS       VDD_WIRELESS_SYS
# VDD_RF_ALWAYS_ON   VDD_RF_SYS
# VSS                VSS

# Level shifters for wireless subsystem outputs
set_level_shifter LS_WIRELESS -domain wireless_subsystem \
  -applies_to outputs \
  -location parent

Key points in solution:

  • Three supply mapping files translate vendor IP supply names to subsystem names
  • Subsystem UPF loads vendor IP files with appropriate scoping
  • RF domain has only ON state (no OFF) to ensure always-on operation
  • Power switch for wireless uses RF supply as input
  • Isolation uses always-on RF supply
  • Top-level loads wireless subsystem with another level of supply mapping

Summary

In this tutorial, you learned:

  • Hierarchical UPF enables modular power intent specification for complex SoCs with hundreds of IP blocks
  • Top-down approach uses single file with complete visibility but poor scalability; bottom-up approach uses modular files enabling IP reuse and parallel development
  • The load_upf command loads subsystem UPF files with scope and supply mapping for integration
  • Scope management with set_scope controls hierarchical context; use relative paths in subsystem UPF for portability
  • File organization strategies include one-per-IP (best for reuse), hierarchical layers (visualization), and functional separation (debugging)
  • Supply mapping translates subsystem supply names to top-level names, enabling third-party IP integration without modification
  • UPF files must be loaded in dependency order: domains, supplies, power management, power states
Did you find what you were looking for?

Quiz

No quiz questions available for this article.