ucs_fix_hold

Tcl EDA Session Usage Guide — ucs_hold_fix.tcl

Scriptucs_fix_hold (proc, exposed after sourcing ucs_hold_fix.tcl)
Script Filepublish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl
VersionUCS-1.1.1
Modified2026-04-01
PurposeMulti-corner hold-fix ECO proc that runs inside a live EDA tool session — queries live setup slack from the loaded design, runs the bottleneck fix engine, and inserts hold buffers via ECO commands
Environmentfc_shell (Fusion Compiler) or icc2_shell (ICC2) — design must be loaded
Supporttech@universalchipstudio.com
Quick Nav: Features Environment How to Load Synopsis Arguments Setup Query Output Files Workflow Examples

Key Features

Environment

Note: ucs_fix_hold must be called inside an active Fusion Compiler (fc_shell) or ICC2 (icc2_shell) session with the design already loaded and timing analysis completed. It is NOT intended for use in PrimeTime (pt_shell). For PrimeTime setup-slack collection, use the companion script setup_query_runtime.tcl described in the Setup Query section below.
License required: A valid UCS license is required. The license check runs automatically when ucs_hold_fix.tcl is sourced. If the check fails, the proc ucs_fix_hold will not be available. Contact tech@universalchipstudio.com to obtain a license file (.ucs_license.conf) for your project tree.

Script File Locations

publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl   (entrypoint)
publish/redhat8/sta/hold/tcl_modular/lib/00_bootstrap.tcl   (namespace + version)
publish/redhat8/sta/hold/tcl_modular/lib/10_io_debug.tcl
publish/redhat8/sta/hold/tcl_modular/lib/20_license_runtime.tcl
publish/redhat8/sta/hold/tcl_modular/lib/30_node_setup_scope.tcl
publish/redhat8/sta/hold/tcl_modular/lib/40_parsing_and_cells.tcl
publish/redhat8/sta/hold/tcl_modular/lib/50_fix_engine.tcl
publish/redhat8/sta/hold/tcl_modular/lib/60_reports.tcl
publish/redhat8/sta/hold/tcl_modular/lib/70_entrypoints.tcl

All lib modules are sourced automatically by the entrypoint. The same directory structure exists under publish/redhat7/.

How to Load

Two ways to source the script:

Option A — Standard source (most EDA tools)

# Inside fc_shell or icc2_shell (design already loaded)
source /path/to/publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl

# After sourcing, the proc is available:
ucs_fix_hold -help

Option B — Pre-set path (for tools that return "" from [info script])

Some EDA sessions (e.g., Fusion Compiler HyperScale) return an empty string from [info script] when files are sourced indirectly. In this case, pre-set the path variable before sourcing:

set ::ucs_holdfix_script_path \
    /path/to/publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl
source $::ucs_holdfix_script_path
Note: The entrypoint automatically walks up the directory tree from its own location to find common/lib/tcl_lib/ and sources the shared Tcl libraries (ucs_tcl_common_utils.tcl, ucs_tcl_dict_compat.tcl, ucs_tcl_license_check.tcl). If the common directory is not found (e.g., isolated deployment), these libraries are silently skipped and the tool falls back to built-in implementations.

Synopsis

Call ucs_fix_hold after sourcing the script. At least one of -setup_corner or -setup_margin_file is required.

ucs_fix_hold \
    -report_list       <violations.lst> \
    -cell_delay_file   <delay_db.txt> \
    -ref_filter        <regex> \
    { -setup_corner <corner_name> | -setup_margin_file <file> [...] } \
    [-scope_json          <file>] \
    [-report_level        <name>] \
    [-fix_level           <name>] \
    [-forbidden_module    <module_list>] \
    [-blacklist_node      <file>] \
    [-setup_guardband     <ps>] \
    [-derate              <factor>] \
    [-pba_mode            <none|path|exhaustive>] \
    [-prefer_cells        <cell_list>] \
    [-time_unit           <ns|ps|auto>] \
    [-max_cells           <int>] \
    [-allow_output_pins] \
    [-enable_io_paths] \
    [-aggressive] \
    [-verbose] \
    [-debug              <0|1|2|3|4>] \
    [-output_dir         <path>] \
    [-help]

Arguments

Required Inputs

OptionTypeDescription
-report_list <file> string Report list file. One line per corner: <corner> <target_slack_ps> <report_abs_path>. Legacy alias: -violation_list (same format).
-cell_delay_file <file> string Cell delay database in Perl-compatible format with [percentile_select], [percentile_delay], and [final_delay] sections. Legacy alias: -delay_config (Tcl source format, still supported).
-ref_filter <regex> regex Required regex to identify true leaf-cell refs in timing reports. Applied to the cell reference field of each path endpoint. Example: {^BWP}, {^SAED32}.

Setup Slack Source — at least one of the following is required

Note: When both -setup_corner and -setup_margin_file are given, the live query result from -setup_corner takes precedence over the TSV for any pin found in both. The TSV is used as a fallback for pins not covered by the live query.
OptionTypeDescription
-setup_corner <corner> string Corner name for LIVE setup slack query. For each candidate pin, calls get_attribute $pin max_slack (or get_timing_paths -pba_mode if -pba_mode is not none). Requires the design and timing to be loaded in the current session.
-setup_margin_file <file> ... list OFFLINE setup margin TSV file(s) generated by setup_query_runtime.tcl in PrimeTime. Accepts multiple files. Format per line: <corner> <pin_path> <slack_ns> <direction>. All files are merged into a single in-memory database.

Hierarchy and Scope

OptionTypeDefaultDescription
-scope_json <file> string — Optional scope database JSON for hierarchy and ref lookup. If omitted, cell refs are derived from the live EDA session (get_attribute ref_name).
-report_level <name> string — Optional report-level scope name (e.g., u_top). Must be paired with -fix_level. Both require -scope_json.
-fix_level <name> string — Optional fix-level scope name (e.g., u_top/u_blk). Must be paired with -report_level.
-forbidden_module <list> list — Module/instance path prefixes to skip. Any pin whose hierarchical path starts with one of these prefixes is excluded from all fix passes.
-blacklist_node <file> string — File of node blacklist patterns, one per line. Supports * and ? wildcards. Matched nodes are excluded from fixing.

Fix Behavior

OptionTypeDefaultDescription
-setup_guardband <float> float (ps) 0 Minimum setup slack (in picoseconds) that must remain after a hold buffer insertion. Fix is applied only when setup slack exceeds this guardband.
-derate <factor> float 1.0 Derate factor applied to hold delay requirements before computing the required buffer chain length.
-pba_mode <mode> enum none PBA mode for live setup slack query via get_timing_paths: none (use max_slack attribute directly), path (pba_mode path), exhaustive (pba_mode exhaustive). Has no effect when using offline TSV only.
-prefer_cells <list> list all valid cells Restrict candidate delay cells to a preferred subset. Accepts exact names (BUFFD1BWP136P5M117H3P48CPDLVT) or glob patterns (BUFFD1*, DLYD*). Intersection with globally valid cells is taken.
-time_unit <unit> enum auto Time unit for delay values in the cell delay file: ns, ps, or auto (detect from the EDA session's current time unit).
-max_cells <int> int 200 Maximum number of delay cells to chain at a single insertion point. Prevents runaway buffer chains.
-allow_output_pins flag off Include output pins as fix candidate insertion points. Default: input pins only.
-enable_io_paths flag off Include IO-related timing paths (paths involving design ports). Default: IO paths are excluded.
-aggressive flag off Enable an aggressive fallback pass after the normal fix pass. Aggressive mode applies tighter per-path constraints. Both passes produce separate ECO output files (normal.tcl and aggressive.tcl).

Output and Debug

OptionTypeDefaultDescription
-output_dir <path> string cwd Base directory for all output files. The script creates ucs_hold_fix_YYYYMMDD/ under this path.
-verbose flag off Enable verbose progress output to stdout during fixing.
-debug <0-4> int 0 Automatic debug dump level. 0=off; 1=stage TSV summaries; 2=level 1 + detailed path/node database views; 3=level 2 + decision trace TSVs; 4=level 3 + full JSON snapshots. All debug output goes to ucs_hold_fix_YYYYMMDD/debug/. Effective level is min(requested, licensed_max).
-help flag — Print full help message and return without running the fix engine.

Setup Query Helper — setup_query_runtime.tcl

setup_query_runtime.tcl is a companion helper that runs inside PrimeTime to collect live setup slack values. It is used when setup margin TSV files need to be generated before running the hold fix. In normal workflow, this file is generated automatically by the Perl ucs_hold_fix in prepare-only mode and then sourced in PrimeTime — you do not call its procs manually.

Script Location

publish/redhat8/sta/hold/perl/bin/setup_query_runtime.tcl
publish/redhat7/sta/hold/perl/bin/setup_query_runtime.tcl
Environment: Must be sourced inside pt_shell with the design loaded and timing analysis complete. Uses PrimeTime-native commands: get_pins, get_attribute, get_timing_paths, sizeof_collection, index_collection.

Global Variables (must be set before calling)

VariableTypeDescription
::ucs_nodes list List of pin path strings to query setup slack for. This list is populated automatically by the generated setup_query.tcl.
::ucs_pba_mode string PBA mode for timing queries: none (use max_slack attribute), path (get_timing_paths -pba_mode path), exhaustive. Defaults to none.

Exported Procs

ProcArgumentsReturnsDescription
ucs_dump_setup_margin_for_corner corner (string) file path Top-level entry point. Iterates ::ucs_nodes, queries setup slack for each pin in the given corner, and writes results to ucs_setup_<corner>.tsv in the current directory. Returns the output file path.
ucs_dump_setup_margin_and_direction out_file corner — Lower-level proc. Appends rows to an existing file. Useful when writing multiple corners to the same file.

Output TSV Format

# Format: <corner>  <pin_path>  <setup_slack_ns>  <direction>
FuncSSG0p6vRcbestCCbest0c   u_top/u_blk/q_reg/D    0.123456   input
FuncSSG0p6vRcbestCCbest0c   u_top/u_blk/q_reg/SI   0.089012   input
FuncSSG0p6vRcbestCCbest0c   u_top/u_blk/mux_inst/I1  0.201340   input

Behavior Details

ConditionBehavior
Pin not found in design Prints WARN: pin not found: <name> to stderr; pin is skipped
Hierarchical boundary pin (is_hierarchical == true) Silently skipped — inserting buffers at hierarchical boundaries can break scan chains and HyperScale annotation
Slack is empty, "infinite", or "infinity" Normalized to 9999 (treated as unconstrained / safe)
::ucs_pba_mode is not "none" Calls get_timing_paths -through $pin -delay_type max -max_paths 1 -pba_mode $::ucs_pba_mode instead of reading max_slack attribute
Unsupported pin direction Prints WARN: unsupported direction '...' for <pin>; pin is skipped

Three-Step Workflow with setup_query_runtime.tcl

# Step 1 — Shell: generate pre-fix DB and setup-query Tcl (Perl prepare-only mode)
ucs_hold_fix \
    -report_list   violations.lst \
    -scope_json    scope_db.json \
    -ref_filter    {^BWP} \
    -setup_query_tcl setup_query_pt.tcl

# Step 2 — PrimeTime: source the generated Tcl to collect setup margins
#   (inside pt_shell with design loaded)
source setup_query_pt.tcl
# -> writes: ucs_setup_FuncSSG0p6vRcbestCCbest0cHld.tsv (one file per corner)

# Step 3 — Fusion Compiler: run the hold fix with collected margins
#   (inside fc_shell with design loaded)
source /path/to/publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl
ucs_fix_hold \
    -report_list     violations.lst \
    -cell_delay_file delay_db.txt \
    -ref_filter      {^BWP} \
    -setup_margin_file ucs_setup_FuncSSG0p6vRcbestCCbest0cHld.tsv \
    -setup_guardband 20 \
    -aggressive

Output Files

All outputs are placed under a timestamped directory. The base path is the current working directory (or -output_dir if set).

ucs_hold_fix_YYYYMMDD/
├── eco/
│   ├── ucs_fix_hold_$USER_YYYYMMDD.normal.tcl        ← Primary ECO Tcl (insert_buffer commands)
│   └── ucs_fix_hold_$USER_YYYYMMDD.aggressive.tcl    ← Aggressive ECO (if -aggressive)
├── reports/
│   ├── ucs_fix_hold_$USER_YYYYMMDD.summary.rpt        ← Per-corner fix statistics
│   ├── ucs_fix_hold_$USER_YYYYMMDD.unfixed_paths.rpt  ← Paths not fixed (hold req not met)
│   └── ucs_fix_hold_$USER_YYYYMMDD.unfixed_raw_paths.rpt
└── debug/                                             ← Only with -debug 1..4
    ├── post_parse.path.tsv
    ├── post_build_node_db.node.tsv
    ├── post_merge_setup.path.tsv
    ├── post_merge_setup.node.tsv
    ├── post_filter.path.tsv
    ├── post_filter.node.tsv
    ├── post_normal_fix.path.tsv
    ├── post_normal_fix.node.tsv
    ├── post_aggressive_fix.path.tsv    ← only with -aggressive
    ├── post_aggressive_fix.node.tsv
    ├── normal.decision.tsv             ← only with -debug 3+
    ├── aggressive.decision.tsv         ← only with -debug 3+ and -aggressive
    └── <stage>.json                    ← only with -debug 4
ECO file format: Each insert_buffer command is preceded by a structured comment block recording: dominant hold corner, all active hold corners, node path, number of paths covered, path IDs, remaining hold requirement per corner, and cells selected. All commands are wrapped in catch {} to allow partial execution (individual failures do not abort the ECO session).
################################################################################
# Hold Fix ECO - Shared Node u_top/u_blk/df_tcdxcn/flop_inst/SI
################################################################################
# Dominant Hold Corner: FuncSSG0p6vRcbestCCbest0cHld
# Active Hold Corners: FuncSSG0p6vRcbestCCbest0cHld FuncSSG0p6vRcworstCCworst100cHld
# Node Selected: u_top/u_blk/df_tcdxcn/flop_inst/SI
# Active Paths Covered: 6
# Path IDs: 15 103 126 555 626 651
# Remaining Hold Requirement By Corner:
# Cells Selected: BUFFD1BWP136P5M117H3P48CPDLVT
################################################################################
catch {insert_buffer u_top/u_blk/df_tcdxcn/flop_inst/SI \
    BUFFD1BWP136P5M117H3P48CPDLVT \
    -new_net_names  ucs_fix_hold_huiyinli_20260411_net \
    -new_cell_names ucs_fix_hold_huiyinli_20260411_buf}

Workflow

  ┌─────────────────────────────────────────────────────────────────┐
  │  fc_shell / icc2_shell  (design loaded, timing analyzed)        │
  │                                                                 │
  │  source /path/to/ucs_hold_fix.tcl                              │
  │        │                                                        │
  │        ▼  (auto-sources lib/00..70 + common libs)              │
  │  ┌──────────────────────┐                                       │
  │  │   License Check      │  ╸ .ucs_license.conf (walk-up)       │
  │  └──────────────────────┘                                       │
  │        │                                                        │
  │        ▼                                                        │
  │  ucs_fix_hold [options]                                         │
  │        │                                                        │
  │        ▼                                                        │
  │  ┌──────────────────────┐                                       │
  │  │  Parse Hold Reports  │  ╸ -report_list                       │
  │  │  Build Node DB       │  ╸ -scope_json, -ref_filter           │
  │  └──────────────────────┘                                       │
  │        │                                                        │
  │        ▼                                                        │
  │  ┌──────────────────────┐     ┌────────────────────────────┐   │
  │  │  Merge Setup Margins │╸────│ -setup_corner (live query) │   │
  │  │  per pin per corner  │╸────│ -setup_margin_file (TSV)   │   │
  │  └──────────────────────┘     └────────────────────────────┘   │
  │        │                                                        │
  │        ▼                                                        │
  │  ┌──────────────────────┐                                       │
  │  │  Filter & Scope      │  ╸ -forbidden_module, -blacklist_node │
  │  │  Apply Guardband     │  ╸ -setup_guardband                   │
  │  └──────────────────────┘                                       │
  │        │                                                        │
  │        ▼                                                        │
  │  ┌──────────────────────┐                                       │
  │  │  Fix Engine          │  ╸ -prefer_cells, -max_cells, -derate │
  │  │  Normal Pass         │     Bottleneck-cost greedy selection   │
  │  └──────────────────────┘                                       │
  │        │                                                        │
  │        ├──▶ eco/normal.tcl  +  reports/summary.rpt             │
  │        │                                                        │
  │        ▼  [if -aggressive]                                      │
  │  ┌──────────────────────┐                                       │
  │  │  Fix Engine          │                                       │
  │  │  Aggressive Pass     │  Per-path fallback with tighter       │
  │  └──────────────────────┘  constraints                          │
  │        │                                                        │
  │        └──▶ eco/aggressive.tcl                                  │
  └─────────────────────────────────────────────────────────────────┘

Examples

Example 1 — Minimal: live setup slack from the loaded design

# Inside fc_shell (design loaded, timing analyzed)
source /path/to/publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl

ucs_fix_hold \
    -report_list     violations.lst \
    -cell_delay_file delay_db.txt \
    -ref_filter      {^BWP} \
    -setup_corner    FuncSSG0p6vRcbestCCbest0cHld

Example 2 — Offline setup margins from TSV files + aggressive mode

source /path/to/tcl_modular/bin/ucs_hold_fix.tcl

ucs_fix_hold \
    -report_list       violations.lst \
    -cell_delay_file   delay_db.txt \
    -ref_filter        {^BWP} \
    -setup_margin_file {setup_FuncSSG_cbest.tsv setup_FuncFF_cworst.tsv} \
    -setup_guardband   20 \
    -aggressive \
    -verbose

Example 3 — Hierarchical scope with forbidden modules and blacklist

source /path/to/tcl_modular/bin/ucs_hold_fix.tcl

ucs_fix_hold \
    -report_list     violations.lst \
    -cell_delay_file delay_db.txt \
    -ref_filter      {^BWP} \
    -setup_corner    FuncSSG0p6vRcbestCCbest0cHld \
    -scope_json      scope_db.json \
    -report_level    u_top \
    -fix_level       u_top/u_blk \
    -forbidden_module {u_top/u_dft u_top/u_scan} \
    -blacklist_node  blacklist.txt \
    -prefer_cells    {BUFFD1* BUFFD2*} \
    -debug           2 \
    -output_dir      /scratch/eco_run

Example 4 — Both live and offline setup (live overrides TSV for shared pins)

ucs_fix_hold \
    -report_list       violations.lst \
    -cell_delay_file   delay_db.txt \
    -ref_filter        {^BWP} \
    -setup_corner      FuncSSG0p6vRcbestCCbest0cHld \
    -setup_margin_file setup_FuncSSG_cbest.tsv \
    -pba_mode          path

Example 5 — Pre-set path for HyperScale / indirect sourcing

# In sessions where [info script] returns "" (e.g., FC HyperScale):
set ::ucs_holdfix_script_path \
    /path/to/publish/redhat8/sta/hold/tcl_modular/bin/ucs_hold_fix.tcl
source $::ucs_holdfix_script_path

ucs_fix_hold \
    -report_list     violations.lst \
    -cell_delay_file delay_db.txt \
    -ref_filter      {^BWP} \
    -setup_corner    FuncSSG0p6vRcbestCCbest0cHld \
    -aggressive