Why Learn Power Domains? Power domains are the foundation of UPF-based power management, defining which parts of your design can be independently controlled for voltage scaling, power gating, or frequency management. Understanding how to create and organize power domains is essential for implementing effective low-power strategies in modern SoC designs. In this tutorial, you'll master power domain creation, hierarchy, and boundaries.

14 min read | Intermediate Level

What You'll Learn

  • Understand what power domains are and why they're fundamental to UPF
  • Create power domains using the create_power_domain command
  • Work with hierarchical power domain structures
  • Define power domain boundaries and element membership

What is a Power Domain?

A power domain is a collection of design elements (modules, instances, logic) that share common power management characteristics. All elements within a power domain:

  • Receive power from the same supply network
  • Operate at the same voltage level
  • Can be controlled together (powered on/off, voltage scaled)
  • Share the same power state behavior

Power domains are the fundamental building blocks of UPF. Every design element must belong to exactly one power domain, and all power management strategies (isolation, retention, level shifting) are defined relative to power domain boundaries.

Think of power domains as "power management zones" in your chip. Just as a building has different lighting zones that can be controlled independently, a chip has power domains that can be managed separately to optimize power consumption.

Power Domains in Mobile SoCs

A typical smartphone processor contains 20-30 power domains: CPU cores (each core is a separate domain), GPU shader units, display controller, camera ISP, modem baseband, and always-on sensor hub. Each domain can be independently powered off when idle, enabling significant battery savings during typical usage scenarios.

Syntax: create_power_domain

The create_power_domain command is the primary UPF command for defining power domains.

Basic Form


create_power_domain domain_name [options]

Common Parameters

  • domain_name - Unique identifier for the power domain (required)
  • -elements {list} - Design instances belonging to this domain
  • -include_scope - Include all hierarchy under current scope
  • -scope instance_name - Set scope to specific instance before creating domain
  • -supply {supply_set} - Associate supply set with domain

Usage Variations

1. Top-Level Domain (Primary Domain):


create_power_domain PD_TOP -include_scope

2. Domain for Specific Elements:


create_power_domain PD_CPU -elements {cpu_inst}

3. Domain with Multiple Elements:


create_power_domain PD_PERIPH -elements {uart_inst spi_inst i2c_inst}

4. Hierarchical Domain with Scope:


set_scope subsystem_inst
create_power_domain PD_SUB -include_scope
set_scope .

The Primary Power Domain

Every UPF specification must have a primary power domain, typically the top-level domain that encompasses the entire design hierarchy.


# Create primary power domain at top level
create_power_domain PD_TOP -include_scope

The -include_scope option means "include all design elements in the current hierarchical scope." When used at the top level, this creates a domain containing everything in the design.

Why the Primary Domain Matters

  • Default Membership: Elements not explicitly assigned to another domain belong to the primary domain
  • Always-On Logic: Often represents the always-on portion of the chip
  • Reference Point: Other domains are defined relative to the primary domain
  • Supply Anchor: Primary supplies (VDD, VSS) are typically defined here

Convention: Name the primary domain PD_TOP, PD_CHIP, or PD_DEFAULT to clearly indicate it's the top-level domain.

Quick Check

Q: What happens to design elements that aren't explicitly assigned to a power domain?

Show Answer

Design elements not explicitly assigned to a power domain automatically belong to the primary power domain (the one created with -include_scope at the top level). This ensures every element has power management coverage.

Creating Power Domains for Design Elements

After creating the primary domain, define additional domains for blocks requiring independent power control.

Single-Element Domain


# CPU block operates at different voltage, can be power-gated
create_power_domain PD_CPU -elements {cpu_subsystem}

# GPU block can be shut off independently
create_power_domain PD_GPU -elements {gpu_subsystem}

This removes cpu_subsystem and gpu_subsystem from PD_TOP and places them in their own domains.

Multi-Element Domain

Group multiple instances into one domain if they share power characteristics:


# All peripheral blocks share 1.8V supply, can be gated together
create_power_domain PD_PERIPH -elements {
  uart_inst
  spi_inst
  i2c_inst
  gpio_inst
}

Wildcard Patterns

Use wildcards to include multiple instances matching a pattern:


# All CPU cores (cpu_core_0, cpu_core_1, cpu_core_2, cpu_core_3)
create_power_domain PD_CORES -elements {cpu_core_*}

# All memory banks
create_power_domain PD_MEM -elements {mem_bank[*]}

Wildcard patterns are tool-dependent. Some tools support * and [*], while others have limited pattern matching. Check your EDA tool documentation for supported syntax.

Hierarchical Power Domains

Complex designs require hierarchical power domain structures where domains contain sub-domains.

Why Hierarchical Domains?

  • Modularity: Define power intent at IP block level, compose at SoC level
  • IP Reuse: Reusable blocks bring their own power domain definitions
  • Fine-Grained Control: Sub-domains enable more granular power management
  • Scalability: Manage complexity of large SoCs with 20+ domains

Example: Hierarchical CPU Subsystem


# Top-level primary domain
create_power_domain PD_TOP -include_scope

# CPU subsystem domain
create_power_domain PD_CPU -elements {cpu_subsystem}

# GPU subsystem domain
create_power_domain PD_GPU -elements {gpu_subsystem}

# Within CPU subsystem, define per-core domains
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
create_power_domain PD_CORE1 -elements {core_1}
create_power_domain PD_CORE2 -elements {core_2}
create_power_domain PD_CORE3 -elements {core_3}
create_power_domain PD_L2CACHE -elements {l2_cache}
set_scope .  ;# "." returns scope to the design root/top level

This creates a hierarchy:

PD_TOP (chip level)
├── PD_CPU (CPU subsystem)
│   ├── PD_CORE0 (individual core)
│   ├── PD_CORE1 (individual core)
│   ├── PD_CORE2 (individual core)
│   ├── PD_CORE3 (individual core)
│   └── PD_L2CACHE (shared cache)
├── PD_GPU (GPU subsystem)
└── [other top-level blocks]

Per-Core Power Gating

Modern processors implement per-core power gating to save power during low-utilization workloads. When a CPU core is idle, it can be completely powered off while other cores continue running. Hierarchical UPF domains enable this fine-grained control: each core is a separate domain within the CPU subsystem domain, allowing independent on/off control.

Scope Management

The set_scope command navigates hierarchy when creating domains:


# Method 1: Use set_scope to navigate
set_scope top/subsystem_a
create_power_domain PD_SUBA -include_scope
set_scope ..

# Method 2: Use -scope option
create_power_domain PD_SUBB -scope top/subsystem_b -include_scope

# Method 3: Fully qualified element paths
create_power_domain PD_SUBC -elements {top/subsystem_c}

Always return to the top scope with set_scope . after creating hierarchical domains to avoid accidentally creating domains in the wrong scope.

Power Domain Boundaries

A power domain boundary is the interface between two different power domains. Signals crossing boundaries require special handling.

Identifying Boundaries

Boundaries exist where:

  • Signals cross from one power domain to another
  • Different voltage levels meet (multi-voltage design)
  • A gated domain interfaces with always-on logic

# Two domains with boundary between them
create_power_domain PD_TOP -include_scope
create_power_domain PD_MOTOR -elements {motor_ctrl}

# Signals crossing from motor_ctrl to top-level logic
# cross the PD_MOTOR → PD_TOP boundary

Why Boundaries Matter

Power domain boundaries determine where UPF inserts special cells:

  • Isolation Cells: Prevent unknown values when domain is powered off
  • Level Shifters: Translate voltage levels in multi-voltage designs
  • Retention Cells: May be needed at boundary to preserve interface state

These strategies are covered in later modules, but understanding that boundaries are defined by domain membership is crucial.

Quick Check

Q: If a signal goes from cpu_inst (in PD_CPU) to mem_ctrl (in PD_TOP), where is the power domain boundary?

Show Answer

The boundary is at the output of cpu_inst (or input of mem_ctrl). The signal crosses from PD_CPU domain to PD_TOP domain at this interface. UPF strategies will be applied at this boundary, such as isolation cells if PD_CPU can be powered off.

Practical Example: Multi-Domain SoC

Let's create a sample power domain structure for a simple SoC:


# ===================================================================
# Power Domain Definition for Example SoC
# ===================================================================
# Architecture:
#   - Always-on top-level domain (1.2V)
#   - CPU subsystem (1.0V, can be power-gated)
#   - GPU subsystem (0.9V, can be power-gated)
#   - Peripherals (1.8V, always-on)
#   - Memory controller (1.2V, always-on, same as top)
# ===================================================================

# Primary domain: Always-on, 1.2V
create_power_domain PD_TOP -include_scope

# CPU subsystem: 1.0V, power-gatable
create_power_domain PD_CPU -elements {cpu_subsystem}

# GPU subsystem: 0.9V, power-gatable
create_power_domain PD_GPU -elements {gpu_subsystem}

# Peripheral domain: 1.8V, always-on
create_power_domain PD_PERIPH -elements {
  uart_inst
  spi_inst
  i2c_inst
}

# Memory controller stays in PD_TOP (same voltage)
# No separate domain needed - it's implicitly in PD_TOP

# ===================================================================
# Result:
# - 4 power domains defined
# - PD_TOP contains: memory_ctrl and any other unassigned logic
# - Each domain will later be associated with appropriate supply nets
# ===================================================================

This structure enables:

  • CPU can be gated when system is idle
  • GPU can be gated when no graphics workload
  • Peripherals always available (1.8V for I/O compatibility)
  • Memory controller always-on with same voltage as top

SoC Power Domain Planning

During SoC architecture phase, power architects analyze functional blocks to determine domain boundaries. Criteria include: independent operational modes (can this block be off while others run?), voltage requirements (does this block need different V_dd?), and power/performance tradeoffs (is the gating overhead worth the leakage savings?). These decisions directly map to create_power_domain commands.

Element Membership Rules

Understanding how UPF assigns elements to domains prevents common errors.

Rule 1: Exclusive Membership

Each design element belongs to exactly one power domain.


# CORRECT: cpu_inst is in PD_CPU
create_power_domain PD_CPU -elements {cpu_inst}

# ERROR: Can't assign cpu_inst to two domains
create_power_domain PD_ANOTHER -elements {cpu_inst}  # Will fail or override

Rule 2: Hierarchical Override

More specific domain assignments override less specific ones:


# PD_TOP includes everything
create_power_domain PD_TOP -include_scope

# PD_CPU removes cpu_subsystem from PD_TOP
create_power_domain PD_CPU -elements {cpu_subsystem}

# Within cpu_subsystem, PD_CORE0 removes core_0 from PD_CPU
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
set_scope .

# Result:
# - core_0 is in PD_CORE0 (most specific)
# - Other parts of cpu_subsystem are in PD_CPU
# - Everything else is in PD_TOP

Rule 3: Include Scope vs Elements

-include_scope includes all hierarchy at current scope, while -elements specifies explicit instances.


# This includes cpu_subsystem AND all its sub-instances
create_power_domain PD_CPU -elements {cpu_subsystem}

# This would only include logic directly in current scope, not sub-instances
# (Rarely used; -include_scope is more common for hierarchical inclusion)
create_power_domain PD_FLAT -include_scope

Common Beginner Mistakes

Mistake #1: Forgetting to create the primary domain

Problem: Creating child domains without a top-level primary domain causes errors or unexpected behavior.


# WRONG: No primary domain
create_power_domain PD_CPU -elements {cpu_inst}

# CORRECT: Always create primary domain first
create_power_domain PD_TOP -include_scope
create_power_domain PD_CPU -elements {cpu_inst}

Mistake #2: Using -include_scope for child domains incorrectly

Problem: Using -include_scope without setting scope can include unintended hierarchy.


# WRONG: This tries to include everything at top level
create_power_domain PD_CPU -include_scope  # Ambiguous or error

# CORRECT: Either use -elements or set_scope first
create_power_domain PD_CPU -elements {cpu_subsystem}
# OR
set_scope cpu_subsystem
create_power_domain PD_CPU -include_scope
set_scope .

Mistake #3: Creating domains in wrong hierarchical order

Problem: Creating child domain before parent can cause errors or inconsistent hierarchy.


# WRONG ORDER: Child before parent
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
set_scope .
create_power_domain PD_CPU -elements {cpu_subsystem}  # May override PD_CORE0

# CORRECT ORDER: Parent before children
create_power_domain PD_TOP -include_scope
create_power_domain PD_CPU -elements {cpu_subsystem}
set_scope cpu_subsystem
create_power_domain PD_CORE0 -elements {core_0}
set_scope .

Practice Exercise

Challenge: Create Power Domains for an SoC

Given the following SoC structure, write UPF commands to create appropriate power domains:

top
├── always_on_ctrl       (must stay powered, 1.2V)
├── cpu_cluster          (can be gated, 1.0V)
│   ├── cpu_core0        (individual core, can be gated independently)
│   ├── cpu_core1        (individual core, can be gated independently)
│   └── shared_l2        (shared cache, gated with cluster)
├── dsp_engine           (can be gated independently, 0.9V)
└── io_subsystem         (always-on for wake capability, 1.8V)

Requirements:

  • Create appropriate power domains for each block
  • Enable per-core CPU power gating
  • Ensure always_on_ctrl and io_subsystem remain powered
Hint

You'll need 7 domains total: 1 primary (PD_TOP), 1 for CPU cluster (PD_CPU_CLUSTER), 2 for individual cores (PD_CORE0/1), 1 for L2 cache (PD_L2), 1 for DSP (PD_DSP), and 1 for I/O (PD_IO). Remember to use set_scope for hierarchical domains.

Solution

# ===================================================================
# Power Domain Definition for SoC Exercise
# ===================================================================

# Primary domain: Contains always_on_ctrl and any unassigned logic
create_power_domain PD_TOP -include_scope

# I/O subsystem: Always-on, 1.8V (separate domain for different voltage)
create_power_domain PD_IO -elements {io_subsystem}

# DSP engine: Power-gatable, 0.9V
create_power_domain PD_DSP -elements {dsp_engine}

# CPU cluster: Power-gatable as a whole, 1.0V
create_power_domain PD_CPU_CLUSTER -elements {cpu_cluster}

# Within CPU cluster, create per-core domains for fine-grained gating
set_scope cpu_cluster

# Individual CPU cores - can be gated independently
create_power_domain PD_CORE0 -elements {cpu_core0}
create_power_domain PD_CORE1 -elements {cpu_core1}

# L2 cache - separate domain (could be kept on while cores sleep)
create_power_domain PD_L2 -elements {shared_l2}

# Return to top scope
set_scope .

# ===================================================================
# Result: 7 power domains
# - PD_TOP: always_on_ctrl (always powered, 1.2V)
# - PD_IO: io_subsystem (always powered, 1.8V for I/O)
# - PD_DSP: dsp_engine (gatable, 0.9V)
# - PD_CPU_CLUSTER: (parent domain, can gate entire cluster)
#   - PD_CORE0: cpu_core0 (fine-grained per-core gating)
#   - PD_CORE1: cpu_core1 (fine-grained per-core gating)
#   - PD_L2: shared_l2 (can be controlled separately from cores)
# ===================================================================

Design Rationale:

  • PD_TOP: Always-on control logic must never lose power
  • PD_IO: Separate domain for wake capability and 1.8V I/O voltage
  • PD_DSP: Independent gating when DSP not needed
  • PD_CORE0/1: Per-core gating maximizes power savings during low utilization
  • PD_L2: Separate L2 allows keeping cache powered while cores sleep (faster wake-up)

Summary

In this tutorial, you learned:

  • Power domains are collections of design elements sharing common power management characteristics (supply, voltage, control)
  • create_power_domain defines domains using -include_scope (hierarchical) or -elements (explicit instances)
  • Every design must have a primary power domain (typically PD_TOP -include_scope) containing elements not assigned elsewhere
  • Hierarchical domains enable modular power management and IP reuse, using set_scope to navigate hierarchy
  • Power domain boundaries (signal crossings between domains) determine where isolation, level shifters, and retention are applied
  • Element membership is exclusive (one domain per element), with hierarchical override (specific beats general)
Did you find what you were looking for?

Quiz

No quiz questions available for this article.