16 min read | Advanced Level
What You'll Learn
- Configure power-aware synthesis flows in Design Compiler
- Insert and verify isolation, retention, and level shifter cells
- Optimize multi-Vt cell selection for leakage power reduction
- Validate UPF consistency between RTL and gate-level netlists
From UPF to Gates
You've written comprehensive UPF for your multi-domain SoC. Verification passed—simulation shows perfect isolation, retention works flawlessly, and formal verification proved correctness. Now comes synthesis: transforming RTL and UPF into gates.
You run standard synthesis. It completes successfully, reporting excellent area and timing. But when you check the netlist, you discover:
- Zero isolation cells inserted (X-propagation will occur)
- Zero retention cells inserted (state will be lost)
- All domains use the same supply (no power gating possible)
- No level shifters between voltage domains (potential corruption)
Standard synthesis ignored your UPF completely.
Power-aware synthesis is not optional—it's mandatory. Standard synthesis tools ignore UPF and produce netlists that violate power intent. You must use power-aware synthesis flows (Design Compiler with UPF support) to correctly implement low-power designs.
Power-Aware Synthesis in Practice
A mobile processor design had 8 power domains with 2,400 isolation cells, 800 retention flip-flops, and 150 level shifters. The first power-aware synthesis run took 6 hours and consumed 45,000 um² for special cells (3% of total area). After optimizing cell placement and using smaller library cells, area dropped to 28,000 um² (1.8%) while maintaining all power management functionality. The key: iterative refinement of UPF and synthesis constraints to balance area, timing, and power.
Power-Aware Synthesis Flow
Standard vs. Power-Aware Synthesis
| Stage | Standard Synthesis | Power-Aware Synthesis |
|---|---|---|
| Input | RTL + constraints | RTL + constraints + UPF |
| Optimization | Area, timing, dynamic power | + Leakage power, multi-Vt |
| Special cells | None | Isolation, retention, level shifters |
| Domain awareness | Single domain | Multiple power domains |
| Supply networks | Single VDD/VSS | Multiple supplies per domain |
| Output | Gate netlist | Gate netlist + UPF netlist |
Design Compiler Power-Aware Flow
# dc_setup.tcl - Power-aware synthesis flow
# 1. Setup library and design
set target_library "your_lib.db"
set link_library "* $target_library"
# 2. Read RTL
analyze -format sverilog design/*.sv
elaborate top_design
# 3. Load UPF BEFORE constraints (critical!)
load_upf top_level.upf
# 4. Check UPF consistency
check_mv_design -verbose
# Must pass before proceeding!
# 5. Load constraints
source constraints.tcl
# 6. Configure power-aware synthesis
set_mv_flow true
set_power_prediction true # Enable power analysis
# 7. Link design with multi-voltage awareness
link_mv
# 8. Compile with power optimization
compile_ultra -gate_clock -no_autoungroup \
-power # Enable power optimization
# 9. Check results
report_mv_design -verbose
report_power -hierarchy
# 10. Write outputs
write -format verilog -hierarchy -output synth_netlist.v
write_upf synth_netlist.upf # Updated UPF for gate-level
Critical: Load UPF before constraints. The synthesis tool needs to understand power domains before applying timing constraints, as constraints may be domain-specific.
Isolation Cell Insertion
Automatic Insertion by Synthesis
When you specify isolation in UPF, synthesis automatically inserts isolation cells:
# UPF specification
set_isolation ISO_GPU -domain PD_GPU \
-isolation_supply_set SS_TOP \
-isolation_signal gpu_iso_enable \
-clamp_value 0 \
-location parent
Synthesis inserts:
// Before synthesis (RTL)
module top;
logic [31:0] gpu_data;
gpu_core gpu_inst(.data_out(gpu_data));
noc_router noc(.gpu_input(gpu_data));
endmodule
// After synthesis (gate-level netlist)
module top;
wire [31:0] gpu_data;
wire [31:0] gpu_data_iso; // Isolated version
gpu_core gpu_inst(.data_out(gpu_data));
// Synthesis inserted 32 isolation cells
ISO_CELL_AND iso_0 (.A(gpu_data[0]), .EN(gpu_iso_enable), .Z(gpu_data_iso[0]));
ISO_CELL_AND iso_1 (.A(gpu_data[1]), .EN(gpu_iso_enable), .Z(gpu_data_iso[1]));
// ... iso_2 through iso_31 ...
noc_router noc(.gpu_input(gpu_data_iso)); // Receives isolated signals
endmodule
Verifying Isolation Insertion
# Check isolation cell insertion
report_mv_design -isolation
# Output shows:
# Isolation Strategy: ISO_GPU
# Signals covered: 47
# Cells inserted: 47
# Cell types: ISO_CELL_AND (47)
# Total area: 2,340 um²
Quick Check
Q: Why does synthesis insert isolation cells automatically instead of requiring manual instantiation in RTL?
Show Answer
Manual instantiation would require modifying RTL with power management logic, breaking the separation of concerns between functional design and power intent. Automatic insertion by synthesis keeps RTL clean and functional, with all power management specified declaratively in UPF. This enables IP reuse (same RTL, different UPF for different integrations) and simplifies verification (verify functional RTL separately from power intent).
Retention Cell Insertion
Retention Register Mapping
Synthesis replaces standard flip-flops with retention flip-flops:
# UPF specification
set_retention RET_CPU -domain PD_CPU \
-retention_supply_set SS_CPU_RET \
-save_signal {cpu_save_enable high} \
-restore_signal {cpu_restore_enable high}
# Map to retention cells in library
map_retention_cell RET_CPU \
-lib_cells {DFFR_X1} # Retention flip-flop from liberty
Synthesis transforms:
// Before synthesis (RTL)
always_ff @(posedge clk)
if (rst_n) pc <= next_pc;
// After synthesis (gate-level)
DFFR_X1 pc_reg_0 (
.D(next_pc[0]),
.CK(clk),
.RN(rst_n),
.SAVE(cpu_save_enable), // Retention control
.RESTORE(cpu_restore_enable), // Retention control
.VRET(VDD_RET), // Always-on retention supply
.Q(pc[0])
);
// ... pc_reg_1 through pc_reg_31 ...
Verifying Retention Coverage
# Check retention cell insertion
report_mv_design -retention
# Output:
# Retention Strategy: RET_CPU
# Sequential elements in domain: 1,057
# Retention elements specified: 1,056
# Retention cells inserted: 1,056
# Cell types: DFFR_X1 (1,056)
# Coverage: 99.9%
# Missing: cpu_subsystem/pipeline_tag (intentionally excluded)
Level Shifter Insertion
Automatic Level Shifter Placement
# UPF specification
set_level_shifter LS_CPU_TO_GPU -domain PD_GPU \
-applies_to inputs \
-source PD_CPU \
-location automatic # Let synthesis decide placement
Synthesis analysis and insertion:
// RTL: CPU (1.0V) drives GPU (0.8V)
module top;
logic [31:0] cpu_to_gpu;
cpu_core cpu(.data_out(cpu_to_gpu)); // 1.0V domain
gpu_core gpu(.data_in(cpu_to_gpu)); // 0.8V domain
endmodule
// Gate-level: Level shifters inserted
module top;
wire [31:0] cpu_to_gpu;
wire [31:0] cpu_to_gpu_shifted; // Level-shifted version
cpu_core cpu(.data_out(cpu_to_gpu)); // 1.0V
// Synthesis inserted 32 level shifters
LS_HL_X1 ls_0 (.A(cpu_to_gpu[0]), .Z(cpu_to_gpu_shifted[0]));
// LS_HL_X1: High-to-Low level shifter (1.0V -> 0.8V)
// ... ls_1 through ls_31 ...
gpu_core gpu(.data_in(cpu_to_gpu_shifted)); // 0.8V
endmodule
Multi-Vt Optimization
Modern libraries provide multiple threshold voltage (Vt) variants of each cell:
- LVT (Low Vt): Fast, high leakage power
- RVT (Regular Vt): Balanced speed and leakage
- HVT (High Vt): Slow, low leakage power
Multi-Vt Cell Selection Strategy
# Configure multi-Vt optimization
set_multi_vth_constraint \
-type soft \
-lvt_percentage 10 \ # 10% LVT cells (critical paths)
-hvt_percentage 60 # 60% HVT cells (non-critical paths)
# Remaining 30% = RVT
# Compile with multi-Vt optimization
compile_ultra -gate_clock -power
Synthesis result:
Multi-Vt Cell Distribution: LVT: 8,423 cells (10.2%) - Critical paths only RVT: 24,891 cells (30.1%) - Moderate timing paths HVT: 49,378 cells (59.7%) - Non-critical paths Leakage Power Reduction: 45% vs. all-LVT design Timing Impact: 0 (meets all constraints) Area Impact: +2.3% (HVT cells slightly larger)
Multi-Vt optimization is one of the most effective leakage reduction techniques, typically achieving 40-50% leakage savings with minimal area/timing impact. Always enable it in power-aware synthesis.
Common Beginner Mistakes
Mistake #1: Loading UPF after constraints
# WRONG: Constraints loaded before UPF
source constraints.tcl
load_upf top_level.upf # Too late!
# CORRECT: UPF before constraints
load_upf top_level.upf
source constraints.tcl
Why? Constraints may reference power domains. Loading UPF first ensures domains exist when constraints are applied.
Mistake #2: Missing library cell mappings
# Check for missing mappings
check_mv_design -verbose
# Error: No retention cell mapping for strategy RET_CPU
# Fix: Add mapping
map_retention_cell RET_CPU -lib_cells {DFFR_X1}
Mistake #3: Not verifying special cell insertion
# WRONG: Assume synthesis inserted cells correctly
compile_ultra -power
write -format verilog -output netlist.v
# CORRECT: Always verify insertion
compile_ultra -power
report_mv_design -isolation # Check isolation cells
report_mv_design -retention # Check retention cells
report_mv_design -level_shifter # Check level shifters
write -format verilog -output netlist.v
Summary
In this tutorial, you learned:
- Power-aware synthesis extends standard synthesis to handle multiple power domains, special cells, and leakage optimization
- Load UPF before constraints, check consistency with check_mv_design, enable multi-voltage flow
- Synthesis automatically inserts isolation cells, retention flip-flops, and level shifters based on UPF specifications
- Verify special cell insertion with report_mv_design commands before writing netlist
- Multi-Vt optimization achieves 40-50% leakage reduction by using HVT cells on non-critical paths
- Always map retention/isolation strategies to library cells before synthesis
- Output includes both gate-level netlist and updated UPF for physical implementation