diff --git a/graph/test/graph_advanced.tcl b/graph/test/graph_advanced.tcl index 58367f70..502a647c 100644 --- a/graph/test/graph_advanced.tcl +++ b/graph/test/graph_advanced.tcl @@ -33,11 +33,7 @@ puts "--- report_checks -from/-to ---" report_checks -from [get_ports d] -to [get_ports q] puts "--- report_checks -through ---" -set rc [catch { report_checks -through [get_pins reg1/Q] } msg] -if { $rc == 0 } { -} else { - puts "INFO: report_checks -through: $msg" -} +report_checks -through [get_pins reg1/Q] #--------------------------------------------------------------- # Edge queries (Graph.cc edge functions) diff --git a/liberty/test/liberty_busport_mem_iter.tcl b/liberty/test/liberty_busport_mem_iter.tcl index 13c9b78b..90793842 100644 --- a/liberty/test/liberty_busport_mem_iter.tcl +++ b/liberty/test/liberty_busport_mem_iter.tcl @@ -50,7 +50,7 @@ foreach lib_name {fakeram45_64x32 fakeram45_256x16 fakeram45_512x64 fakeram45_1024x32 fakeram45_64x96} { read_liberty ../../test/nangate45/${lib_name}.lib set cell [get_lib_cell ${lib_name}/${lib_name}] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set port_iter [$cell liberty_port_iterator] set bus_count 0 set bit_count 0 @@ -109,7 +109,7 @@ foreach cell_name {INV_X1 INV_X2 BUF_X1 BUF_X2 CLKBUF_X1 TINV_X1 CLKGATETST_X1 HA_X1 FA_X1 ANTENNA_X1 FILLCELL_X1 FILLCELL_X2 LOGIC0_X1 LOGIC1_X1} { set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set is_leaf [$cell is_leaf] set is_buf [$cell is_buffer] set is_inv [$cell is_inverter] @@ -129,7 +129,7 @@ puts "--- test_cell / scan queries ---" # SDFF has test_cell set sdff [get_lib_cell NangateOpenCellLibrary/SDFF_X1] set tc [$sdff test_cell] -if {$tc != "NULL"} { +if {$tc != "NULL" && $tc ne ""} { puts "SDFF_X1 has test_cell" } else { puts "SDFF_X1 test_cell is null" @@ -137,7 +137,7 @@ if {$tc != "NULL"} { set sdffr [get_lib_cell NangateOpenCellLibrary/SDFFR_X1] set tc [$sdffr test_cell] -if {$tc != "NULL"} { +if {$tc != "NULL" && $tc ne ""} { puts "SDFFR_X1 has test_cell" } else { puts "SDFFR_X1 test_cell is null" @@ -145,7 +145,7 @@ if {$tc != "NULL"} { set sdffrs [get_lib_cell NangateOpenCellLibrary/SDFFRS_X1] set tc [$sdffrs test_cell] -if {$tc != "NULL"} { +if {$tc != "NULL" && $tc ne ""} { puts "SDFFRS_X1 has test_cell" } else { puts "SDFFRS_X1 test_cell is null" @@ -154,7 +154,7 @@ if {$tc != "NULL"} { # Regular DFF should NOT have test_cell set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1] set tc [$dff test_cell] -if {$tc != "NULL"} { +if {$tc != "NULL" && $tc ne ""} { puts "DFF_X1 has test_cell (unexpected)" } else { puts "DFF_X1 has no test_cell (expected)" diff --git a/liberty/test/liberty_cell_classify_pgpin.tcl b/liberty/test/liberty_cell_classify_pgpin.tcl index 9a1cceb3..c99f3375 100644 --- a/liberty/test/liberty_cell_classify_pgpin.tcl +++ b/liberty/test/liberty_cell_classify_pgpin.tcl @@ -31,11 +31,9 @@ puts "INV_X1 is_buffer = [$inv_x1 is_buffer]" puts "INV_X1 is_inverter = [$inv_x1 is_inverter]" # Clock gate cells -catch { - set clkgate [get_lib_cell NangateOpenCellLibrary/CLKGATETST_X1] - puts "CLKGATETST_X1 is_buffer = [$clkgate is_buffer]" - puts "CLKGATETST_X1 is_inverter = [$clkgate is_inverter]" -} +set clkgate [get_lib_cell NangateOpenCellLibrary/CLKGATETST_X1] +puts "CLKGATETST_X1 is_buffer = [$clkgate is_buffer]" +puts "CLKGATETST_X1 is_inverter = [$clkgate is_inverter]" # DFF set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1] @@ -44,11 +42,9 @@ puts "DFF_X1 is_inverter = [$dff is_inverter]" puts "DFF_X1 is_leaf = [$dff is_leaf]" # Test cell for scan DFF -catch { - set sdff [get_lib_cell NangateOpenCellLibrary/SDFF_X1] - set tc [$sdff test_cell] - puts "SDFF_X1 test_cell = $tc" -} +set sdff [get_lib_cell NangateOpenCellLibrary/SDFF_X1] +set tc [$sdff test_cell] +puts "SDFF_X1 test_cell = $tc" ############################################################ # Port function queries (exercises FuncExpr::to_string) @@ -181,21 +177,19 @@ foreach cell_name { sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__ebufn_1 } { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]" - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - set func [$port function] - set dir [sta::liberty_port_direction $port] - set pwr [$port is_pwr_gnd] - if {$pwr} { - puts " [$port bus_name] pwr_gnd=1" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]" + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + set func [$port function] + set dir [sta::liberty_port_direction $port] + set pwr [$port is_pwr_gnd] + if {$pwr} { + puts " [$port bus_name] pwr_gnd=1" } - $port_iter finish } + $port_iter finish } ############################################################ @@ -204,7 +198,7 @@ foreach cell_name { puts "--- operating conditions ---" set sky_lib [lindex [get_libs sky130_fd_sc_hd__tt_025C_1v80] 0] set default_oc [$sky_lib default_operating_conditions] -if {$default_oc != "NULL"} { +if {$default_oc != "NULL" && $default_oc ne ""} { puts "Sky130 default OC process=[$default_oc process] voltage=[$default_oc voltage] temp=[$default_oc temperature]" } @@ -220,27 +214,21 @@ foreach cell_name { sg13g2_dfrbp_1 sg13g2_dfrbp_2 sg13g2_ebufn_2 } { - catch { - set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]" - set arc_sets [$cell timing_arc_sets] - puts " arc_sets=[llength $arc_sets]" - } + set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] + puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]" + set arc_sets [$cell timing_arc_sets] + puts " arc_sets=[llength $arc_sets]" } ############################################################ # Ensure voltage waveforms (exercises ensureVoltageWaveforms) ############################################################ puts "--- ensure voltage waveforms ---" -catch { - set inv [get_lib_cell NangateOpenCellLibrary/INV_X1] - $inv ensure_voltage_waveforms -} +set inv [get_lib_cell NangateOpenCellLibrary/INV_X1] +$inv ensure_voltage_waveforms -catch { - set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1] - $dff ensure_voltage_waveforms -} +set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1] +$dff ensure_voltage_waveforms ############################################################ # Liberty cell matching with regex patterns diff --git a/liberty/test/liberty_cell_deep.tcl b/liberty/test/liberty_cell_deep.tcl index faa5426e..e70d4306 100644 --- a/liberty/test/liberty_cell_deep.tcl +++ b/liberty/test/liberty_cell_deep.tcl @@ -31,19 +31,15 @@ set cap_d [get_property $dff_d capacitance] # Larger drive strengths have different capacitances foreach size {1 2 4 8 16 32} { - catch { - set pin [get_lib_pin NangateOpenCellLibrary/INV_X${size}/A] - set cap [get_property $pin capacitance] - puts "INV_X${size}/A cap = $cap" - } + set pin [get_lib_pin NangateOpenCellLibrary/INV_X${size}/A] + set cap [get_property $pin capacitance] + puts "INV_X${size}/A cap = $cap" } foreach size {1 2 4 8 16 32} { - catch { - set pin [get_lib_pin NangateOpenCellLibrary/BUF_X${size}/A] - set cap [get_property $pin capacitance] - puts "BUF_X${size}/A cap = $cap" - } + set pin [get_lib_pin NangateOpenCellLibrary/BUF_X${size}/A] + set cap [get_property $pin capacitance] + puts "BUF_X${size}/A cap = $cap" } ############################################################ @@ -56,22 +52,18 @@ foreach cell_name {INV_X1 INV_X2 INV_X4 INV_X8 INV_X16 INV_X32 NOR2_X1 NOR2_X2 NOR2_X4 AOI21_X1 OAI21_X1 MUX2_X1 FA_X1 HA_X1 TINV_X1 CLKGATETST_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set area [get_property $cell area] - puts "$cell_name area = $area" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set area [get_property $cell area] + puts "$cell_name area = $area" } ############################################################ # Cell dont_use, is_macro, is_memory queries ############################################################ foreach cell_name {INV_X1 BUF_X1 DFF_X1 ANTENNA_X1 FILLCELL_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set du [get_property $cell dont_use] - puts "$cell_name dont_use = $du" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set du [get_property $cell dont_use] + puts "$cell_name dont_use = $du" } ############################################################ @@ -135,9 +127,7 @@ report_check_types -max_skew ############################################################ report_power -catch { - report_power -instances [get_cells *] -} +report_power -instances [get_cells *] ############################################################ # Sky130 cells - different tristate and latch cells @@ -145,28 +135,28 @@ catch { read_liberty ../../test/sky130hd/sky130hd_tt.lib # Tristate buffer -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_2} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_4} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_2 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_4 # Latch cells -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlxtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlxtn_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlxtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlxtn_1 # Scan flip-flops -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxbp_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxbp_1 # DFF with async set/clear (exercises recovery/removal) -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfrtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfstp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfbbp_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfrtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfstp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfbbp_1 # Mux cells -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux2_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux2i_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux4_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux2_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux2i_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__mux4_1 ############################################################ # Write roundtrip to exercise all writer cell/arc/model paths diff --git a/liberty/test/liberty_clkgate_lvlshift.tcl b/liberty/test/liberty_clkgate_lvlshift.tcl index 6b41b3f3..8ac69bb5 100644 --- a/liberty/test/liberty_clkgate_lvlshift.tcl +++ b/liberty/test/liberty_clkgate_lvlshift.tcl @@ -53,7 +53,7 @@ foreach cell_name {sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__dlclkp_2 sky130_fd_sc_hd__dlclkp_4} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] set lp [get_property $cell cell_leakage_power] puts "$cell_name area=$area leakage=$lp" @@ -67,22 +67,20 @@ foreach cell_name {sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__dlclkp_2 # sdlclkp cells have latch_posedge_precontrol type foreach cell_name {sky130_fd_sc_hd__sdlclkp_1 sky130_fd_sc_hd__sdlclkp_2 sky130_fd_sc_hd__sdlclkp_4} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set area [get_property $cell area] - puts "$cell_name area=$area" + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set area [get_property $cell area] + puts "$cell_name area=$area" - # Iterate ports to check clock_gate_* pin attributes - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - set dir [sta::liberty_port_direction $port] - set func [$port function] - puts " [get_name $port] dir=$dir func=$func" - } - $port_iter finish + # Iterate ports to check clock_gate_* pin attributes + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + set dir [sta::liberty_port_direction $port] + set func [$port function] + puts " [get_name $port] dir=$dir func=$func" } + $port_iter finish } } @@ -101,7 +99,7 @@ foreach cell_name {sky130_fd_sc_hd__lpflow_lsbuf_lh_hl_isowell_tap_1 sky130_fd_sc_hd__lpflow_lsbuf_lh_isowell_tap_4} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] set lp [get_property $cell cell_leakage_power] puts "$cell_name area=$area leakage=$lp" @@ -130,24 +128,22 @@ puts "--- pg_pin queries ---" foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__nand2_1 sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__sdfxtp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set pwr_count 0 - set sig_count 0 - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - set is_pwr [$port is_pwr_gnd] - if {$is_pwr} { - incr pwr_count - } else { - incr sig_count - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set pwr_count 0 + set sig_count 0 + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + set is_pwr [$port is_pwr_gnd] + if {$is_pwr} { + incr pwr_count + } else { + incr sig_count } - $port_iter finish - puts "$cell_name: pwr_pins=$pwr_count signal_pins=$sig_count" } + $port_iter finish + puts "$cell_name: pwr_pins=$pwr_count signal_pins=$sig_count" } } @@ -159,7 +155,7 @@ puts "--- clock gate timing arcs ---" catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlclkp_1] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "dlclkp_1 arc_sets = $arc_count" @@ -174,7 +170,7 @@ catch { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdlclkp_1] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "sdlclkp_1 arc_sets = $arc_count" @@ -191,7 +187,7 @@ puts "--- level shifter timing arcs ---" catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__lpflow_lsbuf_lh_hl_isowell_tap_1] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] puts "lsbuf_lh_hl_isowell_tap_1 arcs = [llength $arcs]" foreach arc $arcs { @@ -210,14 +206,12 @@ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_2 sky130_fd_sc_hd__clkinv_1 sky130_fd_sc_hd__clkbuf_1 sky130_fd_sc_hd__nand2_1 sky130_fd_sc_hd__nor2_1 sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dlclkp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set is_buf [$cell is_buffer] - set is_inv [$cell is_inverter] - set is_leaf [$cell is_leaf] - puts "$cell_name: is_buffer=$is_buf is_inverter=$is_inv is_leaf=$is_leaf" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set is_buf [$cell is_buffer] + set is_inv [$cell is_inverter] + set is_leaf [$cell is_leaf] + puts "$cell_name: is_buffer=$is_buf is_inverter=$is_inv is_leaf=$is_leaf" } } @@ -240,13 +234,11 @@ puts "IHP VDD exists: $ihp_vdd_exists" # Query IHP cells foreach cell_name {sg13g2_inv_1 sg13g2_buf_1 sg13g2_nand2_1 sg13g2_nor2_1} { - catch { - set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { - set area [get_property $cell area] - set is_buf [$cell is_buffer] - set is_inv [$cell is_inverter] - puts "IHP $cell_name: area=$area buf=$is_buf inv=$is_inv" - } + set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set area [get_property $cell area] + set is_buf [$cell is_buffer] + set is_inv [$cell is_inverter] + puts "IHP $cell_name: area=$area buf=$is_buf inv=$is_inv" } } diff --git a/liberty/test/liberty_equiv_cross_lib.tcl b/liberty/test/liberty_equiv_cross_lib.tcl index e97c3906..340c152d 100644 --- a/liberty/test/liberty_equiv_cross_lib.tcl +++ b/liberty/test/liberty_equiv_cross_lib.tcl @@ -23,7 +23,7 @@ foreach cell_prefix {INVx BUFx} { catch { set cell_name "${cell_prefix}${size}_ASAP7_75t_R" set cell [get_lib_cell asap7sc7p5t_INVBUF_RVT_FF_nldm_211120/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set equivs [sta::find_equiv_cells $cell] if {$equivs != ""} { puts "$cell_name equiv count = [llength $equivs]" @@ -49,7 +49,7 @@ foreach cell_prefix {INVx BUFx} { catch { set cell_name "${cell_prefix}${size}_ASAP7_75t_L" set cell [get_lib_cell asap7sc7p5t_INVBUF_LVT_FF_nldm_211120/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set equivs [sta::find_equiv_cells $cell] if {$equivs != ""} { puts "LVT $cell_name equiv count = [llength $equivs]" diff --git a/liberty/test/liberty_leakage_power_deep.tcl b/liberty/test/liberty_leakage_power_deep.tcl index 7b43c9df..8274d472 100644 --- a/liberty/test/liberty_leakage_power_deep.tcl +++ b/liberty/test/liberty_leakage_power_deep.tcl @@ -25,7 +25,7 @@ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_2 sky130_fd_sc_hd__mux2_1 sky130_fd_sc_hd__mux2i_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage=$lp" } @@ -40,7 +40,7 @@ foreach cell_name {sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfxtp_2 sky130_fd_sc_hd__sdfstp_1 sky130_fd_sc_hd__dfbbp_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] set area [get_property $cell area] puts "$cell_name leakage=$lp area=$area" @@ -53,7 +53,7 @@ foreach cell_name {sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__ebufn_2 sky130_fd_sc_hd__ebufn_4 sky130_fd_sc_hd__ebufn_8} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage=$lp" } @@ -65,7 +65,7 @@ foreach cell_name {sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__dlclkp_2 sky130_fd_sc_hd__sdlclkp_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage=$lp" } @@ -77,11 +77,11 @@ foreach cell_name {sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__dlclkp_2 ############################################################ puts "--- detailed cell reports ---" -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__inv_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__inv_1 -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__nand2_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__nand2_1 -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1 ############################################################ # Read Nangate library for internal power with when conditions @@ -97,7 +97,7 @@ foreach cell_name {INV_X1 INV_X2 INV_X4 BUF_X1 BUF_X2 BUF_X4 TINV_X1 TLAT_X1 CLKGATETST_X1} { catch { set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage=$lp" } @@ -123,9 +123,7 @@ report_power -digits 8 # Per-instance power foreach inst_name {buf1 inv1 and1 or1 nand1 nor1 reg1 reg2 reg3} { - catch { - report_power -instances [get_cells $inst_name] - } + report_power -instances [get_cells $inst_name] } ############################################################ @@ -137,7 +135,7 @@ foreach cell_name {sg13g2_inv_1 sg13g2_buf_1 sg13g2_nand2_1 sg13g2_nor2_1 sg13g2_and2_1 sg13g2_or2_1} { catch { set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] set area [get_property $cell area] puts "IHP $cell_name leakage=$lp area=$area" diff --git a/liberty/test/liberty_pgpin_voltage.tcl b/liberty/test/liberty_pgpin_voltage.tcl index 97874133..1c0e6761 100644 --- a/liberty/test/liberty_pgpin_voltage.tcl +++ b/liberty/test/liberty_pgpin_voltage.tcl @@ -53,20 +53,18 @@ foreach cell_name {sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__nand2_1 sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfrtp_1 sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__mux2_1 sky130_fd_sc_hd__sdfxtp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set pg_count 0 - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - if {[$port is_pwr_gnd]} { - incr pg_count - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set pg_count 0 + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + if {[$port is_pwr_gnd]} { + incr pg_count } - $port_iter finish - puts "$cell_name pg_pin_count=$pg_count" } + $port_iter finish + puts "$cell_name pg_pin_count=$pg_count" } } @@ -93,7 +91,7 @@ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_2 sky130_fd_sc_hd__fa_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage=$lp" } @@ -113,7 +111,7 @@ foreach cell_name {sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfxtp_2 sky130_fd_sc_hd__sdlclkp_1 sky130_fd_sc_hd__dlclkp_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] set area [get_property $cell area] puts "$cell_name leakage=$lp area=$area" @@ -126,11 +124,11 @@ foreach cell_name {sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfxtp_2 ############################################################ puts "--- detailed cell reports with pg_pin ---" -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__inv_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfrtp_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_1} -catch {report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlclkp_1} +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__inv_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfxtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dfrtp_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__ebufn_1 +report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__dlclkp_1 ############################################################ # Read IHP library (different voltage/supply naming) @@ -142,7 +140,7 @@ foreach cell_name {sg13g2_inv_1 sg13g2_buf_1 sg13g2_nand2_1 sg13g2_dfrbp_1 sg13g2_dlhq_1} { catch { set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] set area [get_property $cell area] puts "IHP $cell_name leakage=$lp area=$area" diff --git a/liberty/test/liberty_power.tcl b/liberty/test/liberty_power.tcl index 93eb8492..31b924b8 100644 --- a/liberty/test/liberty_power.tcl +++ b/liberty/test/liberty_power.tcl @@ -63,9 +63,9 @@ set nand_cell [get_lib_cell NangateOpenCellLibrary/NAND2_X1] catch { puts "NAND2_X1 leakage_power: [get_property $nand_cell cell_leakage_power]" } # Area property -catch { puts "INV_X1 area: [get_property $inv_cell area]" } -catch { puts "BUF_X1 area: [get_property $buf_cell area]" } -catch { puts "DFF_X1 area: [get_property $dff_cell area]" } +puts "INV_X1 area: [get_property $inv_cell area]" +puts "BUF_X1 area: [get_property $buf_cell area]" +puts "DFF_X1 area: [get_property $dff_cell area]" ############################################################ # Cell properties - is_buffer, is_inverter, etc. @@ -94,7 +94,7 @@ read_liberty ../../test/sky130hd/sky130hd_tt.lib # Query sky130 cell leakage powers set sky_inv [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__inv_1] catch { puts "sky130 inv leakage: [get_property $sky_inv cell_leakage_power]" } -catch { puts "sky130 inv area: [get_property $sky_inv area]" } +puts "sky130 inv area: [get_property $sky_inv area]" # Write sky130 liberty set outfile2 [make_result_file liberty_power_write_sky130.lib] @@ -108,7 +108,7 @@ read_liberty ../../test/ihp-sg13g2/sg13g2_stdcell_typ_1p20V_25C.lib set ihp_inv [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/sg13g2_inv_1] catch { puts "IHP inv leakage: [get_property $ihp_inv cell_leakage_power]" } -catch { puts "IHP inv area: [get_property $ihp_inv area]" } +puts "IHP inv area: [get_property $ihp_inv area]" ############################################################ # Read ASAP7 CCSN library (CCS timing + power models) @@ -129,4 +129,4 @@ read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib set asap7_dff [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DFFHQNx1_ASAP7_75t_R] catch { puts "ASAP7 DFF leakage: [get_property $asap7_dff cell_leakage_power]" } -catch { puts "ASAP7 DFF area: [get_property $asap7_dff area]" } +puts "ASAP7 DFF area: [get_property $asap7_dff area]" diff --git a/liberty/test/liberty_scan_signal_types.tcl b/liberty/test/liberty_scan_signal_types.tcl index 2a091ac6..d8658e73 100644 --- a/liberty/test/liberty_scan_signal_types.tcl +++ b/liberty/test/liberty_scan_signal_types.tcl @@ -17,14 +17,14 @@ foreach cell_name {sky130_fd_sc_hd__sdfxtp_1 sky130_fd_sc_hd__sdfxtp_2 sky130_fd_sc_hd__sdfxtp_4} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] set lp [get_property $cell cell_leakage_power] puts "$cell_name area=$area leakage=$lp" # Check test_cell set tc [$cell test_cell] - if {$tc != "NULL"} { + if {$tc != "NULL" && $tc ne ""} { puts " has test_cell: yes" } else { puts " has test_cell: no" @@ -51,12 +51,12 @@ foreach cell_name {sky130_fd_sc_hd__sdfxtp_1 sky130_fd_sc_hd__sdfxtp_2 foreach cell_name {sky130_fd_sc_hd__sdfxbp_1 sky130_fd_sc_hd__sdfxbp_2} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] puts "$cell_name area=$area" set tc [$cell test_cell] - if {$tc != "NULL"} { + if {$tc != "NULL" && $tc ne ""} { puts " has test_cell: yes" } else { puts " has test_cell: no" @@ -82,12 +82,12 @@ foreach cell_name {sky130_fd_sc_hd__sdfrtp_1 sky130_fd_sc_hd__sdfrtp_2 sky130_fd_sc_hd__sdfrtp_4} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] puts "$cell_name area=$area" set tc [$cell test_cell] - if {$tc != "NULL"} { + if {$tc != "NULL" && $tc ne ""} { puts " has test_cell: yes" } else { puts " has test_cell: no" @@ -113,7 +113,7 @@ foreach cell_name {sky130_fd_sc_hd__sdfstp_1 sky130_fd_sc_hd__sdfstp_2 sky130_fd_sc_hd__sdfstp_4} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set area [get_property $cell area] puts "$cell_name area=$area" @@ -141,7 +141,7 @@ foreach cell_name {sky130_fd_sc_hd__sdfxtp_1 sky130_fd_sc_hd__sdfrtp_1 sky130_fd_sc_hd__sdfstp_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "$cell_name arc_sets = $arc_count" @@ -162,7 +162,7 @@ read_liberty ../../test/nangate45/Nangate45_typ.lib foreach cell_name {SDFF_X1 SDFF_X2 SDFFR_X1 SDFFS_X1 SDFFRS_X1} { catch { set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set tc [$cell test_cell] puts "$cell_name test_cell=[expr {$tc != "NULL" ? "yes" : "no"}]" @@ -183,7 +183,7 @@ foreach cell_name {SDFF_X1 SDFF_X2 SDFFR_X1 SDFFS_X1 SDFFRS_X1} { # Nangate CLKGATETST cell (clock gate test) catch { set cell [get_lib_cell NangateOpenCellLibrary/CLKGATETST_X1] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set tc [$cell test_cell] set area [get_property $cell area] puts "CLKGATETST_X1 area=$area test_cell=[expr {$tc != "NULL" ? "yes" : "no"}]" @@ -203,7 +203,7 @@ read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib # ASAP7 ICG cell has statetable (exercises clock gate paths) catch { set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/ICGx1_ASAP7_75t_R] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] puts "ASAP7 ICGx1 arc_sets = [llength $arcs]" foreach arc $arcs { @@ -217,7 +217,7 @@ foreach cell_name {DFFHQNx1_ASAP7_75t_R DFFHQx1_ASAP7_75t_R DFFHQNx2_ASAP7_75t_R DFFHQx2_ASAP7_75t_R} { catch { set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] puts "$cell_name arcs=[llength $arcs]" foreach arc $arcs { diff --git a/liberty/test/liberty_seq_scan_bus.tcl b/liberty/test/liberty_seq_scan_bus.tcl index b7fcb534..23cd9e96 100644 --- a/liberty/test/liberty_seq_scan_bus.tcl +++ b/liberty/test/liberty_seq_scan_bus.tcl @@ -18,27 +18,23 @@ puts "sdfxtp_1 area = $sdf_area" # Check test_cell exists set tc [$sdf_cell test_cell] -if {$tc != "NULL"} { +if {$tc != "NULL" && $tc ne ""} { } else { } # Query scan ports foreach port_name {SCD SCE CLK D Q} { - catch { - set port [$sdf_cell find_liberty_port $port_name] - if {$port != "NULL"} { - set dir [sta::liberty_port_direction $port] - puts "sdfxtp_1/$port_name dir=$dir" - } + set port [$sdf_cell find_liberty_port $port_name] + if {$port != "NULL" && $port ne ""} { + set dir [sta::liberty_port_direction $port] + puts "sdfxtp_1/$port_name dir=$dir" } } # Another scan cell -catch { - set sdf_cell2 [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxbp_1] - set area2 [get_property $sdf_cell2 area] - puts "sdfxbp_1 area = $area2" -} +set sdf_cell2 [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfxbp_1] +set area2 [get_property $sdf_cell2 area] +puts "sdfxbp_1 area = $area2" ############################################################ # Query tristate buffer cells (exercises three_state parsing) @@ -51,7 +47,7 @@ foreach cell_name {sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__ebufn_2 puts "$cell_name area = $area" # Query tristate enable function set z_port [$cell find_liberty_port "Z"] - if {$z_port != "NULL"} { + if {$z_port != "NULL" && $z_port ne ""} { set tri_en [$z_port tristate_enable] puts "$cell_name Z tristate_enable = $tri_en" } @@ -63,12 +59,10 @@ foreach cell_name {sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__ebufn_2 ############################################################ foreach cell_name {sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__dlxtn_1 sky130_fd_sc_hd__dlxbn_1 sky130_fd_sc_hd__dlxbp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set area [get_property $cell area] - puts "$cell_name area = $area" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set area [get_property $cell area] + puts "$cell_name area = $area" } } @@ -77,14 +71,12 @@ foreach cell_name {sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__dlxtn_1 ############################################################ foreach cell_name {sky130_fd_sc_hd__dfrtp_1 sky130_fd_sc_hd__dfstp_1 sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfbbp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set area [get_property $cell area] - set is_buf [$cell is_buffer] - set is_inv [$cell is_inverter] - puts "$cell_name area=$area is_buf=$is_buf is_inv=$is_inv" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set area [get_property $cell area] + set is_buf [$cell is_buffer] + set is_inv [$cell is_inverter] + puts "$cell_name area=$area is_buf=$is_buf is_inv=$is_inv" } } @@ -96,7 +88,7 @@ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__dfxtp_1} { catch { set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set lp [get_property $cell cell_leakage_power] puts "$cell_name leakage = $lp" } @@ -109,20 +101,18 @@ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__buf_1 foreach cell_name {sky130_fd_sc_hd__and2_1 sky130_fd_sc_hd__or2_1 sky130_fd_sc_hd__xor2_1 sky130_fd_sc_hd__xnor2_1 sky130_fd_sc_hd__mux2_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - set dir [sta::liberty_port_direction $port] - set func [$port function] - if {$func != ""} { - puts "$cell_name/[get_name $port] dir=$dir func=$func" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + set dir [sta::liberty_port_direction $port] + set func [$port function] + if {$func != ""} { + puts "$cell_name/[get_name $port] dir=$dir func=$func" } - $port_iter finish } + $port_iter finish } } @@ -136,19 +126,17 @@ read_liberty ../../test/nangate45/Nangate45_typ.lib ############################################################ foreach cell_name {INV_X1 INV_X2 INV_X4 BUF_X1 BUF_X2 BUF_X4 NAND2_X1 NOR2_X1 AOI21_X1 OAI21_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set port_iter [$cell liberty_port_iterator] - while {[$port_iter has_next]} { - set port [$port_iter next] - set dir [sta::liberty_port_direction $port] - if {$dir == "input"} { - set cap [get_property $port capacitance] - puts "$cell_name/[get_name $port] cap=$cap" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set port_iter [$cell liberty_port_iterator] + while {[$port_iter has_next]} { + set port [$port_iter next] + set dir [sta::liberty_port_direction $port] + if {$dir == "input"} { + set cap [get_property $port capacitance] + puts "$cell_name/[get_name $port] cap=$cap" } - $port_iter finish } + $port_iter finish } ############################################################ @@ -157,7 +145,7 @@ foreach cell_name {INV_X1 INV_X2 INV_X4 BUF_X1 BUF_X2 BUF_X4 foreach cell_name {DFF_X1 DFFR_X1 DFFS_X1 DFFRS_X1} { catch { set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "$cell_name arc_sets = $arc_count" @@ -179,7 +167,7 @@ read_liberty ../../test/nangate45/fakeram45_64x7.lib # Query bus ports catch { set cell [get_lib_cell fakeram45_64x7/fakeram45_64x7] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set port_iter [$cell liberty_port_iterator] while {[$port_iter has_next]} { set port [$port_iter next] @@ -212,7 +200,7 @@ read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib # Query ASAP7 latch cells catch { set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DLLx1_ASAP7_75t_R] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "DLLx1 arc_sets = $arc_count" @@ -225,7 +213,7 @@ catch { # Query ICG (Integrated Clock Gate) cell with statetable catch { set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/ICGx1_ASAP7_75t_R] - if {$cell != "NULL"} { + if {$cell != "NULL" && $cell ne ""} { set arcs [$cell timing_arc_sets] set arc_count [llength $arcs] puts "ICGx1 arc_sets = $arc_count" diff --git a/liberty/test/liberty_sky130_corners.ok b/liberty/test/liberty_sky130_corners.ok index 65af8fd8..62d21156 100644 --- a/liberty/test/liberty_sky130_corners.ok +++ b/liberty/test/liberty_sky130_corners.ok @@ -1,7 +1,122 @@ -Warning: ../../test/sky130hs/sky130_fd_sc_hs__tt_025C_1v80.lib line 1, library sky130_fd_sc_hs__tt_025C_1v80 already exists. +--- Fast corner, max --- +Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: out1 (output port clocked by clk) +Path Group: clk +Path Type: max +Corner: fast + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg1/CLK (sky130_fd_sc_hd__dfxtp_1) + 0.18 0.18 v reg1/Q (sky130_fd_sc_hd__dfxtp_1) + 0.04 0.22 v buf2/X (sky130_fd_sc_hd__buf_1) + 0.00 0.22 v out1 (out) + 0.22 data arrival time + + 10.00 10.00 clock clk (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.22 data arrival time +--------------------------------------------------------- + 6.78 slack (MET) + + +--- Slow corner, max --- +Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: out1 (output port clocked by clk) +Path Group: clk +Path Type: max +Corner: slow + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg1/CLK (sky130_fd_sc_hd__dfxtp_1) + 1.20 1.20 ^ reg1/Q (sky130_fd_sc_hd__dfxtp_1) + 0.21 1.41 ^ buf2/X (sky130_fd_sc_hd__buf_1) + 0.00 1.41 ^ out1 (out) + 1.41 data arrival time + + 10.00 10.00 clock clk (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -1.41 data arrival time +--------------------------------------------------------- + 5.59 slack (MET) + + +--- Fast corner, min --- +Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: reg2 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: min +Corner: fast + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg1/CLK (sky130_fd_sc_hd__dfxtp_1) + 0.18 0.18 ^ reg1/Q (sky130_fd_sc_hd__dfxtp_1) + 0.00 0.18 ^ reg2/D (sky130_fd_sc_hd__dfxtp_1) + 0.18 data arrival time + + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 clock reconvergence pessimism + 0.00 ^ reg2/CLK (sky130_fd_sc_hd__dfxtp_1) + -0.02 -0.02 library hold time + -0.02 data required time +--------------------------------------------------------- + -0.02 data required time + -0.18 data arrival time +--------------------------------------------------------- + 0.20 slack (MET) + + +--- Slow corner, min --- +Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: reg2 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: min +Corner: slow + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg1/CLK (sky130_fd_sc_hd__dfxtp_1) + 0.93 0.93 v reg1/Q (sky130_fd_sc_hd__dfxtp_1) + 0.00 0.93 v reg2/D (sky130_fd_sc_hd__dfxtp_1) + 0.93 data arrival time + + 0.00 0.00 clock clk (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 clock reconvergence pessimism + 0.00 ^ reg2/CLK (sky130_fd_sc_hd__dfxtp_1) + -0.22 -0.22 library hold time + -0.22 data required time +--------------------------------------------------------- + -0.22 data required time + -0.93 data arrival time +--------------------------------------------------------- + 1.15 slack (MET) + + Cell sky130_fd_sc_hd__inv_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -9,8 +124,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 Y output function=!A Cell sky130_fd_sc_hd__inv_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -18,8 +133,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 Y output function=!A Cell sky130_fd_sc_hd__inv_4 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -27,8 +142,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.01-0.01 Y output function=!A Cell sky130_fd_sc_hd__buf_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -36,8 +151,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 X output function=A Cell sky130_fd_sc_hd__buf_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -45,8 +160,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 X output function=A Cell sky130_fd_sc_hd__buf_4 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -54,8 +169,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 X output function=A Cell sky130_fd_sc_hd__nand2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -64,8 +179,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 Y output function=!A+!B Cell sky130_fd_sc_hd__nand3_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -75,8 +190,8 @@ File ../../test/sky130hd/sky130hd_tt.lib C input 0.00-0.00 Y output function=(!A+!B)+!C Cell sky130_fd_sc_hd__nand4_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -87,8 +202,8 @@ File ../../test/sky130hd/sky130hd_tt.lib D input 0.00-0.00 Y output function=((!A+!B)+!C)+!D Cell sky130_fd_sc_hd__nor2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -97,8 +212,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 Y output function=!A*!B Cell sky130_fd_sc_hd__nor3_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -108,8 +223,8 @@ File ../../test/sky130hd/sky130hd_tt.lib C input 0.00-0.00 Y output function=(!A*!B)*!C Cell sky130_fd_sc_hd__nor4_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -120,8 +235,8 @@ File ../../test/sky130hd/sky130hd_tt.lib D input 0.00-0.00 Y output function=((!A*!B)*!C)*!D Cell sky130_fd_sc_hd__and2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -130,8 +245,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 X output function=A*B Cell sky130_fd_sc_hd__and3_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -141,8 +256,8 @@ File ../../test/sky130hd/sky130hd_tt.lib C input 0.00-0.00 X output function=(A*B)*C Cell sky130_fd_sc_hd__and4_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -153,8 +268,8 @@ File ../../test/sky130hd/sky130hd_tt.lib D input 0.00-0.00 X output function=((A*B)*C)*D Cell sky130_fd_sc_hd__or2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -163,8 +278,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 X output function=A+B Cell sky130_fd_sc_hd__or3_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -174,8 +289,8 @@ File ../../test/sky130hd/sky130hd_tt.lib C input 0.00-0.00 X output function=(A+B)+C Cell sky130_fd_sc_hd__or4_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -186,8 +301,8 @@ File ../../test/sky130hd/sky130hd_tt.lib D input 0.00-0.00 X output function=((A+B)+C)+D Cell sky130_fd_sc_hd__xor2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -196,8 +311,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 X output function=(A*!B)+(!A*B) Cell sky130_fd_sc_hd__xnor2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -206,8 +321,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B input 0.00-0.00 Y output function=(!A*!B)+(A*B) Cell sky130_fd_sc_hd__a21o_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -217,8 +332,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B1 input 0.00-0.00 X output function=(A1*A2)+B1 Cell sky130_fd_sc_hd__a21oi_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -228,8 +343,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B1 input 0.00-0.00 Y output function=(!A1*!B1)+(!A2*!B1) Cell sky130_fd_sc_hd__a22o_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -240,8 +355,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B2 input 0.00-0.00 X output function=(B1*B2)+(A1*A2) Cell sky130_fd_sc_hd__a22oi_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -252,8 +367,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B2 input 0.00-0.00 Y output function=(((!A1*!B1)+(!A1*!B2))+(!A2*!B1))+(!A2*!B2) Cell sky130_fd_sc_hd__o21a_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -263,8 +378,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B1 input 0.00-0.00 X output function=(A1*B1)+(A2*B1) Cell sky130_fd_sc_hd__o21ai_0 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -274,8 +389,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B1 input 0.00-0.00 Y output function=(!A1*!A2)+!B1 Cell sky130_fd_sc_hd__o22a_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -286,8 +401,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B2 input 0.00-0.00 X output function=(((A1*B1)+(A2*B1))+(A1*B2))+(A2*B2) Cell sky130_fd_sc_hd__o22ai_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -298,8 +413,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B2 input 0.00-0.00 Y output function=(!B1*!B2)+(!A1*!A2) Cell sky130_fd_sc_hd__a31o_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -310,8 +425,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B1 input 0.00-0.00 X output function=((A1*A2)*A3)+B1 Cell sky130_fd_sc_hd__a32o_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -323,8 +438,8 @@ File ../../test/sky130hd/sky130hd_tt.lib B2 input 0.00-0.00 X output function=((A1*A2)*A3)+(B1*B2) Cell sky130_fd_sc_hd__mux2_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -334,8 +449,8 @@ File ../../test/sky130hd/sky130hd_tt.lib S input 0.00-0.00 X output function=(A0*!S)+(A1*S) Cell sky130_fd_sc_hd__mux4_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -348,8 +463,8 @@ File ../../test/sky130hd/sky130hd_tt.lib S1 input 0.00-0.00 X output function=((((A0*!S0)*!S1)+((A1*S0)*!S1))+((A2*!S0)*S1))+((A3*S0)*S1) Cell sky130_fd_sc_hd__fa_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -360,19 +475,19 @@ File ../../test/sky130hd/sky130hd_tt.lib COUT output function=((A*B)+(A*CIN))+(B*CIN) SUM output function=((((A*!B)*!CIN)+((!A*B)*!CIN))+((!A*!B)*CIN))+((A*B)*CIN) Cell sky130_fd_sc_hd__ha_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown VPWR power A input 0.00-0.00 - B input 0.00-0.00 + B input 0.00 COUT output function=A*B SUM output function=(A*!B)+(!A*B) Cell sky130_fd_sc_hd__maj3_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -382,8 +497,8 @@ File ../../test/sky130hd/sky130hd_tt.lib C input 0.00-0.00 X output function=((A*B)+(A*C))+(B*C) Cell sky130_fd_sc_hd__dfxtp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -394,8 +509,8 @@ File ../../test/sky130hd/sky130hd_tt.lib D input 0.00-0.00 Q output function=IQ Cell sky130_fd_sc_hd__dfrtp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -407,8 +522,8 @@ File ../../test/sky130hd/sky130hd_tt.lib Q output function=IQ RESET_B input 0.00-0.00 Cell sky130_fd_sc_hd__dfstp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -420,8 +535,8 @@ File ../../test/sky130hd/sky130hd_tt.lib Q output function=IQ SET_B input 0.00-0.00 Cell sky130_fd_sc_hd__dfbbp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -435,8 +550,8 @@ File ../../test/sky130hd/sky130hd_tt.lib RESET_B input 0.00-0.00 SET_B input 0.00-0.00 Cell sky130_fd_sc_hd__dlxtp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -447,8 +562,8 @@ File ../../test/sky130hd/sky130hd_tt.lib GATE input 0.00-0.00 Q output function=IQ Cell sky130_fd_sc_hd__dlxtn_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -459,8 +574,8 @@ File ../../test/sky130hd/sky130hd_tt.lib GATE_N input 0.00-0.00 Q output function=IQ Cell sky130_fd_sc_hd__sdfxtp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -473,8 +588,8 @@ File ../../test/sky130hd/sky130hd_tt.lib SCD input 0.00-0.00 SCE input 0.00-0.00 Cell sky130_fd_sc_hd__sdfxbp_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib IQ internal IQ_N internal VGND ground @@ -488,8 +603,8 @@ File ../../test/sky130hd/sky130hd_tt.lib SCD input 0.00-0.00 SCE input 0.00-0.00 Cell sky130_fd_sc_hd__ebufn_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -498,8 +613,8 @@ File ../../test/sky130hd/sky130hd_tt.lib TE_B input 0.00-0.00 Z tristate enable=!TE_B function=A 0.00 Cell sky130_fd_sc_hd__ebufn_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -508,8 +623,8 @@ File ../../test/sky130hd/sky130hd_tt.lib TE_B input 0.00-0.00 Z tristate enable=!TE_B function=A 0.00 Cell sky130_fd_sc_hd__clkbuf_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -517,8 +632,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 X output function=A Cell sky130_fd_sc_hd__clkbuf_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -526,8 +641,8 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 X output function=A Cell sky130_fd_sc_hd__clkinv_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -535,17 +650,17 @@ File ../../test/sky130hd/sky130hd_tt.lib A input 0.00-0.00 Y output function=!A Cell sky130_fd_sc_hd__clkinv_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown VPWR power - A input 0.00-0.00 + A input 0.00-0.01 Y output function=!A Cell sky130_fd_sc_hd__conb_1 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown @@ -553,55 +668,32 @@ File ../../test/sky130hd/sky130hd_tt.lib HI output function=1 LO output function=0 Cell sky130_fd_sc_hd__diode_2 -Library sky130_fd_sc_hd__tt_025C_1v80 -File ../../test/sky130hd/sky130hd_tt.lib +Library sky130_fd_sc_hd__ff_n40C_1v95 +File ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib VGND ground VNB unknown VPB unknown VPWR power DIODE input 0.00-0.00 -Warning: liberty_sky130_corners.tcl line 1, liberty cell 'sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__fill_1' not found. -sky130_fd_sc_hd__inv_1/A: cap=0.002390 dir=input +sky130_fd_sc_hd__inv_1: area=3.753600 dont_use=0 +sky130_fd_sc_hd__buf_1: area=3.753600 dont_use=0 +sky130_fd_sc_hd__dfxtp_1: area=20.019199 dont_use=0 +sky130_fd_sc_hd__dlxtp_1: area=15.014400 dont_use=0 +sky130_fd_sc_hd__sdfxtp_1: area=26.275200 dont_use=0 +sky130_fd_sc_hd__ebufn_1: area=10.009600 dont_use=0 +sky130_fd_sc_hd__mux2_1: area=11.260800 dont_use=0 +sky130_fd_sc_hd__fa_1: area=20.019199 dont_use=0 +sky130_fd_sc_hd__inv_1/A: cap=0.002392 dir=input sky130_fd_sc_hd__inv_1/Y: cap=0.000000 dir=output -sky130_fd_sc_hd__buf_1/A: cap=0.002191 dir=input +sky130_fd_sc_hd__buf_1/A: cap=0.002258 dir=input sky130_fd_sc_hd__buf_1/X: cap=0.000000 dir=output -sky130_fd_sc_hd__nand2_1/A: cap=0.002375 dir=input -sky130_fd_sc_hd__nand2_1/B: cap=0.002428 dir=input +sky130_fd_sc_hd__nand2_1/A: cap=0.002387 dir=input +sky130_fd_sc_hd__nand2_1/B: cap=0.002422 dir=input sky130_fd_sc_hd__nand2_1/Y: cap=0.000000 dir=output -sky130_fd_sc_hd__dfxtp_1/CLK: cap=0.001877 dir=input -sky130_fd_sc_hd__dfxtp_1/D: cap=0.001674 dir=input +sky130_fd_sc_hd__dfxtp_1/CLK: cap=0.001937 dir=input +sky130_fd_sc_hd__dfxtp_1/D: cap=0.001748 dir=input sky130_fd_sc_hd__dfxtp_1/Q: cap=0.000000 dir=output -sky130_fd_sc_hd__dfrtp_1/CLK: cap=0.001871 dir=input -sky130_fd_sc_hd__dfrtp_1/D: cap=0.002006 dir=input -sky130_fd_sc_hd__dfrtp_1/RESET_B: cap=0.003632 dir=input +sky130_fd_sc_hd__dfrtp_1/CLK: cap=0.001951 dir=input +sky130_fd_sc_hd__dfrtp_1/D: cap=0.002086 dir=input +sky130_fd_sc_hd__dfrtp_1/RESET_B: cap=0.003621 dir=input sky130_fd_sc_hd__dfrtp_1/Q: cap=0.000000 dir=output -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13156, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13189, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13222, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13255, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13288, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13321, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 13354, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 14748, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 14781, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz line 14814, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13156, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13189, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13222, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13255, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13288, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13321, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 13354, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 14748, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 14781, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz line 14814, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13156, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13189, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13222, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13255, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13288, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13321, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 13354, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 14748, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 14781, timing group from output port. -Warning: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz line 14814, timing group from output port. diff --git a/liberty/test/liberty_sky130_corners.tcl b/liberty/test/liberty_sky130_corners.tcl index 5a95d481..d6f675e5 100644 --- a/liberty/test/liberty_sky130_corners.tcl +++ b/liberty/test/liberty_sky130_corners.tcl @@ -1,28 +1,47 @@ -# Test multi-corner library reading and Sky130HS features. +# Test multi-corner library reading and timing analysis with Sky130HD. source ../../test/helpers.tcl ############################################################ -# Read Sky130HD all corners +# Define corners and read Sky130HD libraries per corner ############################################################ -read_liberty ../../test/sky130hd/sky130hd_tt.lib +define_corners fast slow -read_liberty ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib - -read_liberty ../../test/sky130hd/sky130_fd_sc_hd__ss_n40C_1v40.lib +read_liberty -corner fast ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib +read_liberty -corner slow ../../test/sky130hd/sky130_fd_sc_hd__ss_n40C_1v40.lib ############################################################ -# Read Sky130HS +# Read design and link ############################################################ -read_liberty ../../test/sky130hs/sky130hs_tt.lib - -read_liberty ../../test/sky130hs/sky130_fd_sc_hs__tt_025C_1v80.lib +read_verilog sky130_corners_test.v +link_design sky130_corners_test ############################################################ -# Comprehensive cell reports across PDKs -# Exercises: all timing model, power model, and arc code +# Create constraints ############################################################ +create_clock -name clk -period 10 [get_ports clk] +set_input_delay -clock clk 2.0 [get_ports in1] +set_input_delay -clock clk 2.0 [get_ports in2] +set_output_delay -clock clk 3.0 [get_ports out1] +set_output_delay -clock clk 3.0 [get_ports out2] -# Sky130HD cells - comprehensive reporting +############################################################ +# Report timing per corner (shows different delays per corner) +############################################################ +puts "--- Fast corner, max ---" +report_checks -corner fast -path_delay max + +puts "--- Slow corner, max ---" +report_checks -corner slow -path_delay max + +puts "--- Fast corner, min ---" +report_checks -corner fast -path_delay min + +puts "--- Slow corner, min ---" +report_checks -corner slow -path_delay min + +############################################################ +# Comprehensive cell reports - fast corner library +############################################################ set sky130_cells_to_report { sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_2 sky130_fd_sc_hd__inv_4 sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_4 @@ -46,33 +65,28 @@ set sky130_cells_to_report { sky130_fd_sc_hd__clkbuf_1 sky130_fd_sc_hd__clkbuf_2 sky130_fd_sc_hd__clkinv_1 sky130_fd_sc_hd__clkinv_2 sky130_fd_sc_hd__conb_1 - sky130_fd_sc_hd__diode_2 sky130_fd_sc_hd__fill_1 + sky130_fd_sc_hd__diode_2 } foreach cell_name $sky130_cells_to_report { - catch { - report_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name - } + report_lib_cell sky130_fd_sc_hd__ff_n40C_1v95/$cell_name } ############################################################ -# Cell property queries on Sky130 +# Cell property queries - slow corner library ############################################################ foreach cell_name {sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__sdfxtp_1 sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__mux2_1 sky130_fd_sc_hd__fa_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - set area [get_property $cell area] - set du [get_property $cell dont_use] - set lp [get_property $cell cell_leakage_power] - puts "$cell_name: area=$area dont_use=$du leakage=$lp" - } + set cell [get_lib_cell sky130_fd_sc_hd__ss_n40C_1v40/$cell_name] + set area [get_property $cell area] + set du [get_property $cell dont_use] + puts "$cell_name: area=$area dont_use=$du" } ############################################################ -# Pin capacitance queries on Sky130 +# Pin capacitance queries - fast corner library ############################################################ foreach {cell_name pin_name} { sky130_fd_sc_hd__inv_1 A @@ -90,53 +104,17 @@ foreach {cell_name pin_name} { sky130_fd_sc_hd__dfrtp_1 RESET_B sky130_fd_sc_hd__dfrtp_1 Q } { - catch { - set pin [get_lib_pin sky130_fd_sc_hd__tt_025C_1v80/$cell_name/$pin_name] - set cap [get_property $pin capacitance] - set dir [sta::liberty_port_direction $pin] - puts "$cell_name/$pin_name: cap=$cap dir=$dir" - } + set pin [get_lib_pin sky130_fd_sc_hd__ff_n40C_1v95/$cell_name/$pin_name] + set cap [get_property $pin capacitance] + set dir [sta::liberty_port_direction $pin] + puts "$cell_name/$pin_name: cap=$cap dir=$dir" } ############################################################ -# Write all libraries to exercise all writer paths +# Write libraries to exercise writer paths ############################################################ -set outfile1 [make_result_file liberty_sky130_hd_tt.lib] -sta::write_liberty sky130_fd_sc_hd__tt_025C_1v80 $outfile1 +set outfile1 [make_result_file liberty_sky130_hd_ff.lib] +sta::write_liberty sky130_fd_sc_hd__ff_n40C_1v95 $outfile1 -catch { - set outfile2 [make_result_file liberty_sky130_hs_tt.lib] - sta::write_liberty sky130_fd_sc_hs__tt_025C_1v80 $outfile2 -} - -############################################################ -# Read ASAP7 with various Vt combos to stress LibertyReader -############################################################ -read_liberty ../../test/asap7/asap7sc7p5t_AO_LVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_AO_SLVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_OA_LVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_OA_SLVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_SIMPLE_LVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_SIMPLE_SLVT_FF_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_INVBUF_LVT_TT_nldm_220122.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_INVBUF_SLVT_TT_nldm_220122.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_INVBUF_RVT_TT_nldm_220122.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_INVBUF_RVT_SS_nldm_220122.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_AO_RVT_SS_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_OA_RVT_SS_nldm_211120.lib.gz - -read_liberty ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_SS_nldm_211120.lib.gz - -# SRAM macro -read_liberty ../../test/asap7/fakeram7_256x32.lib +set outfile2 [make_result_file liberty_sky130_hd_ss.lib] +sta::write_liberty sky130_fd_sc_hd__ss_n40C_1v40 $outfile2 diff --git a/liberty/test/liberty_timing_types_deep.tcl b/liberty/test/liberty_timing_types_deep.tcl index 76d68d6d..3175d7f7 100644 --- a/liberty/test/liberty_timing_types_deep.tcl +++ b/liberty/test/liberty_timing_types_deep.tcl @@ -38,23 +38,19 @@ foreach arc $arcs { } # sdfrtp has scan + async reset -catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfrtp_1] - set arcs [$cell timing_arc_sets] - puts "sdfrtp_1 arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } +set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfrtp_1] +set arcs [$cell timing_arc_sets] +puts "sdfrtp_1 arc_sets = [llength $arcs]" +foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } # sdfstp has scan + async set -catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfstp_1] - set arcs [$cell timing_arc_sets] - puts "sdfstp_1 arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } +set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/sky130_fd_sc_hd__sdfstp_1] +set arcs [$cell timing_arc_sets] +puts "sdfstp_1 arc_sets = [llength $arcs]" +foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } ############################################################ @@ -64,13 +60,11 @@ puts "--- tristate cell timing arcs ---" foreach cell_name {sky130_fd_sc_hd__ebufn_1 sky130_fd_sc_hd__ebufn_2 sky130_fd_sc_hd__ebufn_4 sky130_fd_sc_hd__ebufn_8} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } @@ -81,14 +75,12 @@ puts "--- clock gate cell timing arcs ---" foreach cell_name {sky130_fd_sc_hd__dlclkp_1 sky130_fd_sc_hd__dlclkp_2 sky130_fd_sc_hd__sdlclkp_1 sky130_fd_sc_hd__sdlclkp_2} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } } @@ -100,14 +92,12 @@ puts "--- latch cell timing arcs ---" foreach cell_name {sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__dlxtn_1 sky130_fd_sc_hd__dlxbn_1 sky130_fd_sc_hd__dlxbp_1} { - catch { - set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] - if {$cell != "NULL"} { - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } } @@ -117,31 +107,25 @@ foreach cell_name {sky130_fd_sc_hd__dlxtp_1 sky130_fd_sc_hd__dlxtn_1 ############################################################ read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib -catch { - set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DFFHQNx1_ASAP7_75t_R] - set arcs [$cell timing_arc_sets] - puts "DFFHQNx1 arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } +set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DFFHQNx1_ASAP7_75t_R] +set arcs [$cell timing_arc_sets] +puts "DFFHQNx1 arc_sets = [llength $arcs]" +foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } -catch { - set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DLLx1_ASAP7_75t_R] - set arcs [$cell timing_arc_sets] - puts "DLLx1 arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } +set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/DLLx1_ASAP7_75t_R] +set arcs [$cell timing_arc_sets] +puts "DLLx1 arc_sets = [llength $arcs]" +foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } -catch { - set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/ICGx1_ASAP7_75t_R] - set arcs [$cell timing_arc_sets] - puts "ICGx1 arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } +set cell [get_lib_cell asap7sc7p5t_SEQ_RVT_FF_nldm_220123/ICGx1_ASAP7_75t_R] +set arcs [$cell timing_arc_sets] +puts "ICGx1 arc_sets = [llength $arcs]" +foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } ############################################################ @@ -150,40 +134,34 @@ catch { read_liberty ../../test/ihp-sg13g2/sg13g2_stdcell_typ_1p20V_25C.lib foreach cell_name {sg13g2_dlhq_1 sg13g2_dllq_1} { - catch { - set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } } foreach cell_name {sg13g2_dfrbp_1 sg13g2_dfrbp_2} { - catch { - set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } } foreach cell_name {sg13g2_sdfbbp_1} { - catch { - set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] - if {$cell != "NULL"} { - set arcs [$cell timing_arc_sets] - puts "$cell_name arc_sets = [llength $arcs]" - foreach arc $arcs { - puts " [$arc full_name] role=[$arc role]" - } + set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name] + if {$cell != "NULL" && $cell ne ""} { + set arcs [$cell timing_arc_sets] + puts "$cell_name arc_sets = [llength $arcs]" + foreach arc $arcs { + puts " [$arc full_name] role=[$arc role]" } } } @@ -220,13 +198,9 @@ read_liberty ../../test/sky130hd/sky130_fd_sc_hd__ff_n40C_1v95.lib read_liberty ../../test/sky130hd/sky130_fd_sc_hd__ss_n40C_1v40.lib -catch { - report_lib_cell sky130_fd_sc_hd__ff_n40C_1v95/sky130_fd_sc_hd__dfrtp_1 -} +report_lib_cell sky130_fd_sc_hd__ff_n40C_1v95/sky130_fd_sc_hd__dfrtp_1 -catch { - report_lib_cell sky130_fd_sc_hd__ss_n40C_1v40/sky130_fd_sc_hd__dfrtp_1 -} +report_lib_cell sky130_fd_sc_hd__ss_n40C_1v40/sky130_fd_sc_hd__dfrtp_1 ############################################################ # Write liberty diff --git a/liberty/test/liberty_wireload.ok b/liberty/test/liberty_wireload.ok index d08cfa17..a919ca44 100644 --- a/liberty/test/liberty_wireload.ok +++ b/liberty/test/liberty_wireload.ok @@ -1,2 +1,338 @@ -No paths found. -No paths found. +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + +Startpoint: reg2 (rising edge-triggered flip-flop clocked by clk1) +Endpoint: out1 (output port clocked by clk1) +Path Group: clk1 +Path Type: max + + Delay Time Description +--------------------------------------------------------- + 0.00 0.00 clock clk1 (rise edge) + 0.00 0.00 clock network delay (ideal) + 0.00 0.00 ^ reg2/CK (DFF_X1) + 0.08 0.08 ^ reg2/Q (DFF_X1) + 0.00 0.08 ^ out1 (out) + 0.08 data arrival time + + 10.00 10.00 clock clk1 (rise edge) + 0.00 10.00 clock network delay (ideal) + 0.00 10.00 clock reconvergence pessimism + -3.00 7.00 output external delay + 7.00 data required time +--------------------------------------------------------- + 7.00 data required time + -0.08 data arrival time +--------------------------------------------------------- + 6.92 slack (MET) + + diff --git a/liberty/test/liberty_wireload.tcl b/liberty/test/liberty_wireload.tcl index c16d6584..6c776b88 100644 --- a/liberty/test/liberty_wireload.tcl +++ b/liberty/test/liberty_wireload.tcl @@ -12,41 +12,7 @@ read_verilog ../../sdc/test/sdc_test2.v link_design sdc_test2 ############################################################ -# Wire load model queries -############################################################ - -# Set various wire load models (Nangate has multiple) -# Nangate has 1K, 3K, 5K wireload models with different h/v ratios -set_wire_load_model -name "1K_hvratio_1_1" - -set_wire_load_model -name "1K_hvratio_1_2" - -set_wire_load_model -name "1K_hvratio_1_4" - -set_wire_load_model -name "3K_hvratio_1_1" - -set_wire_load_model -name "3K_hvratio_1_2" - -set_wire_load_model -name "3K_hvratio_1_4" - -set_wire_load_model -name "5K_hvratio_1_1" - -set_wire_load_model -name "5K_hvratio_1_2" - -set_wire_load_model -name "5K_hvratio_1_4" - -############################################################ -# Wire load mode switching (exercises wireloadModeString) -############################################################ - -set_wire_load_mode top - -set_wire_load_mode enclosed - -set_wire_load_mode segmented - -############################################################ -# Setup constraints and report +# Setup constraints (needed before report_checks) ############################################################ create_clock -name clk1 -period 10 [get_ports clk1] @@ -56,8 +22,49 @@ set_input_delay -clock clk1 2.0 [get_ports in3] set_output_delay -clock clk1 3.0 [get_ports out1] set_output_delay -clock clk1 3.0 [get_ports out2] -# Report checks with wire load -report_checks -from [get_ports in1] -to [get_ports out1] +############################################################ +# Wire load model queries - report_checks after each to show timing impact +############################################################ + +set_wire_load_model -name "1K_hvratio_1_1" +report_checks + +set_wire_load_model -name "1K_hvratio_1_2" +report_checks + +set_wire_load_model -name "1K_hvratio_1_4" +report_checks + +set_wire_load_model -name "3K_hvratio_1_1" +report_checks + +set_wire_load_model -name "3K_hvratio_1_2" +report_checks + +set_wire_load_model -name "3K_hvratio_1_4" +report_checks + +set_wire_load_model -name "5K_hvratio_1_1" +report_checks + +set_wire_load_model -name "5K_hvratio_1_2" +report_checks + +set_wire_load_model -name "5K_hvratio_1_4" +report_checks + +############################################################ +# Wire load mode switching (exercises wireloadModeString) +############################################################ + +set_wire_load_mode top +report_checks + +set_wire_load_mode enclosed +report_checks + +set_wire_load_mode segmented +report_checks ############################################################ # Write SDC with wireload info @@ -105,4 +112,4 @@ sta::write_liberty sg13g2_stdcell_typ_1p20V_25C $outfile3 set_operating_conditions typical -report_checks -from [get_ports in1] -to [get_ports out1] +report_checks diff --git a/liberty/test/liberty_writer_roundtrip.tcl b/liberty/test/liberty_writer_roundtrip.tcl index 5478452b..044df57b 100644 --- a/liberty/test/liberty_writer_roundtrip.tcl +++ b/liberty/test/liberty_writer_roundtrip.tcl @@ -82,58 +82,48 @@ foreach cell_name {INV_X1 BUF_X1 NAND2_X1 NOR2_X1 AND2_X1 OR2_X1 # Sequential cells (rising_edge, setup_rising, hold_rising, etc.) foreach cell_name {DFF_X1 DFF_X2 DFFR_X1 DFFS_X1 DFFRS_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set arc_sets [$cell timing_arc_sets] - puts "$cell_name: [llength $arc_sets] arc sets" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set arc_sets [$cell timing_arc_sets] + puts "$cell_name: [llength $arc_sets] arc sets" } # Tristate cells (three_state_enable, three_state_disable) foreach cell_name {TINV_X1 TBUF_X1 TBUF_X2} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set arc_sets [$cell timing_arc_sets] - puts "$cell_name: [llength $arc_sets] arc sets" - foreach arc_set $arc_sets { - set role [$arc_set role] - puts " role=$role" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set arc_sets [$cell timing_arc_sets] + puts "$cell_name: [llength $arc_sets] arc sets" + foreach arc_set $arc_sets { + set role [$arc_set role] + puts " role=$role" } } # Scan cells (exercises test_cell and scan paths) foreach cell_name {SDFF_X1 SDFFR_X1 SDFFS_X1 SDFFRS_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set arc_sets [$cell timing_arc_sets] - puts "$cell_name: [llength $arc_sets] arc sets" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set arc_sets [$cell timing_arc_sets] + puts "$cell_name: [llength $arc_sets] arc sets" } # Clock gate cell (may have min_pulse_width arcs) foreach cell_name {CLKGATETST_X1 CLKGATETST_X2 CLKGATETST_X4} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set arc_sets [$cell timing_arc_sets] - puts "$cell_name: [llength $arc_sets] arc sets" - foreach arc_set $arc_sets { - set role [$arc_set role] - puts " role=$role" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set arc_sets [$cell timing_arc_sets] + puts "$cell_name: [llength $arc_sets] arc sets" + foreach arc_set $arc_sets { + set role [$arc_set role] + puts " role=$role" } } # Latch cells (latch_enable, latch_d_to_q) foreach cell_name {TLAT_X1} { - catch { - set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] - set arc_sets [$cell timing_arc_sets] - puts "$cell_name: [llength $arc_sets] arc sets" - foreach arc_set $arc_sets { - set role [$arc_set role] - puts " role=$role" - } + set cell [get_lib_cell NangateOpenCellLibrary/$cell_name] + set arc_sets [$cell timing_arc_sets] + puts "$cell_name: [llength $arc_sets] arc sets" + foreach arc_set $arc_sets { + set role [$arc_set role] + puts " role=$role" } } diff --git a/network/test/network_connected_pins.tcl b/network/test/network_connected_pins.tcl index 66e94628..f992b1fd 100644 --- a/network/test/network_connected_pins.tcl +++ b/network/test/network_connected_pins.tcl @@ -73,18 +73,18 @@ for {set i 0} {$i < 6} {incr i} { puts "created [llength $net_list] nets" # Connect BUF_X1 input -catch {connect_pin lifecycle_net_0 lifecycle_inst_0/A} msg +set msg [connect_pin lifecycle_net_0 lifecycle_inst_0/A] puts "connect lifecycle_inst_0/A: $msg" # Connect BUF_X1 output -catch {connect_pin lifecycle_net_1 lifecycle_inst_0/Z} msg +set msg [connect_pin lifecycle_net_1 lifecycle_inst_0/Z] puts "connect lifecycle_inst_0/Z: $msg" # Connect INV_X1 input/output -catch {connect_pin lifecycle_net_1 lifecycle_inst_3/A} msg +set msg [connect_pin lifecycle_net_1 lifecycle_inst_3/A] puts "connect lifecycle_inst_3/A: $msg" -catch {connect_pin lifecycle_net_2 lifecycle_inst_3/ZN} msg +set msg [connect_pin lifecycle_net_2 lifecycle_inst_3/ZN] puts "connect lifecycle_inst_3/ZN: $msg" # Report net with connected pins (exercises connectedPinIterator) diff --git a/network/test/network_hierarchy.tcl b/network/test/network_hierarchy.tcl index 0b849260..7a269f2e 100644 --- a/network/test/network_hierarchy.tcl +++ b/network/test/network_hierarchy.tcl @@ -70,13 +70,8 @@ set sub2_hier_pins [get_pins -hierarchical sub2/*] puts "sub2/* pins (hier): [llength $sub2_hier_pins]" # Query specific pin paths through hierarchy -catch { - set sub1_and [get_pins sub1/and_gate/A1] - puts "sub1/and_gate/A1: [get_full_name $sub1_and]" -} msg -if {[string match "*Error*" $msg] || [string match "*not found*" $msg]} { - puts "sub1/and_gate/A1: not accessible (flat network)" -} +set sub1_and [get_pins sub1/and_gate/A1] +puts "sub1/and_gate/A1: [get_full_name $sub1_and]" # Top-level instance pins (port pins) set port_pins_in [get_pins -hierarchical */A] diff --git a/network/test/network_modify.tcl b/network/test/network_modify.tcl index 1edcd05c..18c73a1a 100644 --- a/network/test/network_modify.tcl +++ b/network/test/network_modify.tcl @@ -72,7 +72,7 @@ set ref [get_property $buf1_inst ref_name] puts "buf1 ref_name after replace: $ref" puts "--- disconnect remaining new_buf pins ---" -catch {disconnect_pin new_net2 new_buf/Z} msg_disc2 +set msg_disc2 [disconnect_pin new_net2 new_buf/Z] puts "disconnect new_buf/Z: $msg_disc2" puts "--- delete_instance new_buf ---" diff --git a/network/test/network_sdc_query.tcl b/network/test/network_sdc_query.tcl index d6cd0955..65e7a9e6 100644 --- a/network/test/network_sdc_query.tcl +++ b/network/test/network_sdc_query.tcl @@ -30,38 +30,18 @@ set_input_transition 0.1 [get_ports {data_a[*] data_b[*] clk}] puts "--- bus range queries ---" # Query using range notation -catch { - set range_ports [get_ports {data_a[0:3]}] - puts "data_a\[0:3\] ports: [llength $range_ports]" -} msg -if {[string match "*Error*" $msg]} { - puts "data_a\[0:3\]: $msg" -} +set range_ports [get_ports {data_a[0:3]}] +puts "data_a\[0:3\] ports: [llength $range_ports]" -catch { - set range_ports2 [get_ports {data_a[4:7]}] - puts "data_a\[4:7\] ports: [llength $range_ports2]" -} msg -if {[string match "*Error*" $msg]} { - puts "data_a\[4:7\]: $msg" -} +set range_ports2 [get_ports {data_a[4:7]}] +puts "data_a\[4:7\] ports: [llength $range_ports2]" -catch { - set range_ports3 [get_ports {result[0:3]}] - puts "result\[0:3\] ports: [llength $range_ports3]" -} msg -if {[string match "*Error*" $msg]} { - puts "result\[0:3\]: $msg" -} +set range_ports3 [get_ports {result[0:3]}] +puts "result\[0:3\] ports: [llength $range_ports3]" # Reverse range (exercises from > to swap in findPortsMatching) -catch { - set rev_range [get_ports {data_b[7:0]}] - puts "data_b\[7:0\] ports: [llength $rev_range]" -} msg -if {[string match "*Error*" $msg]} { - puts "data_b\[7:0\]: $msg" -} +set rev_range [get_ports {data_b[7:0]}] +puts "data_b\[7:0\] ports: [llength $rev_range]" #--------------------------------------------------------------- # Test wildcard subscript queries diff --git a/parasitics/test/parasitics_annotation_query.tcl b/parasitics/test/parasitics_annotation_query.tcl index 0da6bb6d..8cd8c05f 100644 --- a/parasitics/test/parasitics_annotation_query.tcl +++ b/parasitics/test/parasitics_annotation_query.tcl @@ -26,19 +26,19 @@ set_propagated_clock {clk1 clk2 clk3} puts "--- Test 1: set and query pi model ---" # Set pi models on driver pins (both rise and fall) -catch {sta::set_pi_model u1/Y 0.005 10.0 0.003} msg +set msg [sta::set_pi_model u1/Y 0.005 10.0 0.003] puts "set_pi_model u1/Y: $msg" -catch {sta::set_pi_model u2/Y 0.008 15.0 0.005} msg +set msg [sta::set_pi_model u2/Y 0.008 15.0 0.005] puts "set_pi_model u2/Y: $msg" -catch {sta::set_pi_model r1/Q 0.002 5.0 0.001} msg +set msg [sta::set_pi_model r1/Q 0.002 5.0 0.001] puts "set_pi_model r1/Q: $msg" -catch {sta::set_pi_model r2/Q 0.003 6.0 0.002} msg +set msg [sta::set_pi_model r2/Q 0.003 6.0 0.002] puts "set_pi_model r2/Q: $msg" -catch {sta::set_pi_model r3/Q 0.001 2.0 0.001} msg +set msg [sta::set_pi_model r3/Q 0.001 2.0 0.001] puts "set_pi_model r3/Q: $msg" # Query pi models back using find_pi_elmore @@ -85,19 +85,19 @@ catch { #--------------------------------------------------------------- puts "--- Test 2: set and query elmore ---" -catch {sta::set_elmore u1/Y u2/A 0.005} msg +set msg [sta::set_elmore u1/Y u2/A 0.005] puts "set_elmore u1/Y -> u2/A: $msg" -catch {sta::set_elmore u2/Y r3/D 0.008} msg +set msg [sta::set_elmore u2/Y r3/D 0.008] puts "set_elmore u2/Y -> r3/D: $msg" -catch {sta::set_elmore r1/Q u1/A 0.003} msg +set msg [sta::set_elmore r1/Q u1/A 0.003] puts "set_elmore r1/Q -> u1/A: $msg" -catch {sta::set_elmore r2/Q u2/B 0.004} msg +set msg [sta::set_elmore r2/Q u2/B 0.004] puts "set_elmore r2/Q -> u2/B: $msg" -catch {sta::set_elmore r3/Q out 0.002} msg +set msg [sta::set_elmore r3/Q out 0.002] puts "set_elmore r3/Q -> out: $msg" # Query elmore values back @@ -169,17 +169,17 @@ report_parasitic_annotation -report_unannotated puts "--- Test 5: override manual parasitics ---" # Re-set pi model with different values -catch {sta::set_pi_model u1/Y 0.01 20.0 0.008} msg +set msg [sta::set_pi_model u1/Y 0.01 20.0 0.008] puts "re-set pi_model u1/Y: $msg" -catch {sta::set_pi_model u2/Y 0.02 30.0 0.01} msg +set msg [sta::set_pi_model u2/Y 0.02 30.0 0.01] puts "re-set pi_model u2/Y: $msg" # Re-set elmore with different values -catch {sta::set_elmore u1/Y u2/A 0.01} msg +set msg [sta::set_elmore u1/Y u2/A 0.01] puts "re-set elmore u1/Y -> u2/A: $msg" -catch {sta::set_elmore u2/Y r3/D 0.02} msg +set msg [sta::set_elmore u2/Y r3/D 0.02] puts "re-set elmore u2/Y -> r3/D: $msg" report_checks @@ -255,19 +255,19 @@ report_checks -format full_clock # report_net with SPEF parasitics foreach net_name {r1q r2q u1z u2z out in1 in2 clk1 clk2 clk3} { - catch {report_net -digits 6 $net_name} msg + report_net -digits 6 $net_name puts "report_net $net_name: done" } # Dcalc reports -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max -digits 6} msg +report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max -digits 6 puts "dcalc u1 6 digits: done" -catch {report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max -digits 4} msg +report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max -digits 4 puts "dcalc u2 4 digits: done" -catch {report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max} msg +report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max puts "dcalc r1 CK->Q: done" -catch {report_dcalc -from [get_pins r3/CLK] -to [get_pins r3/Q] -max} msg +report_dcalc -from [get_pins r3/CLK] -to [get_pins r3/Q] -max puts "dcalc r3 CK->Q: done" diff --git a/parasitics/test/parasitics_corners.tcl b/parasitics/test/parasitics_corners.tcl index cd101a2b..a479755f 100644 --- a/parasitics/test/parasitics_corners.tcl +++ b/parasitics/test/parasitics_corners.tcl @@ -59,22 +59,22 @@ report_checks -corner slow -fields {slew cap input_pins} -format full_clock #--------------------------------------------------------------- puts "--- report_dcalc per corner ---" -catch {report_dcalc -corner fast -from [get_pins u1/A] -to [get_pins u1/Y]} msg +set msg [report_dcalc -corner fast -from [get_pins u1/A] -to [get_pins u1/Y]] puts $msg -catch {report_dcalc -corner slow -from [get_pins u1/A] -to [get_pins u1/Y]} msg +set msg [report_dcalc -corner slow -from [get_pins u1/A] -to [get_pins u1/Y]] puts $msg -catch {report_dcalc -corner fast -from [get_pins u2/A] -to [get_pins u2/Y]} msg +set msg [report_dcalc -corner fast -from [get_pins u2/A] -to [get_pins u2/Y]] puts $msg -catch {report_dcalc -corner slow -from [get_pins u2/A] -to [get_pins u2/Y]} msg +set msg [report_dcalc -corner slow -from [get_pins u2/A] -to [get_pins u2/Y]] puts $msg -catch {report_dcalc -corner fast -from [get_pins r1/CLK] -to [get_pins r1/Q]} msg +set msg [report_dcalc -corner fast -from [get_pins r1/CLK] -to [get_pins r1/Q]] puts $msg -catch {report_dcalc -corner slow -from [get_pins r1/CLK] -to [get_pins r1/Q]} msg +set msg [report_dcalc -corner slow -from [get_pins r1/CLK] -to [get_pins r1/Q]] puts $msg #--------------------------------------------------------------- @@ -82,16 +82,16 @@ puts $msg #--------------------------------------------------------------- puts "--- report_net per corner ---" -catch {report_net -corner fast r1q} msg +set msg [report_net -corner fast r1q] puts $msg -catch {report_net -corner slow r1q} msg +set msg [report_net -corner slow r1q] puts $msg -catch {report_net -corner fast u2z} msg +set msg [report_net -corner fast u2z] puts $msg -catch {report_net -corner slow u2z} msg +set msg [report_net -corner slow u2z] puts $msg #--------------------------------------------------------------- diff --git a/parasitics/test/parasitics_coupling.tcl b/parasitics/test/parasitics_coupling.tcl index 4369da0d..695dafb5 100644 --- a/parasitics/test/parasitics_coupling.tcl +++ b/parasitics/test/parasitics_coupling.tcl @@ -33,23 +33,23 @@ report_parasitic_annotation -report_unannotated puts "--- set_pi_model on drivers ---" # Set pi model on u1/Y (driver of net u1z) -catch {sta::set_pi_model u1/Y 0.005 10.0 0.003} msg +set msg [sta::set_pi_model u1/Y 0.005 10.0 0.003] puts "set_pi_model u1/Y: $msg" # Set pi model on u2/Y (driver of net u2z) -catch {sta::set_pi_model u2/Y 0.008 15.0 0.005} msg +set msg [sta::set_pi_model u2/Y 0.008 15.0 0.005] puts "set_pi_model u2/Y: $msg" # Set pi model on r1/Q (driver of r1q) -catch {sta::set_pi_model r1/Q 0.002 5.0 0.001} msg +set msg [sta::set_pi_model r1/Q 0.002 5.0 0.001] puts "set_pi_model r1/Q: $msg" # Set pi model on r2/Q (driver of r2q) -catch {sta::set_pi_model r2/Q 0.002 5.0 0.001} msg +set msg [sta::set_pi_model r2/Q 0.002 5.0 0.001] puts "set_pi_model r2/Q: $msg" # Set pi model on r3/Q (driver of out) -catch {sta::set_pi_model r3/Q 0.001 2.0 0.001} msg +set msg [sta::set_pi_model r3/Q 0.001 2.0 0.001] puts "set_pi_model r3/Q: $msg" #--------------------------------------------------------------- @@ -59,23 +59,23 @@ puts "set_pi_model r3/Q: $msg" puts "--- set_elmore on loads ---" # Elmore delays from u1/Y to its loads -catch {sta::set_elmore u1/Y u2/A 0.005} msg +set msg [sta::set_elmore u1/Y u2/A 0.005] puts "set_elmore u1/Y -> u2/A: $msg" # Elmore delays from u2/Y to its loads -catch {sta::set_elmore u2/Y r3/D 0.008} msg +set msg [sta::set_elmore u2/Y r3/D 0.008] puts "set_elmore u2/Y -> r3/D: $msg" # Elmore delays from r1/Q to loads -catch {sta::set_elmore r1/Q u1/A 0.003} msg +set msg [sta::set_elmore r1/Q u1/A 0.003] puts "set_elmore r1/Q -> u1/A: $msg" # Elmore delays from r2/Q to loads -catch {sta::set_elmore r2/Q u2/B 0.003} msg +set msg [sta::set_elmore r2/Q u2/B 0.003] puts "set_elmore r2/Q -> u2/B: $msg" # Elmore delays from r3/Q to out port -catch {sta::set_elmore r3/Q out 0.002} msg +set msg [sta::set_elmore r3/Q out 0.002] puts "set_elmore r3/Q -> out: $msg" #--------------------------------------------------------------- diff --git a/parasitics/test/parasitics_detailed.tcl b/parasitics/test/parasitics_detailed.tcl index b84c325b..ebc5fa62 100644 --- a/parasitics/test/parasitics_detailed.tcl +++ b/parasitics/test/parasitics_detailed.tcl @@ -36,22 +36,22 @@ report_parasitic_annotation -report_unannotated #--------------------------------------------------------------- puts "--- Annotated delay reporting ---" -catch {report_annotated_delay -cell -net} msg +set msg [report_annotated_delay -cell -net] puts $msg -catch {report_annotated_delay -from_in_ports -to_out_ports} msg +set msg [report_annotated_delay -from_in_ports -to_out_ports] puts $msg -catch {report_annotated_delay -cell} msg +set msg [report_annotated_delay -cell] puts $msg -catch {report_annotated_delay -net} msg +set msg [report_annotated_delay -net] puts $msg -catch {report_annotated_delay -report_annotated} msg +set msg [report_annotated_delay -report_annotated] puts $msg -catch {report_annotated_delay -report_unannotated} msg +set msg [report_annotated_delay -report_unannotated] puts $msg #--------------------------------------------------------------- @@ -73,26 +73,26 @@ report_checks -from [get_ports in2] -fields {slew cap} #--------------------------------------------------------------- puts "--- report_net ---" -catch {report_net r1q} msg +set msg [report_net r1q] puts $msg -catch {report_net r2q} msg +set msg [report_net r2q] puts $msg -catch {report_net u1z} msg +set msg [report_net u1z] puts $msg -catch {report_net u2z} msg +set msg [report_net u2z] puts $msg -catch {report_net out} msg +set msg [report_net out] puts $msg -catch {report_net in1} msg +set msg [report_net in1] puts $msg # report_net with -digits -catch {report_net -digits 6 r1q} msg +set msg [report_net -digits 6 r1q] puts $msg #--------------------------------------------------------------- @@ -100,10 +100,10 @@ puts $msg #--------------------------------------------------------------- puts "--- Manual parasitic models ---" -catch {sta::set_pi_model u1/Y 0.005 1.0 0.003} msg +set msg [sta::set_pi_model u1/Y 0.005 1.0 0.003] puts $msg -catch {sta::set_elmore u1/Y u2/B 0.005} msg +set msg [sta::set_elmore u1/Y u2/B 0.005] puts $msg report_checks diff --git a/parasitics/test/parasitics_estimate_wirerc.tcl b/parasitics/test/parasitics_estimate_wirerc.tcl index f91d6505..7afbfb07 100644 --- a/parasitics/test/parasitics_estimate_wirerc.tcl +++ b/parasitics/test/parasitics_estimate_wirerc.tcl @@ -30,21 +30,21 @@ report_parasitic_annotation puts "--- set_pi_model with varied parameters ---" # Very small parasitics -catch {sta::set_pi_model u1/Y 0.0001 0.1 0.00005} msg +set msg [sta::set_pi_model u1/Y 0.0001 0.1 0.00005] puts "set_pi_model u1/Y (small): $msg" # Medium parasitics -catch {sta::set_pi_model u2/Y 0.01 20.0 0.005} msg +set msg [sta::set_pi_model u2/Y 0.01 20.0 0.005] puts "set_pi_model u2/Y (medium): $msg" # Large parasitics -catch {sta::set_pi_model r1/Q 0.05 50.0 0.02} msg +set msg [sta::set_pi_model r1/Q 0.05 50.0 0.02] puts "set_pi_model r1/Q (large): $msg" -catch {sta::set_pi_model r2/Q 0.03 30.0 0.01} msg +set msg [sta::set_pi_model r2/Q 0.03 30.0 0.01] puts "set_pi_model r2/Q: $msg" -catch {sta::set_pi_model r3/Q 0.001 2.0 0.001} msg +set msg [sta::set_pi_model r3/Q 0.001 2.0 0.001] puts "set_pi_model r3/Q: $msg" #--------------------------------------------------------------- @@ -52,19 +52,19 @@ puts "set_pi_model r3/Q: $msg" #--------------------------------------------------------------- puts "--- set_elmore varied ---" -catch {sta::set_elmore u1/Y u2/A 0.0001} msg +set msg [sta::set_elmore u1/Y u2/A 0.0001] puts "set_elmore u1/Y -> u2/A (small): $msg" -catch {sta::set_elmore u2/Y r3/D 0.01} msg +set msg [sta::set_elmore u2/Y r3/D 0.01] puts "set_elmore u2/Y -> r3/D (medium): $msg" -catch {sta::set_elmore r1/Q u1/A 0.05} msg +set msg [sta::set_elmore r1/Q u1/A 0.05] puts "set_elmore r1/Q -> u1/A (large): $msg" -catch {sta::set_elmore r2/Q u2/B 0.02} msg +set msg [sta::set_elmore r2/Q u2/B 0.02] puts "set_elmore r2/Q -> u2/B: $msg" -catch {sta::set_elmore r3/Q out 0.001} msg +set msg [sta::set_elmore r3/Q out 0.001] puts "set_elmore r3/Q -> out: $msg" #--------------------------------------------------------------- @@ -111,7 +111,7 @@ puts "dmp_ceff_two_pole dcalc r1: done" #--------------------------------------------------------------- puts "--- override pi model ---" set_delay_calculator dmp_ceff_elmore -catch {sta::set_pi_model u1/Y 0.02 25.0 0.01} msg +set msg [sta::set_pi_model u1/Y 0.02 25.0 0.01] puts "re-set pi_model u1/Y: $msg" report_checks diff --git a/parasitics/test/parasitics_gcd_reduce.tcl b/parasitics/test/parasitics_gcd_reduce.tcl index c193b5c7..2b3116f4 100644 --- a/parasitics/test/parasitics_gcd_reduce.tcl +++ b/parasitics/test/parasitics_gcd_reduce.tcl @@ -84,12 +84,8 @@ foreach cell_obj [get_cells *] { } } if {[llength $in_pins] > 0 && [llength $out_pins] > 0} { - catch { - report_dcalc -from [lindex $in_pins 0] -to [lindex $out_pins 0] -max - } - catch { - report_dcalc -from [lindex $in_pins 0] -to [lindex $out_pins 0] -min - } + report_dcalc -from [lindex $in_pins 0] -to [lindex $out_pins 0] -max + report_dcalc -from [lindex $in_pins 0] -to [lindex $out_pins 0] -min incr cell_count if {$cell_count >= 20} break } diff --git a/parasitics/test/parasitics_manual.tcl b/parasitics/test/parasitics_manual.tcl index 071997c3..ac4671d4 100644 --- a/parasitics/test/parasitics_manual.tcl +++ b/parasitics/test/parasitics_manual.tcl @@ -34,19 +34,19 @@ report_parasitic_annotation puts "--- set_pi_model ---" # Set pi model on u1/Y (driver of net u1z) -catch {sta::set_pi_model u1/Y 0.002 5.0 0.001} msg +set msg [sta::set_pi_model u1/Y 0.002 5.0 0.001] puts "set_pi_model u1/Y: $msg" # Set pi model on u2/Y (driver of net u2z) -catch {sta::set_pi_model u2/Y 0.003 8.0 0.002} msg +set msg [sta::set_pi_model u2/Y 0.003 8.0 0.002] puts "set_pi_model u2/Y: $msg" # Set pi model on r1/Q (driver of r1q) -catch {sta::set_pi_model r1/Q 0.001 3.0 0.001} msg +set msg [sta::set_pi_model r1/Q 0.001 3.0 0.001] puts "set_pi_model r1/Q: $msg" # Set pi model on r2/Q (driver of r2q) -catch {sta::set_pi_model r2/Q 0.001 3.0 0.001} msg +set msg [sta::set_pi_model r2/Q 0.001 3.0 0.001] puts "set_pi_model r2/Q: $msg" #--------------------------------------------------------------- @@ -56,22 +56,22 @@ puts "set_pi_model r2/Q: $msg" puts "--- set_elmore ---" # Elmore delays from u1/Y to its loads -catch {sta::set_elmore u1/Y u2/A 0.002} msg +set msg [sta::set_elmore u1/Y u2/A 0.002] puts "set_elmore u1/Y -> u2/A: $msg" -catch {sta::set_elmore u1/Y u2/B 0.003} msg +set msg [sta::set_elmore u1/Y u2/B 0.003] puts "set_elmore u1/Y -> u2/B: $msg" # Elmore delays from u2/Y to its loads -catch {sta::set_elmore u2/Y r3/D 0.004} msg +set msg [sta::set_elmore u2/Y r3/D 0.004] puts "set_elmore u2/Y -> r3/D: $msg" # Elmore delays from r1/Q to loads -catch {sta::set_elmore r1/Q u1/A 0.001} msg +set msg [sta::set_elmore r1/Q u1/A 0.001] puts "set_elmore r1/Q -> u1/A: $msg" # Elmore delays from r2/Q to loads -catch {sta::set_elmore r2/Q u2/B 0.001} msg +set msg [sta::set_elmore r2/Q u2/B 0.001] puts "set_elmore r2/Q -> u2/B: $msg" #--------------------------------------------------------------- @@ -92,13 +92,13 @@ report_checks -fields {slew cap input_pins} # Report net with manual parasitics #--------------------------------------------------------------- puts "--- report_net with manual parasitics ---" -catch {report_net r1q} msg +set msg [report_net r1q] puts "report_net r1q: $msg" -catch {report_net u1z} msg +set msg [report_net u1z] puts "report_net u1z: $msg" -catch {report_net u2z} msg +set msg [report_net u2z] puts "report_net u2z: $msg" #--------------------------------------------------------------- @@ -114,13 +114,13 @@ report_parasitic_annotation -report_unannotated #--------------------------------------------------------------- puts "--- report_dcalc with manual parasitics ---" -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max} msg +set msg [report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max] puts "dcalc u1 A->Y: $msg" -catch {report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max} msg +set msg [report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max] puts "dcalc u2 A->Y: $msg" -catch {report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max} msg +set msg [report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max] puts "dcalc r1 CLK->Q: $msg" #--------------------------------------------------------------- diff --git a/parasitics/test/parasitics_pi_pole_residue.tcl b/parasitics/test/parasitics_pi_pole_residue.tcl index 3a1e1e40..367500ad 100644 --- a/parasitics/test/parasitics_pi_pole_residue.tcl +++ b/parasitics/test/parasitics_pi_pole_residue.tcl @@ -174,10 +174,10 @@ report_parasitic_annotation -report_unannotated # Exercises: the type-checking branches in ConcreteParasitics #--------------------------------------------------------------- puts "--- Test 8: manual pi + elmore then query ---" -catch {sta::set_pi_model u1/Y 0.005 10.0 0.003} msg +set msg [sta::set_pi_model u1/Y 0.005 10.0 0.003] puts "set_pi_model u1/Y: $msg" -catch {sta::set_elmore u1/Y u2/B 0.005} msg +set msg [sta::set_elmore u1/Y u2/B 0.005] puts "set_elmore u1/Y->u2/B: $msg" # Run timing with different calculators to force re-reduction diff --git a/parasitics/test/parasitics_reduce.tcl b/parasitics/test/parasitics_reduce.tcl index f83d91d1..c5d81910 100644 --- a/parasitics/test/parasitics_reduce.tcl +++ b/parasitics/test/parasitics_reduce.tcl @@ -48,40 +48,40 @@ report_checks -from [get_ports in1] -to [get_ports out] -fields {slew cap} report_checks -from [get_ports in2] -to [get_ports out] -fields {slew cap} # More detailed report_dcalc to exercise parasitic queries -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max} msg +set msg [report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max] puts "arnoldi dcalc u1: $msg" -catch {report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max} msg +set msg [report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max] puts "arnoldi dcalc u2 A->Y: $msg" -catch {report_dcalc -from [get_pins u2/B] -to [get_pins u2/Y] -max} msg +set msg [report_dcalc -from [get_pins u2/B] -to [get_pins u2/Y] -max] puts "arnoldi dcalc u2 B->Y: $msg" -catch {report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max} msg +set msg [report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max] puts "arnoldi dcalc r1 CLK->Q: $msg" -catch {report_dcalc -from [get_pins r2/CLK] -to [get_pins r2/Q] -max} msg +set msg [report_dcalc -from [get_pins r2/CLK] -to [get_pins r2/Q] -max] puts "arnoldi dcalc r2 CLK->Q: $msg" -catch {report_dcalc -from [get_pins r3/CLK] -to [get_pins r3/Q] -max} msg +set msg [report_dcalc -from [get_pins r3/CLK] -to [get_pins r3/Q] -max] puts "arnoldi dcalc r3 CLK->Q: $msg" # Prima - exercises prima reduction paths puts "--- prima with parasitics ---" -catch {set_delay_calculator prima} msg +set msg [set_delay_calculator prima] puts "set_delay_calculator prima: $msg" report_checks report_checks -from [get_ports in1] -to [get_ports out] -fields {slew cap} -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max} msg +set msg [report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max] puts "prima dcalc u1: $msg" -catch {report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max} msg +set msg [report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max] puts "prima dcalc u2: $msg" -catch {report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max} msg +set msg [report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max] puts "prima dcalc r1: $msg" # dmp_ceff_two_pole - exercises two_pole reduction @@ -92,13 +92,13 @@ report_checks report_checks -path_delay min -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max} msg +set msg [report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max] puts "dmp_ceff_two_pole dcalc u1: $msg" -catch {report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max} msg +set msg [report_dcalc -from [get_pins u2/A] -to [get_pins u2/Y] -max] puts "dmp_ceff_two_pole dcalc u2: $msg" -catch {report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max} msg +set msg [report_dcalc -from [get_pins r1/CLK] -to [get_pins r1/Q] -max] puts "dmp_ceff_two_pole dcalc r1: $msg" #--------------------------------------------------------------- @@ -109,7 +109,7 @@ set_delay_calculator lumped_cap report_checks -catch {report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max} msg +set msg [report_dcalc -from [get_pins u1/A] -to [get_pins u1/Y] -max] puts "lumped_cap dcalc u1: $msg" report_checks -fields {slew cap} @@ -120,22 +120,22 @@ report_checks -fields {slew cap} puts "--- annotated delay reporting ---" set_delay_calculator dmp_ceff_elmore -catch {report_annotated_delay -cell -net} msg +set msg [report_annotated_delay -cell -net] puts "annotated_delay -cell -net: $msg" -catch {report_annotated_delay -from_in_ports -to_out_ports} msg +set msg [report_annotated_delay -from_in_ports -to_out_ports] puts "annotated_delay -from_in_ports -to_out_ports: $msg" -catch {report_annotated_delay -cell} msg +set msg [report_annotated_delay -cell] puts "annotated_delay -cell: $msg" -catch {report_annotated_delay -net} msg +set msg [report_annotated_delay -net] puts "annotated_delay -net: $msg" -catch {report_annotated_delay -report_annotated} msg +set msg [report_annotated_delay -report_annotated] puts "annotated_delay -report_annotated: $msg" -catch {report_annotated_delay -report_unannotated} msg +set msg [report_annotated_delay -report_unannotated] puts "annotated_delay -report_unannotated: $msg" #--------------------------------------------------------------- diff --git a/parasitics/test/parasitics_reduce_dcalc.tcl b/parasitics/test/parasitics_reduce_dcalc.tcl index b0a717d5..7b485a20 100644 --- a/parasitics/test/parasitics_reduce_dcalc.tcl +++ b/parasitics/test/parasitics_reduce_dcalc.tcl @@ -137,7 +137,7 @@ report_checks -fields {slew cap} # Switch to prima #--------------------------------------------------------------- puts "--- prima ---" -catch {set_delay_calculator prima} msg +set msg [set_delay_calculator prima] puts "set_delay_calculator prima: $msg" report_checks diff --git a/power/test/cpp/TestPower.cc b/power/test/cpp/TestPower.cc index 7d27e889..e1dd1787 100644 --- a/power/test/cpp/TestPower.cc +++ b/power/test/cpp/TestPower.cc @@ -776,6 +776,8 @@ TEST_F(PwrActivityTest, CheckViaSetDensity) { #include "Network.hh" #include "ReportTcl.hh" #include "Corner.hh" +#include "PortDirection.hh" +#include "Liberty.hh" #include "power/Power.hh" namespace sta { @@ -911,4 +913,677 @@ TEST_F(PowerDesignTest, PinActivityQuery) { delete pin_iter; } +//////////////////////////////////////////////////////////////// +// Additional design-level power tests +//////////////////////////////////////////////////////////////// + +// Set global activity via Power::setGlobalActivity then run power. +// Covers: Power::setGlobalActivity, Power::ensureActivities +TEST_F(PowerDesignTest, SetGlobalActivity) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Set global activity + Power *pwr = sta_->power(); + pwr->setGlobalActivity(0.1f, 0.5f); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + EXPECT_GE(total.total(), 0.0f); + + // Clean up global activity setting + pwr->unsetGlobalActivity(); +} + +// Set activity on specific pins, verify power reflects the change. +// Covers: Power::setUserActivity, Power::unsetUserActivity +TEST_F(PowerDesignTest, SetPinActivity) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + // Compute baseline power + PowerResult total_baseline, seq_bl, comb_bl, clk_bl, macro_bl, pad_bl; + sta_->power(corner, total_baseline, seq_bl, comb_bl, clk_bl, macro_bl, pad_bl); + + // Set user activity on top-level input pins + Power *pwr = sta_->power(); + InstancePinIterator *pin_iter = network->pinIterator(top); + while (pin_iter->hasNext()) { + const Pin *pin = pin_iter->next(); + PortDirection *dir = network->direction(pin); + if (dir->isInput()) { + pwr->setUserActivity(pin, 0.5f, 0.5f, PwrActivityOrigin::user); + } + } + delete pin_iter; + + // Invalidate activities so the new settings take effect + pwr->activitiesInvalid(); + + PowerResult total_after, seq_af, comb_af, clk_af, macro_af, pad_af; + sta_->power(corner, total_after, seq_af, comb_af, clk_af, macro_af, pad_af); + + EXPECT_GE(total_after.total(), 0.0f); + + // Clean up + pin_iter = network->pinIterator(top); + while (pin_iter->hasNext()) { + const Pin *pin = pin_iter->next(); + PortDirection *dir = network->direction(pin); + if (dir->isInput()) { + pwr->unsetUserActivity(pin); + } + } + delete pin_iter; +} + +// Verify that total = internal + switching + leakage for design-level power. +// Covers: PowerResult::total, PowerResult::internal, switching, leakage +TEST_F(PowerDesignTest, PowerBreakdown) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + float sum = total.internal() + total.switching() + total.leakage(); + EXPECT_FLOAT_EQ(total.total(), sum); +} + +// Verify per-instance power has non-negative components. +// Covers: Power::power(inst, corner), Power::findLeakagePower, +// Power::findSwitchingPower, Power::findInternalPower +TEST_F(PowerDesignTest, PowerPerInstanceBreakdown) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + EXPECT_GE(result.internal(), 0.0f) + << "Negative internal power for " << network->pathName(inst); + EXPECT_GE(result.switching(), 0.0f) + << "Negative switching power for " << network->pathName(inst); + EXPECT_GE(result.leakage(), 0.0f) + << "Negative leakage power for " << network->pathName(inst); + float sum = result.internal() + result.switching() + result.leakage(); + EXPECT_FLOAT_EQ(result.total(), sum); + } + delete child_iter; +} + +// Verify power computation with a clock constraint uses the correct period. +// Covers: Power::clockMinPeriod, Power::findInstClk, Power::clockDuty +TEST_F(PowerDesignTest, PowerWithClockConstraint) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Create clock constraints via Tcl + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + EXPECT_GE(total.total(), 0.0f); + // With clocks defined, sequential power should be non-negative + EXPECT_GE(sequential.total(), 0.0f); +} + +// Verify sequential and combinational power separation. +// Covers: Power::power (sequential vs combinational categorization) +TEST_F(PowerDesignTest, SequentialVsCombinational) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + // Sequential power should be non-negative (reg1 has DFF instances) + EXPECT_GE(sequential.total(), 0.0f); + // Combinational power should be non-negative (reg1 has BUF, AND gates) + EXPECT_GE(combinational.total(), 0.0f); + // Total should be >= sum of sequential + combinational + // (clock and other categories may also contribute) + EXPECT_GE(total.total(), + sequential.total() + combinational.total() - 1e-15f); +} + +// Set different activity densities and verify power scales. +// Covers: Power::setGlobalActivity, Power::activitiesInvalid +TEST_F(PowerDesignTest, PowerWithActivity) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + Power *pwr = sta_->power(); + + // Low activity + pwr->setGlobalActivity(0.01f, 0.5f); + pwr->activitiesInvalid(); + PowerResult total_low, seq_l, comb_l, clk_l, macro_l, pad_l; + sta_->power(corner, total_low, seq_l, comb_l, clk_l, macro_l, pad_l); + + // High activity + pwr->setGlobalActivity(0.5f, 0.5f); + pwr->activitiesInvalid(); + PowerResult total_high, seq_h, comb_h, clk_h, macro_h, pad_h; + sta_->power(corner, total_high, seq_h, comb_h, clk_h, macro_h, pad_h); + + // Higher activity should result in equal or higher switching power + EXPECT_GE(total_high.switching(), total_low.switching()); + + pwr->unsetGlobalActivity(); +} + +// Iterate ALL instances and verify each has non-negative power. +// Covers: Power::power(inst, corner) for every instance +TEST_F(PowerDesignTest, AllInstancesPower) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + int count = 0; + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + EXPECT_GE(result.total(), 0.0f) + << "Negative total power for " << network->pathName(inst); + count++; + } + delete child_iter; + + // reg1_asap7.v has 5 instances: r1, r2, u1, u2, r3 + EXPECT_EQ(count, 5); +} + +// Run updateTiming then power, ensure consistency. +// Covers: Sta::updateTiming, Power::ensureActivities +TEST_F(PowerDesignTest, PowerAfterTimingUpdate) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + // Force timing update + sta_->updateTiming(true); + + // Power should still be consistent after timing update + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + EXPECT_GE(total.total(), 0.0f); + float sum = total.internal() + total.switching() + total.leakage(); + EXPECT_FLOAT_EQ(total.total(), sum); +} + +// Verify clock network has power. +// Covers: Power::power (clock power category) +TEST_F(PowerDesignTest, ClockPowerContribution) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + // Clock power should be non-negative + EXPECT_GE(clk.total(), 0.0f); +} + +// Verify all instance leakage power >= 0. +// Covers: Power::findLeakagePower +TEST_F(PowerDesignTest, LeakagePowerNonNegative) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + EXPECT_GE(result.leakage(), 0.0f) + << "Negative leakage for " << network->pathName(inst); + } + delete child_iter; +} + +// Verify all instance internal power >= 0. +// Covers: Power::findInternalPower +TEST_F(PowerDesignTest, InternalPowerNonNegative) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + EXPECT_GE(result.internal(), 0.0f) + << "Negative internal power for " << network->pathName(inst); + } + delete child_iter; +} + +// Verify all instance switching power >= 0. +// Covers: Power::findSwitchingPower +TEST_F(PowerDesignTest, SwitchingPowerNonNegative) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + EXPECT_GE(result.switching(), 0.0f) + << "Negative switching power for " << network->pathName(inst); + } + delete child_iter; +} + +// Verify Power::setInputActivity sets input defaults correctly. +// Covers: Power::setInputActivity, Power::unsetInputActivity +TEST_F(PowerDesignTest, SetInputActivity) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Power *pwr = sta_->power(); + pwr->setInputActivity(0.2f, 0.5f); + pwr->activitiesInvalid(); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + EXPECT_GE(total.total(), 0.0f); + + pwr->unsetInputActivity(); +} + +// Verify Power::setInputPortActivity sets port-specific activity. +// Covers: Power::setInputPortActivity, Power::unsetInputPortActivity +TEST_F(PowerDesignTest, SetInputPortActivity) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + // Find an input port + const Port *input_port = nullptr; + InstancePinIterator *pin_iter = network->pinIterator(top); + while (pin_iter->hasNext()) { + const Pin *pin = pin_iter->next(); + PortDirection *dir = network->direction(pin); + if (dir->isInput()) { + input_port = network->port(pin); + break; + } + } + delete pin_iter; + + ASSERT_NE(input_port, nullptr); + + Power *pwr = sta_->power(); + pwr->setInputPortActivity(input_port, 0.3f, 0.5f); + pwr->activitiesInvalid(); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + EXPECT_GE(total.total(), 0.0f); + + pwr->unsetInputPortActivity(input_port); +} + +// Verify highestPowerInstances returns correct count. +// Covers: Power::highestPowerInstances, Power::ensureInstPowers +TEST_F(PowerDesignTest, HighestPowerInstances) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Power *pwr = sta_->power(); + InstanceSeq top_instances = pwr->highestPowerInstances(3, corner); + + // Should return at most 3 instances (or fewer if design has fewer) + EXPECT_LE(top_instances.size(), 3u); + EXPECT_GE(top_instances.size(), 1u); + + // Verify instances are sorted by descending power + Network *network = sta_->network(); + float prev_power = std::numeric_limits::max(); + for (const Instance *inst : top_instances) { + PowerResult result = sta_->power(inst, corner); + EXPECT_LE(result.total(), prev_power + 1e-15f); + prev_power = result.total(); + } +} + +// Verify highestPowerInstances returns exactly count instances. +// Covers: Power::highestPowerInstances with count == instance count +TEST_F(PowerDesignTest, HighestPowerInstancesAllInstances) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Power *pwr = sta_->power(); + // Request exactly the total instance count (5 in reg1_asap7) + InstanceSeq top_instances = pwr->highestPowerInstances(5, corner); + + EXPECT_EQ(top_instances.size(), 5u); +} + +// Verify Power::pinActivity returns valid activity for instance pins. +// Covers: Power::pinActivity, Power::findActivity +TEST_F(PowerDesignTest, PinActivityOnInstancePins) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + // Force activity propagation + PowerResult total, seq, comb, clk, macro, pad; + sta_->power(corner, total, seq, comb, clk, macro, pad); + + Power *pwr = sta_->power(); + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + // Check activity on pins of child instances + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + InstancePinIterator *pin_iter = network->pinIterator(inst); + while (pin_iter->hasNext()) { + const Pin *pin = pin_iter->next(); + PwrActivity act = pwr->pinActivity(pin); + // Density should be non-negative + EXPECT_GE(act.density(), 0.0f); + // Duty should be between 0 and 1 + EXPECT_GE(act.duty(), 0.0f); + EXPECT_LE(act.duty(), 1.0f); + } + delete pin_iter; + } + delete child_iter; +} + +// Verify sequential instances have sequential classification. +// Covers: LibertyCell::hasSequentials, Power categorization +TEST_F(PowerDesignTest, SequentialCellClassification) { + ASSERT_TRUE(design_loaded_); + + Network *network = sta_->network(); + Instance *top = network->topInstance(); + + int seq_count = 0; + int comb_count = 0; + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + LibertyCell *cell = network->libertyCell(inst); + ASSERT_NE(cell, nullptr); + if (cell->hasSequentials()) { + seq_count++; + } else { + comb_count++; + } + } + delete child_iter; + + // reg1_asap7 has 3 DFFs (sequential) and 2 combinational (BUF, AND) + EXPECT_EQ(seq_count, 3); + EXPECT_EQ(comb_count, 2); +} + +// Verify Power::clear resets state properly. +// Covers: Power::clear +TEST_F(PowerDesignTest, PowerClear) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Compute power first + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + EXPECT_GE(total.total(), 0.0f); + + // Clear power state + Power *pwr = sta_->power(); + pwr->clear(); + + // Recompute - should still produce valid results + PowerResult total2, seq2, comb2, clk2, macro2, pad2; + sta_->power(corner, total2, seq2, comb2, clk2, macro2, pad2); + EXPECT_GE(total2.total(), 0.0f); +} + +// Verify Power::powerInvalid forces recomputation. +// Covers: Power::powerInvalid, Power::ensureInstPowers +TEST_F(PowerDesignTest, PowerInvalid) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Compute power + PowerResult total1, seq1, comb1, clk1, macro1, pad1; + sta_->power(corner, total1, seq1, comb1, clk1, macro1, pad1); + + // Invalidate + Power *pwr = sta_->power(); + pwr->powerInvalid(); + + // Recompute - results should be consistent + PowerResult total2, seq2, comb2, clk2, macro2, pad2; + sta_->power(corner, total2, seq2, comb2, clk2, macro2, pad2); + + EXPECT_FLOAT_EQ(total1.total(), total2.total()); +} + +// Verify macro and pad power are zero for this simple design. +// Covers: Power::power (macro/pad categories) +TEST_F(PowerDesignTest, MacroPadPowerZero) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + // Simple design has no macros or pads + EXPECT_FLOAT_EQ(macro.total(), 0.0f); + EXPECT_FLOAT_EQ(pad.total(), 0.0f); +} + +// Verify per-instance power sums to approximately total design power. +// Covers: Power::power consistency between instance and design level +TEST_F(PowerDesignTest, InstancePowerSumsToTotal) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Design-level power + PowerResult total, sequential, combinational, clk, macro, pad; + sta_->power(corner, total, sequential, combinational, clk, macro, pad); + + // Sum per-instance power + Network *network = sta_->network(); + Instance *top = network->topInstance(); + float inst_sum = 0.0f; + + InstanceChildIterator *child_iter = network->childIterator(top); + while (child_iter->hasNext()) { + Instance *inst = child_iter->next(); + PowerResult result = sta_->power(inst, corner); + inst_sum += result.total(); + } + delete child_iter; + + // Instance power sum should match total power (flat design) + EXPECT_NEAR(inst_sum, total.total(), total.total() * 0.01f + 1e-15f); +} + +// Verify Power with different clock periods yields different power. +// Covers: Power::clockMinPeriod, activity scaling with period +TEST_F(PowerDesignTest, PowerWithDifferentClockPeriods) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + // Fast clock (1ns period) + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + Power *pwr = sta_->power(); + pwr->activitiesInvalid(); + PowerResult total_fast, seq_f, comb_f, clk_f, macro_f, pad_f; + sta_->power(corner, total_fast, seq_f, comb_f, clk_f, macro_f, pad_f); + + EXPECT_GE(total_fast.total(), 0.0f); +} + +// Verify Power::reportActivityAnnotation does not crash. +// Covers: Power::reportActivityAnnotation +TEST_F(PowerDesignTest, ReportActivityAnnotation) { + ASSERT_TRUE(design_loaded_); + sta_->ensureGraph(); + + Corner *corner = sta_->cmdCorner(); + sta_->readSpef("test/reg1_asap7.spef", sta_->network()->topInstance(), corner, + MinMaxAll::all(), false, false, 1.0f, true); + + Tcl_Eval(interp_, "create_clock -name clk1 -period 1.0 [get_ports clk1]"); + Tcl_Eval(interp_, "create_clock -name clk2 -period 1.0 [get_ports clk2]"); + Tcl_Eval(interp_, "create_clock -name clk3 -period 1.0 [get_ports clk3]"); + + // Force activities to be computed + PowerResult total, seq, comb, clk, macro, pad; + sta_->power(corner, total, seq, comb, clk, macro, pad); + + Power *pwr = sta_->power(); + // Should not crash + pwr->reportActivityAnnotation(true, true); + pwr->reportActivityAnnotation(true, false); + pwr->reportActivityAnnotation(false, true); + pwr->reportActivityAnnotation(false, false); +} + } // namespace sta diff --git a/power/test/power_saif_vcd.tcl b/power/test/power_saif_vcd.tcl index 5eb66ca1..5ee30f6b 100644 --- a/power/test/power_saif_vcd.tcl +++ b/power/test/power_saif_vcd.tcl @@ -50,10 +50,4 @@ report_power -highest_power_instances 10 -digits 4 #--------------------------------------------------------------- puts "--- instance power with VCD ---" set some_cells [get_cells _*_] -set rc [catch { - report_power -instances $some_cells -} msg] -if { $rc == 0 } { -} else { - puts "INFO: report_power -instances: $msg" -} +report_power -instances $some_cells diff --git a/power/test/power_vcd_detailed.tcl b/power/test/power_vcd_detailed.tcl index 49a363ff..055e982d 100644 --- a/power/test/power_vcd_detailed.tcl +++ b/power/test/power_vcd_detailed.tcl @@ -71,29 +71,11 @@ set some_cells [get_cells _*_] set cell_count [llength $some_cells] puts "cells for instance power: $cell_count" -set rc [catch { - report_power -instances $some_cells -} msg] -if { $rc == 0 } { -} else { - puts "INFO: report_power -instances: $msg" -} +report_power -instances $some_cells -set rc [catch { - report_power -instances $some_cells -format json -} msg] -if { $rc == 0 } { -} else { - puts "INFO: report_power -instances json: $msg" -} +report_power -instances $some_cells -format json -set rc [catch { - report_power -instances $some_cells -digits 6 -} msg] -if { $rc == 0 } { -} else { - puts "INFO: report_power -instances -digits 6: $msg" -} +report_power -instances $some_cells -digits 6 #--------------------------------------------------------------- # Test 6: Override VCD with manual activity diff --git a/sdc/test/sdc_clock_operations.tcl b/sdc/test/sdc_clock_operations.tcl index a2b0c850..557407b3 100644 --- a/sdc/test/sdc_clock_operations.tcl +++ b/sdc/test/sdc_clock_operations.tcl @@ -69,9 +69,7 @@ set_propagated_clock [get_clocks clk2] report_checks puts "--- set_propagated_clock on pin ---" -catch { - set_propagated_clock [get_ports clk1] -} +set_propagated_clock [get_ports clk1] ############################################################ # Clock slew/transition @@ -105,12 +103,10 @@ report_checks # Clock insertion ############################################################ puts "--- clock insertion ---" -catch { - set_clock_latency -source -rise -early 0.1 [get_clocks clk1] - set_clock_latency -source -rise -late 0.3 [get_clocks clk1] - set_clock_latency -source -fall -early 0.15 [get_clocks clk1] - set_clock_latency -source -fall -late 0.35 [get_clocks clk1] -} +set_clock_latency -source -rise -early 0.1 [get_clocks clk1] +set_clock_latency -source -rise -late 0.3 [get_clocks clk1] +set_clock_latency -source -fall -early 0.15 [get_clocks clk1] +set_clock_latency -source -fall -late 0.35 [get_clocks clk1] report_checks ############################################################ @@ -136,10 +132,8 @@ report_checks # Clock uncertainty on pin ############################################################ puts "--- clock uncertainty on pin ---" -catch { - set_clock_uncertainty -setup 0.25 [get_ports clk1] - set_clock_uncertainty -hold 0.08 [get_ports clk1] -} +set_clock_uncertainty -setup 0.25 [get_ports clk1] +set_clock_uncertainty -hold 0.08 [get_ports clk1] report_checks ############################################################ @@ -181,40 +175,32 @@ report_checks # Remove clock latency ############################################################ puts "--- unset_clock_latency ---" -catch { - unset_clock_latency -source [get_clocks clk1] - report_checks -} +unset_clock_latency -source [get_clocks clk1] +report_checks ############################################################ # Remove clock uncertainty ############################################################ puts "--- unset_clock_uncertainty ---" -catch { - unset_clock_uncertainty -setup [get_clocks clk1] - unset_clock_uncertainty -hold [get_clocks clk1] - report_checks -} +unset_clock_uncertainty -setup [get_clocks clk1] +unset_clock_uncertainty -hold [get_clocks clk1] +report_checks ############################################################ # Remove inter-clock uncertainty ############################################################ puts "--- unset inter-clock uncertainty ---" -catch { - unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -setup - unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -hold - report_checks -} +unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -setup +unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -hold +report_checks ############################################################ # Remove propagated clock ############################################################ puts "--- unset_propagated_clock ---" -catch { - unset_propagated_clock [get_clocks clk1] - unset_propagated_clock [get_clocks clk2] - report_checks -} +unset_propagated_clock [get_clocks clk1] +unset_propagated_clock [get_clocks clk2] +report_checks ############################################################ # Final write diff --git a/sdc/test/sdc_delay_borrow_group.tcl b/sdc/test/sdc_delay_borrow_group.tcl index 867f856c..5baefae1 100644 --- a/sdc/test/sdc_delay_borrow_group.tcl +++ b/sdc/test/sdc_delay_borrow_group.tcl @@ -87,13 +87,9 @@ set_max_time_borrow 1.5 [get_clocks clk2] set_max_time_borrow 1.0 [get_pins reg1/D] set_max_time_borrow 0.8 [get_pins reg2/D] -catch { - set_max_time_borrow 1.2 [get_cells reg1] -} +set_max_time_borrow 1.2 [get_cells reg1] -catch { - set_max_time_borrow 0.9 [get_cells reg3] -} +set_max_time_borrow 0.9 [get_cells reg3] ############################################################ # Min pulse width on all targets @@ -109,19 +105,13 @@ set_min_pulse_width -low 0.4 [get_clocks clk1] set_min_pulse_width 0.55 [get_clocks clk2] # Pin -catch { - set_min_pulse_width 0.3 [get_pins reg1/CK] -} +set_min_pulse_width 0.3 [get_pins reg1/CK] -catch { - set_min_pulse_width -high 0.35 [get_pins reg2/CK] - set_min_pulse_width -low 0.25 [get_pins reg2/CK] -} +set_min_pulse_width -high 0.35 [get_pins reg2/CK] +set_min_pulse_width -low 0.25 [get_pins reg2/CK] # Instance -catch { - set_min_pulse_width 0.45 [get_cells reg3] -} +set_min_pulse_width 0.45 [get_cells reg3] ############################################################ # set_max_area diff --git a/sdc/test/sdc_design_rules_limits.tcl b/sdc/test/sdc_design_rules_limits.tcl index a7a9b486..b04750b2 100644 --- a/sdc/test/sdc_design_rules_limits.tcl +++ b/sdc/test/sdc_design_rules_limits.tcl @@ -53,18 +53,12 @@ set_max_capacitance 0.1 [get_ports out1] set_max_capacitance 0.15 [get_ports out2] # Pin-level cap limits -catch { - set_max_capacitance 0.08 [get_pins reg1/Q] -} +set_max_capacitance 0.08 [get_pins reg1/Q] # Min capacitance -catch { - set_min_capacitance 0.001 [current_design] -} +set_min_capacitance 0.001 [current_design] -catch { - set_min_capacitance 0.0005 [get_ports out1] -} +set_min_capacitance 0.0005 [get_ports out1] ############################################################ # Max/min fanout limits @@ -99,16 +93,12 @@ set_min_pulse_width -low 0.4 [get_clocks clk1] set_min_pulse_width 0.7 [get_clocks clk2] # Pin min pulse width -catch { - set_min_pulse_width 0.3 [get_pins reg1/CK] - set_min_pulse_width -high 0.35 [get_pins reg2/CK] - set_min_pulse_width -low 0.25 [get_pins reg2/CK] -} +set_min_pulse_width 0.3 [get_pins reg1/CK] +set_min_pulse_width -high 0.35 [get_pins reg2/CK] +set_min_pulse_width -low 0.25 [get_pins reg2/CK] # Instance min pulse width -catch { - set_min_pulse_width 0.45 [get_cells reg3] -} +set_min_pulse_width 0.45 [get_cells reg3] ############################################################ # Latch borrow limits @@ -118,9 +108,7 @@ set_max_time_borrow 1.5 [get_clocks clk2] set_max_time_borrow 1.0 [get_pins reg1/D] -catch { - set_max_time_borrow 1.2 [get_cells reg2] -} +set_max_time_borrow 1.2 [get_cells reg2] ############################################################ # Port slew limits diff --git a/sdc/test/sdc_disable_case.tcl b/sdc/test/sdc_disable_case.tcl index 556f8f56..076d299f 100644 --- a/sdc/test/sdc_disable_case.tcl +++ b/sdc/test/sdc_disable_case.tcl @@ -116,9 +116,7 @@ set_logic_zero [get_ports in1] set_logic_one [get_ports in2] # set_logic_dc (don't care) -catch { - set_logic_dc [get_ports in3] -} +set_logic_dc [get_ports in3] # Write SDC with logic values (exercises writeConstants) set sdc_file4 [make_result_file sdc_logic1.sdc] @@ -130,21 +128,13 @@ report_checks # Data checks ############################################################ -catch { - set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.5 -} +set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.5 -catch { - set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -hold 0.3 -} +set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -hold 0.3 -catch { - set_data_check -rise_from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.6 -} +set_data_check -rise_from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.6 -catch { - set_data_check -from [get_pins reg1/Q] -fall_to [get_pins reg2/D] -hold 0.25 -} +set_data_check -from [get_pins reg1/Q] -fall_to [get_pins reg2/D] -hold 0.25 # Write with data checks set sdc_file5 [make_result_file sdc_datacheck1.sdc] @@ -174,16 +164,12 @@ set_clock_gating_check -setup 0.35 [get_clocks clk2] set_clock_gating_check -hold 0.15 [get_clocks clk2] # Instance-level -catch { - set_clock_gating_check -setup 0.3 [get_cells reg1] - set_clock_gating_check -hold 0.1 [get_cells reg1] -} +set_clock_gating_check -setup 0.3 [get_cells reg1] +set_clock_gating_check -hold 0.1 [get_cells reg1] # Pin-level -catch { - set_clock_gating_check -setup 0.25 [get_pins reg1/CK] - set_clock_gating_check -hold 0.08 [get_pins reg1/CK] -} +set_clock_gating_check -setup 0.25 [get_pins reg1/CK] +set_clock_gating_check -hold 0.08 [get_pins reg1/CK] # Write SDC with clock gating set sdc_file6 [make_result_file sdc_clkgate1.sdc] @@ -196,10 +182,8 @@ write_sdc -no_timestamp $sdc_file6 set_ideal_network [get_ports clk1] set_ideal_network [get_ports clk2] -catch { - set_ideal_transition 0.0 [get_ports clk1] - set_ideal_transition 0.05 [get_ports clk2] -} +set_ideal_transition 0.0 [get_ports clk1] +set_ideal_transition 0.05 [get_ports clk2] ############################################################ # Min pulse width on various objects @@ -211,13 +195,9 @@ set_min_pulse_width -low 0.4 [get_clocks clk1] set_min_pulse_width 0.8 [get_clocks clk2] -catch { - set_min_pulse_width 0.5 [get_pins reg1/CK] -} +set_min_pulse_width 0.5 [get_pins reg1/CK] -catch { - set_min_pulse_width 0.6 [get_cells reg1] -} +set_min_pulse_width 0.6 [get_cells reg1] ############################################################ # Latch borrow limits on various objects @@ -228,9 +208,7 @@ set_max_time_borrow 1.5 [get_clocks clk2] set_max_time_borrow 1.0 [get_pins reg1/D] -catch { - set_max_time_borrow 1.2 [get_cells reg2] -} +set_max_time_borrow 1.2 [get_cells reg2] ############################################################ # Comprehensive write with all constraints diff --git a/sdc/test/sdc_port_delay_advanced.tcl b/sdc/test/sdc_port_delay_advanced.tcl index 6c5858fc..21997ada 100644 --- a/sdc/test/sdc_port_delay_advanced.tcl +++ b/sdc/test/sdc_port_delay_advanced.tcl @@ -130,13 +130,9 @@ set_disable_timing [get_lib_cells NangateOpenCellLibrary/NAND2_X1] # Data check (DataCheck.cc) ############################################################ -catch { - set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.5 -} +set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.5 -catch { - set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -hold 0.3 -} +set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -hold 0.3 catch { set_data_check -from [get_pins reg1/Q] -to [get_pins reg2/D] -setup 0.6 -clock_fall @@ -241,7 +237,7 @@ set_wire_load_mode enclosed # Voltage setting ############################################################ -catch {set_voltage 1.1 -min 0.9} +set_voltage 1.1 -min 0.9 ############################################################ # Write SDC with all the constraints diff --git a/sdf/test/sdf_reread_cond.tcl b/sdf/test/sdf_reread_cond.tcl index 4d706a98..9624a0cf 100644 --- a/sdf/test/sdf_reread_cond.tcl +++ b/sdf/test/sdf_reread_cond.tcl @@ -111,10 +111,6 @@ set sdf_gz [make_result_file "${test_name}_gz.sdf.gz"] write_sdf -gzip -no_timestamp $sdf_gz # Read gzip SDF -set rc [catch { read_sdf $sdf_gz } msg] -if { $rc == 0 } { -} else { - puts "INFO: read gzip SDF: $msg" -} +read_sdf $sdf_gz report_checks diff --git a/search/test/cpp/TestSearchIncremental.cc b/search/test/cpp/TestSearchIncremental.cc index b90f9568..9b4f9f06 100644 --- a/search/test/cpp/TestSearchIncremental.cc +++ b/search/test/cpp/TestSearchIncremental.cc @@ -10,6 +10,7 @@ #include "Network.hh" #include "Liberty.hh" #include "Graph.hh" +#include "TimingArc.hh" namespace sta { @@ -457,4 +458,1117 @@ TEST_F(IncrementalTimingTest, ClockConstraintAfterEdit) { EXPECT_GT(loose_slack, tight_slack); } +//////////////////////////////////////////////////////////////// +// Test 9: Replace AND gate with larger variant (AND2_X4) +// and verify timing improves due to stronger drive. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ReplaceAndGateWithLargerVariant) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Find and1 instance (AND2_X1) and replace with AND2_X4 + Instance *and1 = network->findChild(top, "and1"); + ASSERT_NE(and1, nullptr); + + LibertyCell *and2_x4 = network->findLibertyCell("AND2_X4"); + ASSERT_NE(and2_x4, nullptr); + + sta_->replaceCell(and1, and2_x4); + Slack after_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_slack)); + + // Larger AND gate has stronger drive, should improve or maintain slack + EXPECT_GE(after_slack, initial_slack); + + // Replace back and verify restoration + LibertyCell *and2_x1 = network->findLibertyCell("AND2_X1"); + ASSERT_NE(and2_x1, nullptr); + sta_->replaceCell(and1, and2_x1); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 10: Chain of replacements: upsize -> downsize -> upsize +// and verify timing is consistent after each step. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ChainedReplacementsConsistency) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + + LibertyCell *buf_x1 = network->findLibertyCell("BUF_X1"); + LibertyCell *buf_x2 = network->findLibertyCell("BUF_X2"); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x1, nullptr); + ASSERT_NE(buf_x2, nullptr); + ASSERT_NE(buf_x4, nullptr); + + // Step 1: Upsize to BUF_X4 + sta_->replaceCell(buf1, buf_x4); + Slack slack_x4 = sta_->worstSlack(MinMax::max()); + + // Step 2: Downsize to BUF_X2 + sta_->replaceCell(buf1, buf_x2); + Slack slack_x2 = sta_->worstSlack(MinMax::max()); + + // BUF_X4 should be at least as good as BUF_X2 + EXPECT_GE(slack_x4, slack_x2); + + // Step 3: Upsize again to BUF_X4 + sta_->replaceCell(buf1, buf_x4); + Slack slack_x4_again = sta_->worstSlack(MinMax::max()); + + // Same cell should produce same slack + EXPECT_NEAR(slack_x4, slack_x4_again, 1e-6); + + // Step 4: Return to original + sta_->replaceCell(buf1, buf_x1); + Slack slack_original = sta_->worstSlack(MinMax::max()); + + // X2 should be between X1 and X4 + EXPECT_GE(slack_x2, slack_original); + EXPECT_LE(slack_x2, slack_x4); +} + +//////////////////////////////////////////////////////////////// +// Test 11: Replace all cells on the combinational path +// (and1 + buf1) and verify cumulative timing effect. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ReplaceAllCellsOnPath) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Upsize and1 to AND2_X4 + Instance *and1 = network->findChild(top, "and1"); + ASSERT_NE(and1, nullptr); + LibertyCell *and2_x4 = network->findLibertyCell("AND2_X4"); + ASSERT_NE(and2_x4, nullptr); + sta_->replaceCell(and1, and2_x4); + + Slack after_and_slack = sta_->worstSlack(MinMax::max()); + + // Also upsize buf1 to BUF_X4 + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack after_both_slack = sta_->worstSlack(MinMax::max()); + + // Both upsized should be at least as good as just and1 upsized + EXPECT_GE(after_both_slack, initial_slack); + // Cumulative improvement: both should be better than initial + EXPECT_GE(after_and_slack, initial_slack); + EXPECT_GE(after_both_slack, initial_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 12: Set timing derate (cell delay) after initial timing +// and verify setup slack degrades for late derate > 1.0. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, TimingDerateAffectsSlack) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Timing derate requires OCV analysis mode to distinguish early/late. + sta_->setAnalysisType(AnalysisType::ocv); + + // Add significant load to make gate delays visible for derating + Port *out1_port = network->findPort(network->cell(top), "out1"); + ASSERT_NE(out1_port, nullptr); + sta_->setPortExtPinCap(out1_port, RiseFallBoth::riseFall(), + sta_->cmdCorner(), MinMaxAll::all(), 0.5f); + sta_->updateTiming(true); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(initial_slack)); + + // Apply a large cell delay derate on data paths for late analysis + sta_->setTimingDerate(TimingDerateType::cell_delay, + PathClkOrData::data, + RiseFallBoth::riseFall(), + EarlyLate::late(), + 5.0f); + + Slack derated_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(derated_slack)); + + // Late derate > 1.0 increases data path delay, worsening setup slack + // With 0.5pF load, gate delays are significant enough that 5x derate + // should produce a visible effect on slack + EXPECT_LE(derated_slack, initial_slack); + + // Remove the derate and verify slack restores + sta_->unsetTimingDerate(); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 13: Set clock uncertainty and verify setup slack degrades. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ClockUncertaintyDegradeSetupSlack) { + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + + // Add 0.5ns setup uncertainty -- eats into the timing margin + sta_->setClockUncertainty(clk, SetupHoldAll::max(), 0.5f); + + Slack after_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_slack)); + + // Uncertainty reduces available margin, slack should worsen + EXPECT_LT(after_slack, initial_slack); + + // The slack difference should be approximately 0.5ns + float slack_diff = initial_slack - after_slack; + EXPECT_NEAR(slack_diff, 0.5f, 0.01f); + + // Remove uncertainty + sta_->removeClockUncertainty(clk, SetupHoldAll::max()); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 14: Set input transition (slew) on port and verify +// path delay changes. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, InputSlewChangesPathDelay) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Set a very large input slew on in1 (1ns) + Port *in1_port = network->findPort(network->cell(top), "in1"); + ASSERT_NE(in1_port, nullptr); + sta_->setInputSlew(in1_port, RiseFallBoth::riseFall(), + MinMaxAll::all(), 1.0f); + + Slack after_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_slack)); + + // Large input slew increases gate delays downstream, worsening slack + EXPECT_LE(after_slack, initial_slack); + + // Now set a small slew (fast transition) + sta_->setInputSlew(in1_port, RiseFallBoth::riseFall(), + MinMaxAll::all(), 0.001f); + + Slack fast_slack = sta_->worstSlack(MinMax::max()); + // Fast slew should give better timing than slow slew + EXPECT_GE(fast_slack, after_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 15: Disable timing on the AND cell and verify the +// path through it is no longer constrained (slack improves +// dramatically or becomes unconstrained). +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, DisableCellTimingExcludesPath) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Check pin slack on reg1/D (endpoint of the input path through and1) + Instance *reg1 = network->findChild(top, "reg1"); + ASSERT_NE(reg1, nullptr); + Pin *reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + + Slack initial_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_FALSE(std::isnan(initial_pin_slack)); + + // Find and1 instance and disable timing through it + Instance *and1 = network->findChild(top, "and1"); + ASSERT_NE(and1, nullptr); + + // Disable all timing arcs through and1 instance + sta_->disable(and1, nullptr, nullptr); + + // After disabling and1, the path in1/in2 -> and1 -> buf1 -> reg1 is broken. + // The pin slack at reg1/D should become unconstrained (NaN/INF) or improve + // significantly because no constrained path reaches it. + Slack after_disable_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + // Either unconstrained (NaN/very large) or much better than before + if (std::isnan(after_disable_pin_slack) == false) { + EXPECT_GT(after_disable_pin_slack, initial_pin_slack); + } + // else: NaN means unconstrained, which is expected + + // Re-enable timing through and1 + sta_->removeDisable(and1, nullptr, nullptr); + Slack restored_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_NEAR(restored_pin_slack, initial_pin_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 16: Disconnect and reconnect a pin, verify timing restores. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, DisconnectReconnectPinRestoresTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Use pin slack at reg1/D to track the specific input path + Instance *reg1 = network->findChild(top, "reg1"); + ASSERT_NE(reg1, nullptr); + Pin *reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + + Slack initial_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_FALSE(std::isnan(initial_pin_slack)); + + // Disconnect reg1/D from n2 and reconnect it + sta_->disconnectPin(reg1_d); + + // Reconnect reg1/D to n2 + Net *n2 = network->findNet(top, "n2"); + ASSERT_NE(n2, nullptr); + LibertyCell *dff_cell = network->findLibertyCell("DFF_X1"); + ASSERT_NE(dff_cell, nullptr); + LibertyPort *dff_d_port = dff_cell->findLibertyPort("D"); + ASSERT_NE(dff_d_port, nullptr); + sta_->connectPin(reg1, dff_d_port, n2); + + // After disconnect/reconnect to same net, timing should restore + Slack restored_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + // The pin slack should be restored to close to the initial value + // after reconnecting to the same net + EXPECT_FALSE(std::isnan(restored_pin_slack)); + EXPECT_NEAR(restored_pin_slack, initial_pin_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 17: Connect reg1/D to a different net (n1 instead of n2), +// bypassing buf1, and verify timing updates for new topology. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ConnectPinToDifferentNet) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Add significant output load on buf1 output (net n2) to make + // the buf1 delay visible when bypassing it. + Port *out1_port = network->findPort(network->cell(top), "out1"); + ASSERT_NE(out1_port, nullptr); + sta_->setPortExtPinCap(out1_port, RiseFallBoth::riseFall(), + sta_->cmdCorner(), MinMaxAll::all(), 0.1f); + sta_->updateTiming(true); + + // Track pin slack at reg1/D for the input path + Instance *reg1 = network->findChild(top, "reg1"); + ASSERT_NE(reg1, nullptr); + Pin *reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + + Slack initial_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_FALSE(std::isnan(initial_pin_slack)); + + // Current: and1/ZN --[n1]--> buf1/A, buf1/Z --[n2]--> reg1/D + // Change to: reg1/D connected to n1 (bypass buf1) + + sta_->disconnectPin(reg1_d); + + Net *n1 = network->findNet(top, "n1"); + ASSERT_NE(n1, nullptr); + LibertyCell *dff_cell = network->findLibertyCell("DFF_X1"); + ASSERT_NE(dff_cell, nullptr); + LibertyPort *dff_d_port = dff_cell->findLibertyPort("D"); + ASSERT_NE(dff_d_port, nullptr); + sta_->connectPin(reg1, dff_d_port, n1); + + // After bypassing buf1, the path is shorter so pin slack should improve + reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + Slack bypassed_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_FALSE(std::isnan(bypassed_pin_slack)); + // Shorter path should improve slack at this pin + EXPECT_GE(bypassed_pin_slack, initial_pin_slack); + + // Restore: reconnect reg1/D to n2 + reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + sta_->disconnectPin(reg1_d); + + Net *n2 = network->findNet(top, "n2"); + ASSERT_NE(n2, nullptr); + sta_->connectPin(reg1, dff_d_port, n2); + + // After restoring, pin slack should return to original + reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + Slack restored_pin_slack = sta_->pinSlack(reg1_d, MinMax::max()); + EXPECT_NEAR(restored_pin_slack, initial_pin_slack, 1e-3); +} + +//////////////////////////////////////////////////////////////// +// Test 18: Annotate net wire capacitance and verify it increases +// delay through the path. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, NetWireCapAnnotation) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Annotate large wire cap on net n1 (and1 output) + Net *n1 = network->findNet(top, "n1"); + ASSERT_NE(n1, nullptr); + sta_->setNetWireCap(n1, false, sta_->cmdCorner(), + MinMaxAll::all(), 0.5f); + + Slack after_cap_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_cap_slack)); + + // Large wire cap should slow down and1's output, degrading slack + EXPECT_LT(after_cap_slack, initial_slack); + + // Reduce the cap + sta_->setNetWireCap(n1, false, sta_->cmdCorner(), + MinMaxAll::all(), 0.001f); + + Slack small_cap_slack = sta_->worstSlack(MinMax::max()); + // Smaller cap should be better than large cap + EXPECT_GT(small_cap_slack, after_cap_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 19: Set annotated slew on a vertex and verify +// delay calculation uses the annotation. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, AnnotatedSlewAffectsDelay) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Get the graph vertex for and1/ZN (driver pin) + Instance *and1 = network->findChild(top, "and1"); + ASSERT_NE(and1, nullptr); + Pin *and1_zn = network->findPin(and1, "ZN"); + ASSERT_NE(and1_zn, nullptr); + + Graph *graph = sta_->ensureGraph(); + ASSERT_NE(graph, nullptr); + Vertex *and1_zn_vertex = graph->pinDrvrVertex(and1_zn); + ASSERT_NE(and1_zn_vertex, nullptr); + + // Annotate a very large slew (2.0ns) on the and1 output + sta_->setAnnotatedSlew(and1_zn_vertex, sta_->cmdCorner(), + MinMaxAll::all(), RiseFallBoth::riseFall(), + 2.0f); + + Slack after_slew_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_slew_slack)); + + // Large slew annotation on and1 output should increase downstream + // delay through buf1, degrading timing + EXPECT_LT(after_slew_slack, initial_slack); + + // Remove annotations and verify restoration + sta_->removeDelaySlewAnnotations(); + // Need full timing update after removing annotations + sta_->updateTiming(true); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 20: Annotate arc delay on an edge and verify it affects timing. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ArcDelayAnnotation) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Find buf1 instance and get its timing arcs + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + Pin *buf1_a = network->findPin(buf1, "A"); + Pin *buf1_z = network->findPin(buf1, "Z"); + ASSERT_NE(buf1_a, nullptr); + ASSERT_NE(buf1_z, nullptr); + + Graph *graph = sta_->ensureGraph(); + ASSERT_NE(graph, nullptr); + + Vertex *buf1_a_vertex = graph->pinLoadVertex(buf1_a); + ASSERT_NE(buf1_a_vertex, nullptr); + + // Find an edge from buf1/A to buf1/Z and annotate a large delay + bool found_edge = false; + VertexOutEdgeIterator edge_iter(buf1_a_vertex, graph); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + TimingArcSet *arc_set = edge->timingArcSet(); + for (TimingArc *arc : arc_set->arcs()) { + // Annotate a large delay (5ns) on this arc + sta_->setArcDelay(edge, arc, sta_->cmdCorner(), + MinMaxAll::all(), 5.0f); + found_edge = true; + } + } + ASSERT_TRUE(found_edge); + + Slack annotated_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(annotated_slack)); + + // A 5ns delay annotation on buf1 should significantly worsen slack + EXPECT_LT(annotated_slack, initial_slack); + + // Remove annotations and restore + sta_->removeDelaySlewAnnotations(); + sta_->updateTiming(true); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 21: Verify that multiple incremental edit-query cycles +// produce results consistent with a final full timing update. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, RapidEditQueryCycles) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + Instance *and1 = network->findChild(top, "and1"); + ASSERT_NE(and1, nullptr); + + LibertyCell *buf_x1 = network->findLibertyCell("BUF_X1"); + LibertyCell *buf_x2 = network->findLibertyCell("BUF_X2"); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + LibertyCell *and2_x2 = network->findLibertyCell("AND2_X2"); + ASSERT_NE(buf_x1, nullptr); + ASSERT_NE(buf_x2, nullptr); + ASSERT_NE(buf_x4, nullptr); + ASSERT_NE(and2_x2, nullptr); + + // Cycle 1: Edit buf1 -> BUF_X2, query + sta_->replaceCell(buf1, buf_x2); + Slack slack1 = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(slack1)); + + // Cycle 2: Edit and1 -> AND2_X2, query + sta_->replaceCell(and1, and2_x2); + Slack slack2 = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(slack2)); + + // Cycle 3: Edit buf1 -> BUF_X4, query + sta_->replaceCell(buf1, buf_x4); + Slack slack3 = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(slack3)); + + // Now do a full timing update and verify consistency + sta_->updateTiming(true); + Slack full_slack = sta_->worstSlack(MinMax::max()); + + // The last incremental result should match full timing + EXPECT_NEAR(slack3, full_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 22: Verify TNS (total negative slack) updates +// incrementally after edits. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, TnsUpdatesIncrementally) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_tns = sta_->totalNegativeSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(initial_tns)); + // TNS is <= 0 by definition (sum of negative slacks) + EXPECT_LE(initial_tns, 0.0f); + + // Tighten the clock severely to create violations + Pin *clk_pin = network->findPin(top, "clk"); + ASSERT_NE(clk_pin, nullptr); + PinSet *clk_pins = new PinSet(network); + clk_pins->insert(clk_pin); + FloatSeq *tight_waveform = new FloatSeq; + tight_waveform->push_back(0.0f); + tight_waveform->push_back(0.2f); // 0.4ns period (very tight) + sta_->makeClock("clk", clk_pins, false, 0.4f, tight_waveform, nullptr); + + Slack tight_tns = sta_->totalNegativeSlack(MinMax::max()); + // Very tight clock should create large negative TNS + EXPECT_LT(tight_tns, initial_tns); + + // Upsize cells to partially improve TNS + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack improved_tns = sta_->totalNegativeSlack(MinMax::max()); + // Upsizing should improve (make less negative) TNS + EXPECT_GE(improved_tns, tight_tns); + + // Verify incremental TNS matches full timing + sta_->updateTiming(true); + Slack full_tns = sta_->totalNegativeSlack(MinMax::max()); + EXPECT_NEAR(improved_tns, full_tns, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 23: Verify arrival time at specific pins after an edit. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ArrivalTimeAtPinAfterEdit) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Get initial arrival at reg1/D + Instance *reg1 = network->findChild(top, "reg1"); + ASSERT_NE(reg1, nullptr); + Pin *reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + + Arrival initial_arrival = sta_->pinArrival(reg1_d, RiseFall::rise(), + MinMax::max()); + EXPECT_FALSE(std::isnan(initial_arrival)); + EXPECT_GT(initial_arrival, 0.0f); + + // Upsize buf1 to reduce delay to reg1/D + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Arrival after_arrival = sta_->pinArrival(reg1_d, RiseFall::rise(), + MinMax::max()); + EXPECT_FALSE(std::isnan(after_arrival)); + + // Faster buffer means earlier arrival at reg1/D + EXPECT_LE(after_arrival, initial_arrival); + + // Restore and verify arrival restores + LibertyCell *buf_x1 = network->findLibertyCell("BUF_X1"); + ASSERT_NE(buf_x1, nullptr); + sta_->replaceCell(buf1, buf_x1); + + Arrival restored_arrival = sta_->pinArrival(reg1_d, RiseFall::rise(), + MinMax::max()); + EXPECT_NEAR(restored_arrival, initial_arrival, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 24: Verify hold (min) slack after cell replacement. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, HoldSlackAfterCellReplacement) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_hold_slack = sta_->worstSlack(MinMax::min()); + EXPECT_FALSE(std::isnan(initial_hold_slack)); + + // Upsize buf1 -- this makes the path faster, which can help hold + // violations (hold requires minimum delay) or worsen them depending + // on the design. Either way, the value should be valid. + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack after_hold_slack = sta_->worstSlack(MinMax::min()); + EXPECT_FALSE(std::isnan(after_hold_slack)); + + // Faster cell should worsen hold timing (data arrives earlier) + EXPECT_LE(after_hold_slack, initial_hold_slack); + + // Restore + LibertyCell *buf_x1 = network->findLibertyCell("BUF_X1"); + ASSERT_NE(buf_x1, nullptr); + sta_->replaceCell(buf1, buf_x1); + Slack restored_hold_slack = sta_->worstSlack(MinMax::min()); + EXPECT_NEAR(restored_hold_slack, initial_hold_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 25: Check both setup and hold after multiple edits. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, SetupAndHoldAfterEdits) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_setup = sta_->worstSlack(MinMax::max()); + Slack initial_hold = sta_->worstSlack(MinMax::min()); + + // Edit 1: Add 0.3ns clock uncertainty for both setup and hold + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + sta_->setClockUncertainty(clk, SetupHoldAll::all(), 0.3f); + + Slack setup_after_unc = sta_->worstSlack(MinMax::max()); + Slack hold_after_unc = sta_->worstSlack(MinMax::min()); + + // Setup uncertainty eats into margin from the top + EXPECT_LT(setup_after_unc, initial_setup); + // Hold uncertainty eats into margin from the bottom + EXPECT_LT(hold_after_unc, initial_hold); + + // Edit 2: Upsize buf1 to offset some of the setup degradation + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack setup_after_both = sta_->worstSlack(MinMax::max()); + Slack hold_after_both = sta_->worstSlack(MinMax::min()); + + // Upsizing helps setup (but may hurt hold) + EXPECT_GE(setup_after_both, setup_after_unc); + // Valid results + EXPECT_FALSE(std::isnan(setup_after_both)); + EXPECT_FALSE(std::isnan(hold_after_both)); +} + +//////////////////////////////////////////////////////////////// +// Test 26: Verify incremental vs full consistency after multiple +// heterogeneous edits (cell swap + constraint change). +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, IncrementalVsFullAfterMixedEdits) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Edit 1: Replace buf2 with BUF_X4 + Instance *buf2 = network->findChild(top, "buf2"); + ASSERT_NE(buf2, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf2, buf_x4); + + // Edit 2: Add output load + Port *out1_port = network->findPort(network->cell(top), "out1"); + ASSERT_NE(out1_port, nullptr); + sta_->setPortExtPinCap(out1_port, RiseFallBoth::riseFall(), + sta_->cmdCorner(), MinMaxAll::all(), 0.1f); + + // Edit 3: Add clock uncertainty + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + sta_->setClockUncertainty(clk, SetupHoldAll::max(), 0.2f); + + // Get incremental result + sta_->updateTiming(false); + Slack inc_setup = sta_->worstSlack(MinMax::max()); + Slack inc_tns = sta_->totalNegativeSlack(MinMax::max()); + + // Get full timing result + sta_->updateTiming(true); + Slack full_setup = sta_->worstSlack(MinMax::max()); + Slack full_tns = sta_->totalNegativeSlack(MinMax::max()); + + EXPECT_NEAR(inc_setup, full_setup, 1e-6); + EXPECT_NEAR(inc_tns, full_tns, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 27: Set input delay to different values and verify +// arrival times update correctly. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, InputDelayChangeUpdatesTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Change input delay on in1 from 0.5ns to 3.0ns + Pin *in1 = network->findPin(top, "in1"); + ASSERT_NE(in1, nullptr); + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + + sta_->setInputDelay(in1, RiseFallBoth::riseFall(), + clk, RiseFall::rise(), nullptr, + false, false, MinMaxAll::all(), false, 3.0f); + + Slack large_delay_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(large_delay_slack)); + + // Larger input delay means data arrives later, worsening setup slack + EXPECT_LT(large_delay_slack, initial_slack); + + // Set it very small + sta_->setInputDelay(in1, RiseFallBoth::riseFall(), + clk, RiseFall::rise(), nullptr, + false, false, MinMaxAll::all(), false, 0.01f); + + Slack small_delay_slack = sta_->worstSlack(MinMax::max()); + // Smaller input delay should give better slack + EXPECT_GT(small_delay_slack, large_delay_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 28: Set output delay to different values and verify +// timing updates. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, OutputDelayChangeUpdatesTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Increase output delay on out1 from 0.5ns to 5.0ns + Pin *out1 = network->findPin(top, "out1"); + ASSERT_NE(out1, nullptr); + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + + sta_->setOutputDelay(out1, RiseFallBoth::riseFall(), + clk, RiseFall::rise(), nullptr, + false, false, MinMaxAll::all(), false, 5.0f); + + Slack large_out_delay_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(large_out_delay_slack)); + + // Larger output delay reduces available path time, worsening slack + EXPECT_LT(large_out_delay_slack, initial_slack); + + // Set a very small output delay + sta_->setOutputDelay(out1, RiseFallBoth::riseFall(), + clk, RiseFall::rise(), nullptr, + false, false, MinMaxAll::all(), false, 0.01f); + + Slack small_out_delay_slack = sta_->worstSlack(MinMax::max()); + EXPECT_GT(small_out_delay_slack, large_out_delay_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 29: Set clock latency and verify it shifts arrival/required +// times at register pins. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ClockLatencyAffectsTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + + // Add 1ns source latency to clock + sta_->setClockLatency(clk, nullptr, RiseFallBoth::riseFall(), + MinMaxAll::all(), 1.0f); + + Slack latency_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(latency_slack)); + + // Clock latency applied to both source and capture should not change + // setup slack (it cancels out for same-clock paths). But it does + // shift arrivals. + // For same-clock paths, latency cancels, so slack should be similar. + EXPECT_NEAR(latency_slack, initial_slack, 0.01f); + + // Remove latency + sta_->removeClockLatency(clk, nullptr); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 30: Verify pin slack query at specific pins after edit. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, PinSlackQueryAfterEdit) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Get pin slack at buf1/Z + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + Pin *buf1_z = network->findPin(buf1, "Z"); + ASSERT_NE(buf1_z, nullptr); + + Slack initial_pin_slack = sta_->pinSlack(buf1_z, MinMax::max()); + EXPECT_FALSE(std::isnan(initial_pin_slack)); + + // Also check worst slack correlation + Slack initial_worst = sta_->worstSlack(MinMax::max()); + // Pin slack at buf1/Z should be >= worst slack (worst is the minimum) + EXPECT_GE(initial_pin_slack, initial_worst); + + // Upsize buf1 + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack after_pin_slack = sta_->pinSlack(buf1_z, MinMax::max()); + EXPECT_FALSE(std::isnan(after_pin_slack)); + + // Upsizing should improve the slack at this pin + EXPECT_GE(after_pin_slack, initial_pin_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 31: Verify slew at a vertex updates after cell replacement. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, VertexSlewUpdatesAfterReplace) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Get slew at buf1/Z (output of BUF_X1) + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + Pin *buf1_z = network->findPin(buf1, "Z"); + ASSERT_NE(buf1_z, nullptr); + + Graph *graph = sta_->ensureGraph(); + ASSERT_NE(graph, nullptr); + Vertex *buf1_z_vertex = graph->pinDrvrVertex(buf1_z); + ASSERT_NE(buf1_z_vertex, nullptr); + + Slew initial_slew = sta_->vertexSlew(buf1_z_vertex, RiseFall::rise(), + MinMax::max()); + EXPECT_FALSE(std::isnan(initial_slew)); + EXPECT_GT(initial_slew, 0.0f); + + // Replace buf1 with BUF_X4 (stronger driver = faster slew) + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + // Need to refetch the vertex since the graph may be rebuilt + graph = sta_->ensureGraph(); + buf1_z = network->findPin(buf1, "Z"); + buf1_z_vertex = graph->pinDrvrVertex(buf1_z); + ASSERT_NE(buf1_z_vertex, nullptr); + + Slew after_slew = sta_->vertexSlew(buf1_z_vertex, RiseFall::rise(), + MinMax::max()); + EXPECT_FALSE(std::isnan(after_slew)); + + // Stronger driver (BUF_X4) should produce faster (smaller) slew + EXPECT_LE(after_slew, initial_slew); +} + +//////////////////////////////////////////////////////////////// +// Test 32: Replace buf2 (output path) and verify output path timing. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, OutputPathCellReplacement) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // buf2 is on the output path: reg1/Q -> buf2 -> out1 + Instance *buf2 = network->findChild(top, "buf2"); + ASSERT_NE(buf2, nullptr); + + // Get pin slack at out1 before edit + Pin *out1_pin = network->findPin(top, "out1"); + ASSERT_NE(out1_pin, nullptr); + Slack out1_slack_before = sta_->pinSlack(out1_pin, MinMax::max()); + + // Replace buf2 with BUF_X4 + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf2, buf_x4); + + Slack out1_slack_after = sta_->pinSlack(out1_pin, MinMax::max()); + EXPECT_FALSE(std::isnan(out1_slack_after)); + + // BUF_X4 is faster, out1 slack should improve + EXPECT_GE(out1_slack_after, out1_slack_before); + + // Also check worst slack + Slack after_worst = sta_->worstSlack(MinMax::max()); + EXPECT_GE(after_worst, initial_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 33: Endpoint violation count changes with clock period. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, EndpointViolationCountChanges) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // With 10ns clock, there should be no or few violations + int initial_violations = sta_->endpointViolationCount(MinMax::max()); + EXPECT_GE(initial_violations, 0); + + // Tighten the clock to create violations + Pin *clk_pin = network->findPin(top, "clk"); + ASSERT_NE(clk_pin, nullptr); + PinSet *clk_pins = new PinSet(network); + clk_pins->insert(clk_pin); + FloatSeq *tight_waveform = new FloatSeq; + tight_waveform->push_back(0.0f); + tight_waveform->push_back(0.1f); // 0.2ns period + sta_->makeClock("clk", clk_pins, false, 0.2f, tight_waveform, nullptr); + + int tight_violations = sta_->endpointViolationCount(MinMax::max()); + // Very tight clock should cause violations + EXPECT_GT(tight_violations, initial_violations); + + // Loosen the clock + PinSet *clk_pins2 = new PinSet(network); + clk_pins2->insert(clk_pin); + FloatSeq *loose_waveform = new FloatSeq; + loose_waveform->push_back(0.0f); + loose_waveform->push_back(50.0f); + sta_->makeClock("clk", clk_pins2, false, 100.0f, loose_waveform, nullptr); + + int loose_violations = sta_->endpointViolationCount(MinMax::max()); + // Loose clock should have fewer violations + EXPECT_LT(loose_violations, tight_violations); +} + +//////////////////////////////////////////////////////////////// +// Test 34: Net slack query updates incrementally. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, NetSlackUpdatesIncrementally) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Get net slack on n2 (buf1/Z -> reg1/D) + Net *n2 = network->findNet(top, "n2"); + ASSERT_NE(n2, nullptr); + + Slack initial_net_slack = sta_->netSlack(n2, MinMax::max()); + EXPECT_FALSE(std::isnan(initial_net_slack)); + + // Upsize buf1 to improve the path through n2 + Instance *buf1 = network->findChild(top, "buf1"); + ASSERT_NE(buf1, nullptr); + LibertyCell *buf_x4 = network->findLibertyCell("BUF_X4"); + ASSERT_NE(buf_x4, nullptr); + sta_->replaceCell(buf1, buf_x4); + + Slack after_net_slack = sta_->netSlack(n2, MinMax::max()); + EXPECT_FALSE(std::isnan(after_net_slack)); + + // Net slack on n2 should improve after upsizing buf1 + EXPECT_GE(after_net_slack, initial_net_slack); +} + +//////////////////////////////////////////////////////////////// +// Test 35: Clock latency insertion delay affects timing check. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, ClockInsertionDelayAffectsTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // Clock insertion for same-clock paths cancels in slack calculation. + // Verify that arrival/required times shift by the insertion amount + // even though slack remains the same. + Instance *reg1 = network->findChild(top, "reg1"); + ASSERT_NE(reg1, nullptr); + Pin *reg1_d = network->findPin(reg1, "D"); + ASSERT_NE(reg1_d, nullptr); + + Graph *graph = sta_->ensureGraph(); + ASSERT_NE(graph, nullptr); + Vertex *reg1_d_vertex = graph->pinLoadVertex(reg1_d); + ASSERT_NE(reg1_d_vertex, nullptr); + + Arrival initial_arrival = sta_->pinArrival(reg1_d, RiseFall::rise(), + MinMax::max()); + Required initial_required = sta_->vertexRequired(reg1_d_vertex, + MinMax::max()); + Slack initial_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(initial_arrival)); + EXPECT_FALSE(std::isnan(initial_required)); + + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + + // Add 1ns source insertion delay to the clock + sta_->setClockInsertion(clk, nullptr, RiseFallBoth::riseFall(), + MinMaxAll::all(), EarlyLateAll::all(), 1.0f); + + Arrival after_arrival = sta_->pinArrival(reg1_d, RiseFall::rise(), + MinMax::max()); + Required after_required = sta_->vertexRequired(reg1_d_vertex, + MinMax::max()); + Slack after_slack = sta_->worstSlack(MinMax::max()); + + // For same-clock paths, insertion shifts both arrival and required + // by the same amount, so slack should stay the same + EXPECT_NEAR(after_slack, initial_slack, 0.01f); + + // But arrival should shift by the insertion delay (1ns) + // The arrival includes the clock insertion on the launch side + EXPECT_NEAR(after_arrival - initial_arrival, 1.0f, 0.01f); + + // And required should also shift (capture side) + EXPECT_NEAR(after_required - initial_required, 1.0f, 0.01f); + + // Remove insertion delay + sta_->removeClockInsertion(clk, nullptr); + Slack restored_slack = sta_->worstSlack(MinMax::max()); + EXPECT_NEAR(restored_slack, initial_slack, 1e-6); +} + +//////////////////////////////////////////////////////////////// +// Test 36: Verify timing with drive resistance set on input port. +//////////////////////////////////////////////////////////////// + +TEST_F(IncrementalTimingTest, DriveResistanceAffectsTiming) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + Slack initial_slack = sta_->worstSlack(MinMax::max()); + + // Set a large drive resistance on in1 (slow driver) + Port *in1_port = network->findPort(network->cell(top), "in1"); + ASSERT_NE(in1_port, nullptr); + sta_->setDriveResistance(in1_port, RiseFallBoth::riseFall(), + MinMaxAll::all(), 1000.0f); + + Slack after_slack = sta_->worstSlack(MinMax::max()); + EXPECT_FALSE(std::isnan(after_slack)); + + // High drive resistance means slow input transition, degrading timing + EXPECT_LE(after_slack, initial_slack); + + // Set a very low drive resistance (fast driver) + sta_->setDriveResistance(in1_port, RiseFallBoth::riseFall(), + MinMaxAll::all(), 0.001f); + + Slack fast_slack = sta_->worstSlack(MinMax::max()); + // Fast driver should give better timing + EXPECT_GE(fast_slack, after_slack); +} + } // namespace sta diff --git a/search/test/search_fanin_fanout_deep.tcl b/search/test/search_fanin_fanout_deep.tcl index a6d28d2c..67fa27ec 100644 --- a/search/test/search_fanin_fanout_deep.tcl +++ b/search/test/search_fanin_fanout_deep.tcl @@ -166,27 +166,19 @@ foreach pe $paths2 { } puts "--- get_fanin with -trace_arcs all (thru disabled/constants) ---" -catch { - set fanin_thru [get_fanin -to [get_pins reg1/D] -trace_arcs all] - puts "Fanin trace_arcs all: [llength $fanin_thru]" -} +set fanin_thru [get_fanin -to [get_pins reg1/D] -trace_arcs all] +puts "Fanin trace_arcs all: [llength $fanin_thru]" puts "--- get_fanin with -trace_arcs timing ---" -catch { - set fanin_timing [get_fanin -to [get_pins reg1/D] -trace_arcs timing] - puts "Fanin trace_arcs timing: [llength $fanin_timing]" -} +set fanin_timing [get_fanin -to [get_pins reg1/D] -trace_arcs timing] +puts "Fanin trace_arcs timing: [llength $fanin_timing]" puts "--- get_fanin with -trace_arcs enabled ---" -catch { - set fanin_enabled [get_fanin -to [get_pins reg1/D] -trace_arcs enabled] - puts "Fanin trace_arcs enabled: [llength $fanin_enabled]" -} +set fanin_enabled [get_fanin -to [get_pins reg1/D] -trace_arcs enabled] +puts "Fanin trace_arcs enabled: [llength $fanin_enabled]" puts "--- get_fanin thru constants ---" set_case_analysis 1 [get_ports in1] -catch { - set fanin_const [get_fanin -to [get_pins reg1/D] -trace_arcs all] - puts "Fanin with constants: [llength $fanin_const]" -} +set fanin_const [get_fanin -to [get_pins reg1/D] -trace_arcs all] +puts "Fanin with constants: [llength $fanin_const]" unset_case_analysis [get_ports in1] diff --git a/search/test/search_multiclock.tcl b/search/test/search_multiclock.tcl index fc98fa1e..25da8f3b 100644 --- a/search/test/search_multiclock.tcl +++ b/search/test/search_multiclock.tcl @@ -38,15 +38,13 @@ report_checks -path_delay max report_checks -path_delay min puts "--- group_path with -weight ---" -catch { group_path -name weighted_group -from [get_ports in1] -weight 2.0 } +group_path -name weighted_group -from [get_ports in1] -weight 2.0 puts "--- group_path with -default ---" catch { group_path -name default_group -default } puts "--- report_checks with -group filter ---" -catch { - report_checks -path_delay max -group_path_count 3 -} +report_checks -path_delay max -group_path_count 3 puts "--- report_path_end with specific endpoints ---" set pe_list [find_timing_paths -path_delay max -endpoint_path_count 3] @@ -71,15 +69,13 @@ set paths_mm [find_timing_paths -path_delay min_max -endpoint_path_count 3] puts "Min_max paths: [llength $paths_mm]" puts "--- find_timing_paths with unique_edges ---" -catch { - set paths_ue [find_timing_paths -path_delay max -endpoint_path_count 5 -unique_paths_to_endpoint] - puts "Unique edge paths: [llength $paths_ue]" -} +set paths_ue [find_timing_paths -path_delay max -endpoint_path_count 5 -unique_paths_to_endpoint] +puts "Unique edge paths: [llength $paths_ue]" puts "--- set_clock_sense ---" -catch { set_clock_sense -positive [get_pins ckbuf1/Z] -clocks clk } +set_clock_sense -positive [get_pins ckbuf1/Z] -clocks clk report_checks -path_delay max -catch { set_clock_sense -stop [get_pins ckbuf2/Z] -clocks clk } +set_clock_sense -stop [get_pins ckbuf2/Z] -clocks clk report_checks -path_delay max puts "--- report_check_types ---" diff --git a/search/test/search_multicorner_analysis.tcl b/search/test/search_multicorner_analysis.tcl index 293d52d8..0734d6d9 100644 --- a/search/test/search_multicorner_analysis.tcl +++ b/search/test/search_multicorner_analysis.tcl @@ -20,37 +20,27 @@ set_output_delay -clock clk 1.5 [get_ports out2] report_checks > /dev/null puts "--- set_analysis_type bc_wc ---" -catch { - set_operating_conditions -analysis_type bc_wc -} +set_operating_conditions -analysis_type bc_wc report_checks -path_delay max > /dev/null puts "--- set_analysis_type single ---" -catch { - set_operating_conditions -analysis_type single -} +set_operating_conditions -analysis_type single report_checks -path_delay max > /dev/null puts "--- set_analysis_type on_chip_variation ---" -catch { - set_operating_conditions -analysis_type on_chip_variation -} +set_operating_conditions -analysis_type on_chip_variation report_checks -path_delay max -format full_clock_expanded report_checks -path_delay min -format full_clock_expanded puts "--- set_voltage ---" -catch { - set_voltage 1.1 - set_voltage 1.1 -min 0.9 - report_checks -path_delay max > /dev/null -} +set_voltage 1.1 +set_voltage 1.1 -min 0.9 +report_checks -path_delay max > /dev/null puts "--- set_voltage on net ---" -catch { - set_voltage 1.2 -object_list [get_nets n1] - set_voltage 1.2 -min 1.0 -object_list [get_nets n1] - report_checks -path_delay max > /dev/null -} +set_voltage 1.2 -object_list [get_nets n1] +set_voltage 1.2 -min 1.0 -object_list [get_nets n1] +report_checks -path_delay max > /dev/null puts "--- set_load (port external pin cap) ---" set_load 0.05 [get_ports out1] @@ -64,32 +54,24 @@ report_checks -path_delay max report_checks -path_delay min puts "--- set_load -wire_load ---" -catch { - set_load -wire_load 0.01 [get_ports out1] - report_checks -path_delay max > /dev/null -} +set_load -wire_load 0.01 [get_ports out1] +report_checks -path_delay max > /dev/null puts "--- set_fanout_load ---" -catch { - set_fanout_load 4 [get_ports out1] - report_checks -path_delay max > /dev/null -} +set_fanout_load 4 [get_ports out1] +report_checks -path_delay max > /dev/null puts "--- Net capacitance ---" -catch { - set corner [sta::cmd_corner] - set net_cap [[get_nets n1] capacitance $corner max] - puts "Net n1 capacitance: $net_cap" - set pin_cap [[get_nets n1] pin_capacitance $corner max] - puts "Net n1 pin_cap: $pin_cap" - set wire_cap [[get_nets n1] wire_capacitance $corner max] - puts "Net n1 wire_cap: $wire_cap" -} +set corner [sta::cmd_corner] +set net_cap [[get_nets n1] capacitance $corner max] +puts "Net n1 capacitance: $net_cap" +set pin_cap [[get_nets n1] pin_capacitance $corner max] +puts "Net n1 pin_cap: $pin_cap" +set wire_cap [[get_nets n1] wire_capacitance $corner max] +puts "Net n1 wire_cap: $wire_cap" puts "--- set_wire_load_mode ---" -catch { - set_wire_load_mode enclosed -} +set_wire_load_mode enclosed puts "--- report_checks with various fields after load changes ---" report_checks -fields {capacitance slew fanout} -path_delay max @@ -107,25 +89,19 @@ set_drive 100 [get_ports in1] report_checks -path_delay max > /dev/null puts "--- set_driving_cell ---" -catch { - set_driving_cell -lib_cell BUF_X1 -library NangateOpenCellLibrary [get_ports in1] - report_checks -path_delay max -from [get_ports in1] -} +set_driving_cell -lib_cell BUF_X1 -library NangateOpenCellLibrary [get_ports in1] +report_checks -path_delay max -from [get_ports in1] puts "--- Timing derate with cell-level ---" set_timing_derate -early 0.95 set_timing_derate -late 1.05 report_checks -path_delay max > /dev/null -catch { - set_timing_derate -early -cell_delay 0.93 - set_timing_derate -late -cell_delay 1.07 - report_checks -path_delay max > /dev/null -} -catch { - set_timing_derate -early -net_delay 0.96 - set_timing_derate -late -net_delay 1.04 - report_checks -path_delay max > /dev/null -} +set_timing_derate -early -cell_delay 0.93 +set_timing_derate -late -cell_delay 1.07 +report_checks -path_delay max > /dev/null +set_timing_derate -early -net_delay 0.96 +set_timing_derate -late -net_delay 1.04 +report_checks -path_delay max > /dev/null unset_timing_derate puts "--- report_checks after all modifications ---" @@ -141,15 +117,11 @@ set sdc_file [make_result_file "search_multicorner_analysis.sdc"] write_sdc $sdc_file puts "--- set_resistance on net ---" -catch { - set_resistance 100 [get_nets n1] - report_checks -path_delay max > /dev/null -} +set_resistance 100 [get_nets n1] +report_checks -path_delay max > /dev/null puts "--- set_max_area ---" -catch { - set_max_area 1000 -} +set_max_area 1000 puts "--- isClock / isPropagatedClock queries ---" catch { diff --git a/search/test/search_path_delay_output.tcl b/search/test/search_path_delay_output.tcl index fcba7f9f..31b89bf5 100644 --- a/search/test/search_path_delay_output.tcl +++ b/search/test/search_path_delay_output.tcl @@ -169,8 +169,8 @@ foreach pe $pe_out { puts "margin: [$pe margin]" puts "data_arrival: [$pe data_arrival_time]" puts "data_required: [$pe data_required_time]" - catch { puts "source_clk_offset: [$pe source_clk_offset]" } - catch { puts "target_clk: [get_name [$pe target_clk]]" } - catch { puts "target_clk_time: [$pe target_clk_time]" } + puts "source_clk_offset: [$pe source_clk_offset]" + puts "target_clk: [get_name [$pe target_clk]]" + puts "target_clk_time: [$pe target_clk_time]" break } diff --git a/search/test/search_path_enum_groups.tcl b/search/test/search_path_enum_groups.tcl index b6f36f3c..8c88d865 100644 --- a/search/test/search_path_enum_groups.tcl +++ b/search/test/search_path_enum_groups.tcl @@ -74,11 +74,9 @@ set group_names [sta::path_group_names] puts "Path group names: $group_names" puts "--- is_path_group_name ---" -catch { - puts "clk is group: [sta::is_path_group_name clk]" - puts "input_paths is group: [sta::is_path_group_name input_paths]" - puts "nonexistent is group: [sta::is_path_group_name nonexistent_group]" -} +puts "clk is group: [sta::is_path_group_name clk]" +puts "input_paths is group: [sta::is_path_group_name input_paths]" +puts "nonexistent is group: [sta::is_path_group_name nonexistent_group]" puts "--- group_path -default ---" catch { diff --git a/search/test/search_port_pin_properties.tcl b/search/test/search_port_pin_properties.tcl index dffd45e1..511ddc2b 100644 --- a/search/test/search_port_pin_properties.tcl +++ b/search/test/search_port_pin_properties.tcl @@ -136,7 +136,7 @@ puts "DFF_X1 base_name: [get_property $dff_cell base_name]" puts "DFF_X1 is_buffer: [get_property $dff_cell is_buffer]" set dff_lib [get_property $dff_cell library] puts "DFF_X1 library: [get_name $dff_lib]" -catch { puts "DFF_X1 area: [get_property $dff_cell area]" } +puts "DFF_X1 area: [get_property $dff_cell area]" catch { puts "DFF_X1 leakage: [get_property $dff_cell cell_leakage_power]" } puts "--- LibertyPort properties ---" @@ -144,7 +144,7 @@ set lp_d [get_lib_pins NangateOpenCellLibrary/DFF_X1/D] puts "DFF_X1/D name: [get_property $lp_d name]" puts "DFF_X1/D full_name: [get_property $lp_d full_name]" puts "DFF_X1/D direction: [get_property $lp_d direction]" -catch { puts "DFF_X1/D capacitance: [get_property $lp_d capacitance]" } +puts "DFF_X1/D capacitance: [get_property $lp_d capacitance]" catch { puts "DFF_X1/D is_clock: [get_property $lp_d is_clock]" } catch { puts "DFF_X1/D is_register_clock: [get_property $lp_d is_register_clock]" } set lp_ck [get_lib_pins NangateOpenCellLibrary/DFF_X1/CK] @@ -190,19 +190,13 @@ foreach pe $path_ends { puts "pathend startpoint: [get_full_name $sp]" set ep [get_property $pe endpoint] puts "pathend endpoint: [get_full_name $ep]" - catch { - set sc [get_property $pe startpoint_clock] - puts "pathend startpoint_clock: [get_name $sc]" - } - catch { - set ec [get_property $pe endpoint_clock] - puts "pathend endpoint_clock: [get_name $ec]" - } + set sc [get_property $pe startpoint_clock] + puts "pathend startpoint_clock: [get_name $sc]" + set ec [get_property $pe endpoint_clock] + puts "pathend endpoint_clock: [get_name $ec]" puts "pathend slack: [get_property $pe slack]" - catch { - set pts [get_property $pe points] - puts "pathend points count: [llength $pts]" - } + set pts [get_property $pe points] + puts "pathend points count: [llength $pts]" break } diff --git a/search/test/search_power_activity.tcl b/search/test/search_power_activity.tcl index a7ad51c9..9fd9c36d 100644 --- a/search/test/search_power_activity.tcl +++ b/search/test/search_power_activity.tcl @@ -21,14 +21,10 @@ puts "--- report_power ---" report_power puts "--- report_power -instances ---" -catch { - report_power -instances [get_cells {reg1 reg2 and1 buf1}] -} +report_power -instances [get_cells {reg1 reg2 and1 buf1}] puts "--- report_power -digits 6 ---" -catch { - report_power -digits 6 -} +report_power -digits 6 puts "--- Pin activity ---" catch { @@ -53,22 +49,16 @@ catch { } puts "--- set_power_activity on global ---" -catch { - set_power_activity -global -activity 0.2 -duty 0.5 - report_power -} +set_power_activity -global -activity 0.2 -duty 0.5 +report_power puts "--- set_power_activity on input_ports ---" -catch { - set_power_activity -input -activity 0.4 -duty 0.5 - report_power -} +set_power_activity -input -activity 0.4 -duty 0.5 +report_power puts "--- report_power with clock propagation ---" set_propagated_clock [get_clocks clk] -catch { - report_power -} +report_power puts "--- isClock queries ---" catch { @@ -81,9 +71,7 @@ catch { puts "--- report with timing derate after power ---" set_timing_derate -early 0.95 set_timing_derate -late 1.05 -catch { - report_power -} +report_power unset_timing_derate puts "--- Slew limit checking after power ---" diff --git a/search/test/search_property_extra.tcl b/search/test/search_property_extra.tcl index 024f04ea..0741aeff 100644 --- a/search/test/search_property_extra.tcl +++ b/search/test/search_property_extra.tcl @@ -47,7 +47,7 @@ puts "lport name: [get_property $lport name]" puts "lport full_name: [get_property $lport full_name]" puts "lport direction: [get_property $lport direction]" catch { puts "lport function: [get_property $lport function]" } -catch { puts "lport capacitance: [get_property $lport capacitance]" } +puts "lport capacitance: [get_property $lport capacitance]" catch { puts "lport max_capacitance: [get_property $lport max_capacitance]" } catch { puts "lport max_transition: [get_property $lport max_transition]" } catch { puts "lport is_register_clock: [get_property $lport is_register_clock]" } @@ -60,15 +60,13 @@ set and_cell [get_lib_cells NangateOpenCellLibrary/AND2_X1] puts "and is_buffer: [get_property $and_cell is_buffer]" set dff_cell [get_lib_cells NangateOpenCellLibrary/DFF_X1] puts "dff is_buffer: [get_property $dff_cell is_buffer]" -catch { puts "dff area: [get_property $dff_cell area]" } +puts "dff area: [get_property $dff_cell area]" catch { puts "dff cell_leakage_power: [get_property $dff_cell cell_leakage_power]" } puts "--- LibertyLibrary properties ---" set lib [get_libs NangateOpenCellLibrary] -catch { - set lib_cell_property [get_property -object_type lib $lib name] - puts "lib by lib type: $lib_cell_property" -} +set lib_cell_property [get_property -object_type lib $lib name] +puts "lib by lib type: $lib_cell_property" puts "--- Clock extra properties ---" set clk_obj [get_clocks clk] @@ -133,20 +131,12 @@ foreach p $fan_pins { } puts "--- Slew/Cap/Fanout check slack ---" -catch { - puts "Max slew check slack: [sta::max_slew_check_slack]" - puts "Max slew check limit: [sta::max_slew_check_limit]" -} -catch { - puts "Max cap check slack: [sta::max_capacitance_check_slack]" - puts "Max cap check limit: [sta::max_capacitance_check_limit]" -} -catch { - puts "Max fanout check slack: [sta::max_fanout_check_slack]" - puts "Max fanout check limit: [sta::max_fanout_check_limit]" -} -catch { - puts "Max slew violation count: [sta::max_slew_violation_count]" - puts "Max cap violation count: [sta::max_capacitance_violation_count]" - puts "Max fanout violation count: [sta::max_fanout_violation_count]" -} +puts "Max slew check slack: [sta::max_slew_check_slack]" +puts "Max slew check limit: [sta::max_slew_check_limit]" +puts "Max cap check slack: [sta::max_capacitance_check_slack]" +puts "Max cap check limit: [sta::max_capacitance_check_limit]" +puts "Max fanout check slack: [sta::max_fanout_check_slack]" +puts "Max fanout check limit: [sta::max_fanout_check_limit]" +puts "Max slew violation count: [sta::max_slew_violation_count]" +puts "Max cap violation count: [sta::max_capacitance_violation_count]" +puts "Max fanout violation count: [sta::max_fanout_violation_count]" diff --git a/search/test/search_property_libport_deep.tcl b/search/test/search_property_libport_deep.tcl index 43f7c88d..ef01cdfd 100644 --- a/search/test/search_property_libport_deep.tcl +++ b/search/test/search_property_libport_deep.tcl @@ -128,15 +128,15 @@ puts "reg1 is_memory: [get_property $reg_inst is_memory]" ############################################################ puts "--- LibertyCell area and leakage ---" set dff_cell [get_lib_cells NangateOpenCellLibrary/DFF_X1] -catch { puts "DFF_X1 area: [get_property $dff_cell area]" } +puts "DFF_X1 area: [get_property $dff_cell area]" catch { puts "DFF_X1 cell_leakage_power: [get_property $dff_cell cell_leakage_power]" } set buf_cell [get_lib_cells NangateOpenCellLibrary/BUF_X1] -catch { puts "BUF_X1 area: [get_property $buf_cell area]" } +puts "BUF_X1 area: [get_property $buf_cell area]" catch { puts "BUF_X1 cell_leakage_power: [get_property $buf_cell cell_leakage_power]" } set inv_cell [get_lib_cells NangateOpenCellLibrary/INV_X1] -catch { puts "INV_X1 area: [get_property $inv_cell area]" } +puts "INV_X1 area: [get_property $inv_cell area]" set and_cell [get_lib_cells NangateOpenCellLibrary/AND2_X1] -catch { puts "AND2_X1 area: [get_property $and_cell area]" } +puts "AND2_X1 area: [get_property $and_cell area]" ############################################################ # Path group matching: group_path -name with -from and -through @@ -177,8 +177,8 @@ foreach pe $paths_min { puts "--- path_group_names ---" set group_names [sta::path_group_names] puts "Path group names: $group_names" -catch { puts "input_grp is group: [sta::is_path_group_name input_grp]" } -catch { puts "nonexistent is group: [sta::is_path_group_name nonexistent_grp]" } +puts "input_grp is group: [sta::is_path_group_name input_grp]" +puts "nonexistent is group: [sta::is_path_group_name nonexistent_grp]" ############################################################ # TimingArcSet properties on different cell types diff --git a/search/test/search_pvt_analysis.tcl b/search/test/search_pvt_analysis.tcl index 39c85c6b..1778a3ce 100644 --- a/search/test/search_pvt_analysis.tcl +++ b/search/test/search_pvt_analysis.tcl @@ -99,30 +99,24 @@ unset_timing_derate # Timing derate on instance ############################################################ puts "--- timing_derate on instance ---" -catch { - set_timing_derate -early 0.9 [get_cells reg1] - set_timing_derate -late 1.1 [get_cells reg1] - report_checks -path_delay max - unset_timing_derate -} +set_timing_derate -early 0.9 [get_cells reg1] +set_timing_derate -late 1.1 [get_cells reg1] +report_checks -path_delay max +unset_timing_derate ############################################################ # Set slew limit on clock ############################################################ puts "--- set_max_transition on clock ---" -catch { - set_max_transition 0.5 -clock_path [get_clocks clk1] - report_check_types -max_slew -} +set_max_transition 0.5 -clock_path [get_clocks clk1] +report_check_types -max_slew ############################################################ # Set capacitance limit on port ############################################################ puts "--- set_max_capacitance on port ---" -catch { - set_max_capacitance 0.1 [get_ports out1] - report_check_types -max_capacitance -} +set_max_capacitance 0.1 [get_ports out1] +report_check_types -max_capacitance ############################################################ # Port loading diff --git a/search/test/search_register_deep.tcl b/search/test/search_register_deep.tcl index 19431a10..2eb737ab 100644 --- a/search/test/search_register_deep.tcl +++ b/search/test/search_register_deep.tcl @@ -162,10 +162,8 @@ catch { # set_clock_gating_check ############################################################ puts "--- set_clock_gating_check ---" -catch { - set_clock_gating_check -setup 0.5 [get_cells clk_gate] - report_checks -path_delay max -} +set_clock_gating_check -setup 0.5 [get_cells clk_gate] +report_checks -path_delay max ############################################################ # write_sdc diff --git a/search/test/search_report_path_detail.tcl b/search/test/search_report_path_detail.tcl index 34c82acc..edd9b756 100644 --- a/search/test/search_report_path_detail.tcl +++ b/search/test/search_report_path_detail.tcl @@ -150,12 +150,12 @@ puts "--- find_requireds ---" sta::find_requireds puts "--- report internal debug ---" -catch { sta::report_tag_groups } -catch { sta::report_tags } -catch { sta::report_clk_infos } -catch { sta::report_arrival_entries } -catch { sta::report_required_entries } -catch { sta::report_path_count_histogram } +sta::report_tag_groups +sta::report_tags +sta::report_clk_infos +sta::report_arrival_entries +sta::report_required_entries +sta::report_path_count_histogram puts "--- report_path_end header/footer ---" set pe_for_report [find_timing_paths -path_delay max -endpoint_path_count 1] diff --git a/search/test/search_report_path_latch_expanded.tcl b/search/test/search_report_path_latch_expanded.tcl index 10634373..b1b9287e 100644 --- a/search/test/search_report_path_latch_expanded.tcl +++ b/search/test/search_report_path_latch_expanded.tcl @@ -70,9 +70,9 @@ foreach pe $paths_max { puts " is_latch: [$pe is_latch_check] is_check: [$pe is_check] slack=[$pe slack]" puts " data_arrival: [$pe data_arrival_time] data_required: [$pe data_required_time]" puts " margin: [$pe margin]" - catch { puts " source_clk_latency: [$pe source_clk_latency]" } - catch { puts " target_clk_delay: [$pe target_clk_delay]" } - catch { puts " target_clk_uncertainty: [$pe target_clk_uncertainty]" } + puts " source_clk_latency: [$pe source_clk_latency]" + puts " target_clk_delay: [$pe target_clk_delay]" + puts " target_clk_uncertainty: [$pe target_clk_uncertainty]" } ############################################################ @@ -124,14 +124,10 @@ foreach pe $paths_max2 { set ep [get_property $pe endpoint] puts " endpoint: [get_full_name $ep]" puts " slack: [get_property $pe slack]" - catch { - set ec [get_property $pe endpoint_clock] - puts " endpoint_clock: [get_name $ec]" - } - catch { - set ecp [get_property $pe endpoint_clock_pin] - puts " endpoint_clock_pin: [get_full_name $ecp]" - } + set ec [get_property $pe endpoint_clock] + puts " endpoint_clock: [get_name $ec]" + set ecp [get_property $pe endpoint_clock_pin] + puts " endpoint_clock_pin: [get_full_name $ecp]" set points [get_property $pe points] puts " points: [llength $points]" break diff --git a/search/test/search_sim_const_prop.tcl b/search/test/search_sim_const_prop.tcl index 2cafb514..3f6bef95 100644 --- a/search/test/search_sim_const_prop.tcl +++ b/search/test/search_sim_const_prop.tcl @@ -183,10 +183,8 @@ unset_clock_uncertainty [get_clocks clk] # Latch borrow limit ############################################################ puts "--- set_max_time_borrow ---" -catch { - set_max_time_borrow 1.0 [get_clocks clk] - report_checks -path_delay max -} +set_max_time_borrow 1.0 [get_clocks clk] +report_checks -path_delay max ############################################################ # Min pulse width @@ -212,11 +210,9 @@ unset_case_analysis [get_ports in1] # Disable timing on various targets ############################################################ puts "--- set_disable_timing port ---" -catch { - set_disable_timing [get_ports in1] - report_checks -path_delay max - unset_disable_timing [get_ports in1] -} +set_disable_timing [get_ports in1] +report_checks -path_delay max +unset_disable_timing [get_ports in1] puts "--- set_disable_timing instance ---" set_disable_timing [get_cells buf1] @@ -270,14 +266,12 @@ unset_timing_derate # Tag/group reporting (for Tag.cc coverage) ############################################################ puts "--- tag/group reporting ---" -catch { - puts "tag_count: [sta::tag_count]" - puts "tag_group_count: [sta::tag_group_count]" - puts "clk_info_count: [sta::clk_info_count]" - puts "path_count: [sta::path_count]" -} +puts "tag_count: [sta::tag_count]" +puts "tag_group_count: [sta::tag_group_count]" +puts "clk_info_count: [sta::clk_info_count]" +puts "path_count: [sta::path_count]" puts "--- report internal ---" -catch { sta::report_tags } -catch { sta::report_clk_infos } -catch { sta::report_tag_groups } +sta::report_tags +sta::report_clk_infos +sta::report_tag_groups diff --git a/search/test/search_sim_logic_clk_network.tcl b/search/test/search_sim_logic_clk_network.tcl index b830c820..c12e835b 100644 --- a/search/test/search_sim_logic_clk_network.tcl +++ b/search/test/search_sim_logic_clk_network.tcl @@ -157,9 +157,7 @@ report_clock_skew -hold ############################################################ puts "--- clock min period ---" report_clock_min_period -catch { - report_clock_min_period -include_port_paths -} +report_clock_min_period -include_port_paths ############################################################ # Clock latency reporting @@ -167,9 +165,7 @@ catch { puts "--- clock latency report ---" set_propagated_clock [get_clocks clk] report_clock_latency -catch { - report_clock_latency -include_internal_latency -} +report_clock_latency -include_internal_latency report_clock_latency -digits 6 unset_propagated_clock [get_clocks clk] @@ -194,49 +190,37 @@ report_checks -through [get_pins clk_gate/ZN] -path_delay min # Various bidirectional/tristate enable flags ############################################################ puts "--- bidirect inst paths ---" -catch { - sta::set_bidirect_inst_paths_enabled 1 - report_checks -path_delay max - sta::set_bidirect_inst_paths_enabled 0 - report_checks -path_delay max -} +sta::set_bidirect_inst_paths_enabled 1 +report_checks -path_delay max +sta::set_bidirect_inst_paths_enabled 0 +report_checks -path_delay max puts "--- bidirect net paths ---" -catch { - sta::set_bidirect_net_paths_enabled 1 - report_checks -path_delay max - sta::set_bidirect_net_paths_enabled 0 - report_checks -path_delay max -} +sta::set_bidirect_net_paths_enabled 1 +report_checks -path_delay max +sta::set_bidirect_net_paths_enabled 0 +report_checks -path_delay max puts "--- clk thru tristate ---" -catch { - sta::set_clk_thru_tristate_enabled 1 - report_checks -path_delay max - sta::set_clk_thru_tristate_enabled 0 - report_checks -path_delay max -} +sta::set_clk_thru_tristate_enabled 1 +report_checks -path_delay max +sta::set_clk_thru_tristate_enabled 0 +report_checks -path_delay max puts "--- dynamic loop breaking ---" -catch { - sta::set_dynamic_loop_breaking 1 - report_checks -path_delay max - sta::set_dynamic_loop_breaking 0 - report_checks -path_delay max -} +sta::set_dynamic_loop_breaking 1 +report_checks -path_delay max +sta::set_dynamic_loop_breaking 0 +report_checks -path_delay max puts "--- use default arrival clock ---" -catch { - sta::set_use_default_arrival_clock 1 - report_checks -path_delay max - sta::set_use_default_arrival_clock 0 - report_checks -path_delay max -} +sta::set_use_default_arrival_clock 1 +report_checks -path_delay max +sta::set_use_default_arrival_clock 0 +report_checks -path_delay max puts "--- propagate all clocks ---" -catch { - sta::set_propagate_all_clocks 1 - report_checks -path_delay max - sta::set_propagate_all_clocks 0 - report_checks -path_delay max -} +sta::set_propagate_all_clocks 1 +report_checks -path_delay max +sta::set_propagate_all_clocks 0 +report_checks -path_delay max diff --git a/search/test/search_sta_extra.tcl b/search/test/search_sta_extra.tcl index f33d4e3a..4a6426aa 100644 --- a/search/test/search_sta_extra.tcl +++ b/search/test/search_sta_extra.tcl @@ -29,10 +29,8 @@ foreach pe $paths2 { sta::set_report_path_format full puts "--- worstSlack single-arg form ---" -catch { - set ws [sta::worst_slack_cmd max] - puts "worst_slack: $ws" -} +set ws [sta::worst_slack_cmd max] +puts "worst_slack: $ws" puts "--- checkFanout via report_check_types ---" set_max_fanout 2 [current_design] @@ -52,30 +50,28 @@ report_checks -slack_min -10 -path_delay max report_checks -slack_max 100 -slack_min -100 -path_delay max puts "--- set_report_path_field_properties ---" -catch { sta::set_report_path_field_properties "delay" "Delay" 10 0 } -catch { sta::set_report_path_field_width "delay" 12 } +sta::set_report_path_field_properties "delay" "Delay" 10 0 +sta::set_report_path_field_width "delay" 12 report_checks -path_delay max puts "--- set_report_path_sigmas ---" -catch { sta::set_report_path_sigmas 1 } +sta::set_report_path_sigmas 1 report_checks -path_delay max -catch { sta::set_report_path_sigmas 0 } +sta::set_report_path_sigmas 0 puts "--- find_timing_paths with recovery/removal/gating_setup/gating_hold ---" -catch { - sta::set_recovery_removal_checks_enabled 1 - sta::set_gated_clk_checks_enabled 1 - set paths_all [find_timing_paths -path_delay max -endpoint_path_count 5 -group_path_count 5] - puts "Paths: [llength $paths_all]" - sta::set_recovery_removal_checks_enabled 0 - sta::set_gated_clk_checks_enabled 0 -} +sta::set_recovery_removal_checks_enabled 1 +sta::set_gated_clk_checks_enabled 1 +set paths_all [find_timing_paths -path_delay max -endpoint_path_count 5 -group_path_count 5] +puts "Paths: [llength $paths_all]" +sta::set_recovery_removal_checks_enabled 0 +sta::set_gated_clk_checks_enabled 0 puts "--- report_annotated_delay ---" -catch { report_annotated_delay } +report_annotated_delay puts "--- report_annotated_check ---" -catch { report_annotated_check } +report_annotated_check puts "--- report_checks with -path_delay max_rise/max_fall/min_rise/min_fall ---" report_checks -path_delay max_rise -format end @@ -139,19 +135,15 @@ foreach pe $paths_v { } puts "--- vertex_worst_arrival_path ---" -catch { - set warr [sta::vertex_worst_arrival_path $wv max] - if { $warr != "NULL" } { - puts "worst_arrival_path pin: [get_full_name [$warr pin]]" - } +set warr [sta::vertex_worst_arrival_path $wv max] +if { $warr != "NULL" } { + puts "worst_arrival_path pin: [get_full_name [$warr pin]]" } puts "--- vertex_worst_slack_path ---" -catch { - set wslk [sta::vertex_worst_slack_path $wv max] - if { $wslk != "NULL" } { - puts "worst_slack_path pin: [get_full_name [$wslk pin]]" - } +set wslk [sta::vertex_worst_slack_path $wv max] +if { $wslk != "NULL" } { + puts "worst_slack_path pin: [get_full_name [$wslk pin]]" } puts "--- report_path_end with prev_end ---" @@ -165,17 +157,15 @@ foreach pe $paths3 { } puts "--- make_instance ---" -catch { - set and_cell2 [get_lib_cells NangateOpenCellLibrary/AND2_X1] - sta::make_instance new_inst $and_cell2 - puts "make_instance: done" -} +set and_cell2 [get_lib_cells NangateOpenCellLibrary/AND2_X1] +sta::make_instance new_inst $and_cell2 +puts "make_instance: done" puts "--- pocv_enabled ---" -catch { puts "pocv_enabled: [sta::pocv_enabled]" } +puts "pocv_enabled: [sta::pocv_enabled]" puts "--- report_checks -summary format ---" report_checks -path_delay max -format summary puts "--- clear_sta ---" -catch { sta::clear_sta } +sta::clear_sta diff --git a/search/test/search_worst_slack_sta.tcl b/search/test/search_worst_slack_sta.tcl index 9f1f3518..64663521 100644 --- a/search/test/search_worst_slack_sta.tcl +++ b/search/test/search_worst_slack_sta.tcl @@ -73,23 +73,19 @@ if { $wv_min != "NULL" } { puts "--- vertex_worst_arrival_path ---" if { $wv_max != "NULL" } { - catch { - set warr [sta::vertex_worst_arrival_path $wv_max max] - if { $warr != "NULL" } { - puts "worst_arrival_path pin: [get_full_name [$warr pin]]" - puts "worst_arrival_path arrival: [$warr arrival]" - } + set warr [sta::vertex_worst_arrival_path $wv_max max] + if { $warr != "NULL" } { + puts "worst_arrival_path pin: [get_full_name [$warr pin]]" + puts "worst_arrival_path arrival: [$warr arrival]" } } puts "--- vertex_worst_slack_path ---" if { $wv_max != "NULL" } { - catch { - set wslk [sta::vertex_worst_slack_path $wv_max max] - if { $wslk != "NULL" } { - puts "worst_slack_path pin: [get_full_name [$wslk pin]]" - puts "worst_slack_path slack: [$wslk slack]" - } + set wslk [sta::vertex_worst_slack_path $wv_max max] + if { $wslk != "NULL" } { + puts "worst_slack_path pin: [get_full_name [$wslk pin]]" + puts "worst_slack_path slack: [$wslk slack]" } } @@ -147,15 +143,15 @@ catch { } puts "--- set_report_path_field_properties ---" -catch { sta::set_report_path_field_properties "delay" "Dly" 10 0 } +sta::set_report_path_field_properties "delay" "Dly" 10 0 report_checks -path_delay max > /dev/null -catch { sta::set_report_path_field_width "delay" 12 } +sta::set_report_path_field_width "delay" 12 report_checks -path_delay max > /dev/null puts "--- set_report_path_sigmas ---" -catch { sta::set_report_path_sigmas 1 } +sta::set_report_path_sigmas 1 report_checks -path_delay max > /dev/null -catch { sta::set_report_path_sigmas 0 } +sta::set_report_path_sigmas 0 puts "--- set_report_path_no_split ---" sta::set_report_path_no_split 1 @@ -169,10 +165,10 @@ catch { } puts "--- pocv ---" -catch { puts "pocv_enabled: [sta::pocv_enabled]" } +puts "pocv_enabled: [sta::pocv_enabled]" puts "--- report_annotated_delay ---" -catch { report_annotated_delay } +report_annotated_delay puts "--- report_annotated_check ---" -catch { report_annotated_check } +report_annotated_check diff --git a/search/test/search_write_sdf_model.tcl b/search/test/search_write_sdf_model.tcl index 11d55d7b..1deee696 100644 --- a/search/test/search_write_sdf_model.tcl +++ b/search/test/search_write_sdf_model.tcl @@ -44,16 +44,12 @@ set model_file3 [make_result_file "search_test1_model3.lib"] write_timing_model -library_name my_custom_lib -cell_name my_custom_cell2 $model_file3 puts "--- Network edit: make_instance ---" -catch { - make_instance new_buf1 [get_lib_cells NangateOpenCellLibrary/BUF_X1] - puts "make_instance new_buf1 done" -} +make_instance new_buf1 [get_lib_cells NangateOpenCellLibrary/BUF_X1] +puts "make_instance new_buf1 done" puts "--- Network edit: make_net ---" -catch { - make_net new_net1 - puts "make_net new_net1 done" -} +make_net new_net1 +puts "make_net new_net1 done" puts "--- Network edit: connect_pin ---" catch { @@ -68,23 +64,17 @@ catch { } puts "--- Network edit: delete_net ---" -catch { - delete_net [get_nets new_net1] - puts "delete_net done" -} +delete_net [get_nets new_net1] +puts "delete_net done" puts "--- Network edit: delete_instance ---" -catch { - delete_instance [get_cells new_buf1] - puts "delete_instance done" -} +delete_instance [get_cells new_buf1] +puts "delete_instance done" puts "--- Network edit: replace_cell ---" -catch { - replace_cell [get_cells buf1] [get_lib_cells NangateOpenCellLibrary/BUF_X2] - report_checks -path_delay max - puts "replace_cell done" -} +replace_cell [get_cells buf1] [get_lib_cells NangateOpenCellLibrary/BUF_X2] +report_checks -path_delay max +puts "replace_cell done" puts "--- report_checks after edits ---" report_checks -path_delay max diff --git a/spice/test/cpp/TestSpice.cc b/spice/test/cpp/TestSpice.cc index 8fa8b011..4dc0a3ff 100644 --- a/spice/test/cpp/TestSpice.cc +++ b/spice/test/cpp/TestSpice.cc @@ -3,8 +3,22 @@ #include #include +#include #include "MinMax.hh" #include "Transition.hh" +#include "Sta.hh" +#include "Network.hh" +#include "ReportTcl.hh" +#include "Corner.hh" +#include "Liberty.hh" +#include "Sdc.hh" +#include "Graph.hh" +#include "PathEnd.hh" +#include "PathExpanded.hh" +#include "PathAnalysisPt.hh" +#include "DcalcAnalysisPt.hh" +#include "Search.hh" +#include "CircuitSim.hh" #include "spice/Xyce.hh" #include "spice/WriteSpice.hh" @@ -1367,4 +1381,477 @@ TEST_F(XyceCsvTest, ReadCsv50Signals) { EXPECT_EQ(waveforms.size(), 50u); } +//////////////////////////////////////////////////////////////// +// SpiceDesignTest: tests that load a design and exercise +// higher-level SPICE writing functionality +//////////////////////////////////////////////////////////////// + +class SpiceDesignTest : public ::testing::Test { +protected: + void SetUp() override { + interp_ = Tcl_CreateInterp(); + initSta(); + sta_ = new Sta; + Sta::setSta(sta_); + sta_->makeComponents(); + ReportTcl *report = dynamic_cast(sta_->report()); + if (report) + report->setTclInterp(interp_); + + Corner *corner = sta_->cmdCorner(); + const MinMaxAll *min_max = MinMaxAll::all(); + LibertyLibrary *lib = sta_->readLiberty( + "test/nangate45/Nangate45_typ.lib", corner, min_max, false); + ASSERT_NE(lib, nullptr); + lib_ = lib; + + bool ok = sta_->readVerilog("search/test/search_test1.v"); + ASSERT_TRUE(ok); + ok = sta_->linkDesign("search_test1", true); + ASSERT_TRUE(ok); + + // Create clock and constraints + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + Pin *clk_pin = network->findPin(top, "clk"); + ASSERT_NE(clk_pin, nullptr); + PinSet *clk_pins = new PinSet(network); + clk_pins->insert(clk_pin); + FloatSeq *waveform = new FloatSeq; + waveform->push_back(0.0f); + waveform->push_back(5.0f); + sta_->makeClock("clk", clk_pins, false, 10.0f, waveform, nullptr); + + Pin *in1 = network->findPin(top, "in1"); + Pin *in2 = network->findPin(top, "in2"); + Pin *out1 = network->findPin(top, "out1"); + Clock *clk = sta_->sdc()->findClock("clk"); + sta_->setInputDelay(in1, RiseFallBoth::riseFall(), clk, RiseFall::rise(), + nullptr, false, false, MinMaxAll::all(), false, 0.5f); + sta_->setInputDelay(in2, RiseFallBoth::riseFall(), clk, RiseFall::rise(), + nullptr, false, false, MinMaxAll::all(), false, 0.5f); + sta_->setOutputDelay(out1, RiseFallBoth::riseFall(), clk, RiseFall::rise(), + nullptr, false, false, MinMaxAll::all(), false, 0.5f); + sta_->updateTiming(true); + design_loaded_ = true; + } + + void TearDown() override { + deleteAllMemory(); + sta_ = nullptr; + if (interp_) + Tcl_DeleteInterp(interp_); + interp_ = nullptr; + } + + // Helper: find a vertex for a pin by hierarchical path name + Vertex *findVertex(const char *path_name) { + Network *network = sta_->cmdNetwork(); + Pin *pin = network->findPin(path_name); + if (pin == nullptr) + return nullptr; + Graph *graph = sta_->graph(); + if (graph == nullptr) + return nullptr; + return graph->pinDrvrVertex(pin); + } + + Pin *findPin(const char *path_name) { + Network *network = sta_->cmdNetwork(); + return network->findPin(path_name); + } + + Sta *sta_; + Tcl_Interp *interp_; + LibertyLibrary *lib_; + bool design_loaded_ = false; +}; + +// Verify that the design loaded and basic network is accessible +TEST_F(SpiceDesignTest, DesignLoaded) { + ASSERT_TRUE(design_loaded_); + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + ASSERT_NE(top, nullptr); +} + +// Verify all leaf instances are accessible for SPICE netlisting +TEST_F(SpiceDesignTest, NetworkLeafInstances) { + Network *network = sta_->cmdNetwork(); + InstanceSeq leaves = network->leafInstances(); + // search_test1.v has: and1 (AND2_X1), buf1 (BUF_X1), reg1 (DFF_X1), + // buf2 (BUF_X1) + EXPECT_EQ(leaves.size(), 4u); +} + +// Verify each instance can be found by name for SPICE subcircuit generation +TEST_F(SpiceDesignTest, NetworkInstancesByName) { + Network *network = sta_->cmdNetwork(); + Instance *and1 = network->findInstance("and1"); + Instance *buf1 = network->findInstance("buf1"); + Instance *reg1 = network->findInstance("reg1"); + Instance *buf2 = network->findInstance("buf2"); + EXPECT_NE(and1, nullptr); + EXPECT_NE(buf1, nullptr); + EXPECT_NE(reg1, nullptr); + EXPECT_NE(buf2, nullptr); +} + +// Verify liberty cell information is accessible for SPICE model generation +TEST_F(SpiceDesignTest, LibertyCellAccess) { + Network *network = sta_->cmdNetwork(); + Instance *and1 = network->findInstance("and1"); + ASSERT_NE(and1, nullptr); + LibertyCell *cell = network->libertyCell(and1); + ASSERT_NE(cell, nullptr); + EXPECT_STREQ(cell->name(), "AND2_X1"); +} + +// Verify liberty cell ports (needed for SPICE subcircuit port mapping) +TEST_F(SpiceDesignTest, LibertyCellPortInfo) { + LibertyCell *and2_cell = lib_->findLibertyCell("AND2_X1"); + ASSERT_NE(and2_cell, nullptr); + + LibertyPort *a1 = and2_cell->findLibertyPort("A1"); + LibertyPort *a2 = and2_cell->findLibertyPort("A2"); + LibertyPort *zn = and2_cell->findLibertyPort("ZN"); + EXPECT_NE(a1, nullptr); + EXPECT_NE(a2, nullptr); + EXPECT_NE(zn, nullptr); +} + +// Verify buffer cell identification (used in SPICE path analysis) +TEST_F(SpiceDesignTest, LibertyCellIsBuffer) { + LibertyCell *buf_cell = lib_->findLibertyCell("BUF_X1"); + ASSERT_NE(buf_cell, nullptr); + EXPECT_TRUE(buf_cell->isBuffer()); + + LibertyCell *and2_cell = lib_->findLibertyCell("AND2_X1"); + ASSERT_NE(and2_cell, nullptr); + EXPECT_FALSE(and2_cell->isBuffer()); +} + +// Verify inverter cell identification (used in SPICE logic value computation) +TEST_F(SpiceDesignTest, LibertyCellIsInverter) { + LibertyCell *inv_cell = lib_->findLibertyCell("INV_X1"); + ASSERT_NE(inv_cell, nullptr); + EXPECT_TRUE(inv_cell->isInverter()); + + LibertyCell *buf_cell = lib_->findLibertyCell("BUF_X1"); + ASSERT_NE(buf_cell, nullptr); + EXPECT_FALSE(buf_cell->isInverter()); +} + +// Verify timing arcs exist for cells (needed for SPICE delay checking) +TEST_F(SpiceDesignTest, LibertyCellTimingArcs) { + LibertyCell *and2_cell = lib_->findLibertyCell("AND2_X1"); + ASSERT_NE(and2_cell, nullptr); + EXPECT_GT(and2_cell->timingArcSets().size(), 0u); +} + +// Verify pin connectivity for SPICE net writing +TEST_F(SpiceDesignTest, PinConnectivity) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + + // The internal net n1 connects and1:ZN to buf1:A + Pin *and1_zn = network->findPin("and1/ZN"); + Pin *buf1_a = network->findPin("buf1/A"); + ASSERT_NE(and1_zn, nullptr); + ASSERT_NE(buf1_a, nullptr); + + // Both pins should be on the same net + Net *net_and1_zn = network->net(and1_zn); + Net *net_buf1_a = network->net(buf1_a); + ASSERT_NE(net_and1_zn, nullptr); + ASSERT_NE(net_buf1_a, nullptr); + EXPECT_EQ(net_and1_zn, net_buf1_a); +} + +// Verify driver/load pin classification (used in SPICE netlisting) +TEST_F(SpiceDesignTest, PinDriverLoad) { + Network *network = sta_->cmdNetwork(); + + Pin *and1_zn = network->findPin("and1/ZN"); + Pin *buf1_a = network->findPin("buf1/A"); + ASSERT_NE(and1_zn, nullptr); + ASSERT_NE(buf1_a, nullptr); + + // ZN is an output (driver), A is an input (load) + EXPECT_TRUE(network->isDriver(and1_zn)); + EXPECT_TRUE(network->isLoad(buf1_a)); +} + +// Verify graph vertex access (needed for SPICE path traversal) +TEST_F(SpiceDesignTest, GraphVertexAccess) { + Graph *graph = sta_->graph(); + ASSERT_NE(graph, nullptr); + + Vertex *v = findVertex("buf1/Z"); + EXPECT_NE(v, nullptr); + + Vertex *v2 = findVertex("and1/ZN"); + EXPECT_NE(v2, nullptr); +} + +// Verify timing paths exist after analysis (prerequisite for writePathSpice) +TEST_F(SpiceDesignTest, TimingPathExists) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, // from + nullptr, // thrus + nullptr, // to + false, // unconstrained + sta_->cmdCorner(), + MinMaxAll::max(), + 10, // group_path_count + 1, // endpoint_path_count + false, // unique_pins + false, // unique_edges + -INF, // slack_min + INF, // slack_max + false, // sort_by_slack + nullptr, // group_names + true, // setup + false, // hold + false, // recovery + false, // removal + false, // clk_gating_setup + false // clk_gating_hold + ); + // The design has constrained paths (in1/in2 -> reg1 -> out1) + EXPECT_GT(path_ends.size(), 0u); +} + +// Verify path end has a valid path object for SPICE writing +TEST_F(SpiceDesignTest, PathEndHasPath) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, nullptr, nullptr, false, + sta_->cmdCorner(), MinMaxAll::max(), + 10, 1, false, false, -INF, INF, false, nullptr, + true, false, false, false, false, false + ); + ASSERT_GT(path_ends.size(), 0u); + PathEnd *path_end = path_ends[0]; + ASSERT_NE(path_end, nullptr); + Path *path = path_end->path(); + ASSERT_NE(path, nullptr); +} + +// Verify worst slack computation (used to select paths for SPICE simulation) +TEST_F(SpiceDesignTest, WorstSlackComputation) { + Slack worst_slack; + Vertex *worst_vertex; + sta_->worstSlack(MinMax::max(), worst_slack, worst_vertex); + // The design should have a finite slack (not INF/-INF) + EXPECT_NE(worst_vertex, nullptr); +} + +// Verify DcalcAnalysisPt access (needed for WriteSpice constructor) +TEST_F(SpiceDesignTest, DcalcAnalysisPtAccess) { + Corner *corner = sta_->cmdCorner(); + ASSERT_NE(corner, nullptr); + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max()); + ASSERT_NE(dcalc_ap, nullptr); +} + +// Verify SPICE file can be written for a timing path +TEST_F(SpiceDesignTest, WriteSpicePathFile) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, nullptr, nullptr, false, + sta_->cmdCorner(), MinMaxAll::max(), + 10, 1, false, false, -INF, INF, false, nullptr, + true, false, false, false, false, false + ); + ASSERT_GT(path_ends.size(), 0u); + Path *path = path_ends[0]->path(); + ASSERT_NE(path, nullptr); + + // Create temp files for SPICE output + char spice_tmpl[] = "/tmp/sta_spice_path_XXXXXX"; + int fd = mkstemp(spice_tmpl); + ASSERT_NE(fd, -1); + close(fd); + + // writePathSpice requires subckt/model files to exist, but we can test + // that the function does not crash with empty stubs + char subckt_tmpl[] = "/tmp/sta_spice_subckt_XXXXXX"; + fd = mkstemp(subckt_tmpl); + ASSERT_NE(fd, -1); + close(fd); + + // We cannot provide real model/subckt files for this unit test, so we + // verify the path is valid and the API is callable. The actual file write + // would fail without proper SPICE models, so we just verify the path + // and analysis point are properly formed. + Corner *corner = sta_->cmdCorner(); + const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(MinMax::max()); + EXPECT_NE(dcalc_ap, nullptr); + + // Clean up temp files + std::remove(spice_tmpl); + std::remove(subckt_tmpl); +} + +// Verify multiple timing paths are found (SPICE multi-path analysis) +TEST_F(SpiceDesignTest, MultipleTimingPaths) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, nullptr, nullptr, false, + sta_->cmdCorner(), MinMaxAll::max(), + 10, 10, false, false, -INF, INF, false, nullptr, + true, false, false, false, false, false + ); + // The design has multiple paths through and1/buf1/reg1/buf2 + EXPECT_GE(path_ends.size(), 1u); +} + +// Verify liberty library cell lookup (used in writeSubckts) +TEST_F(SpiceDesignTest, LibraryLookupForSpice) { + // The library should contain the cells used in our design + EXPECT_NE(lib_->findLibertyCell("AND2_X1"), nullptr); + EXPECT_NE(lib_->findLibertyCell("BUF_X1"), nullptr); + EXPECT_NE(lib_->findLibertyCell("DFF_X1"), nullptr); +} + +// Verify cell name is accessible from instance (for SPICE subcircuit naming) +TEST_F(SpiceDesignTest, InstanceCellName) { + Network *network = sta_->cmdNetwork(); + Instance *and1 = network->findInstance("and1"); + ASSERT_NE(and1, nullptr); + const char *cell_name = network->cellName(and1); + ASSERT_NE(cell_name, nullptr); + EXPECT_STREQ(cell_name, "AND2_X1"); + + Instance *reg1 = network->findInstance("reg1"); + ASSERT_NE(reg1, nullptr); + cell_name = network->cellName(reg1); + ASSERT_NE(cell_name, nullptr); + EXPECT_STREQ(cell_name, "DFF_X1"); +} + +// Verify streamPrint with SPICE subcircuit instance format for design cells +TEST_F(SpiceDesignTest, StreamPrintSubcktInst) { + char tmpl[] = "/tmp/sta_spice_subckt_inst_XXXXXX"; + int fd = mkstemp(tmpl); + ASSERT_NE(fd, -1); + close(fd); + + Network *network = sta_->cmdNetwork(); + Instance *and1 = network->findInstance("and1"); + ASSERT_NE(and1, nullptr); + const char *inst_name = network->name(and1); + const char *cell_name = network->cellName(and1); + + std::ofstream out(tmpl); + ASSERT_TRUE(out.is_open()); + streamPrint(out, "x%s VDD VSS %s\n", inst_name, cell_name); + out.close(); + + std::ifstream in(tmpl); + std::string line; + std::getline(in, line); + EXPECT_NE(line.find("xand1"), std::string::npos); + EXPECT_NE(line.find("AND2_X1"), std::string::npos); + std::remove(tmpl); +} + +// Verify net names for SPICE node naming +TEST_F(SpiceDesignTest, NetNamesForSpice) { + Network *network = sta_->cmdNetwork(); + Pin *and1_zn = network->findPin("and1/ZN"); + ASSERT_NE(and1_zn, nullptr); + Net *net = network->net(and1_zn); + ASSERT_NE(net, nullptr); + const char *net_name = network->name(net); + EXPECT_NE(net_name, nullptr); + // The net name should be "n1" (from the Verilog: wire n1) + EXPECT_STREQ(net_name, "n1"); +} + +// Verify hold timing paths (for SPICE min-delay analysis) +TEST_F(SpiceDesignTest, HoldTimingPaths) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, nullptr, nullptr, false, + sta_->cmdCorner(), MinMaxAll::min(), + 10, 1, false, false, -INF, INF, false, nullptr, + false, true, false, false, false, false + ); + // Hold paths should exist for the constrained design + EXPECT_GE(path_ends.size(), 0u); +} + +// Verify clock can be found for SPICE waveform generation +TEST_F(SpiceDesignTest, ClockAccessForSpice) { + Clock *clk = sta_->sdc()->findClock("clk"); + ASSERT_NE(clk, nullptr); + EXPECT_FLOAT_EQ(clk->period(), 10.0f); +} + +// Verify vertex arrival times are computed (used in SPICE timing correlation) +TEST_F(SpiceDesignTest, VertexArrivalForSpice) { + Vertex *v = findVertex("buf1/Z"); + ASSERT_NE(v, nullptr); + Arrival arr = sta_->vertexArrival(v, MinMax::max()); + // Arrival should be finite (not INF) + (void)arr; +} + +// Verify PathExpanded works on timing paths (used in SPICE path writing) +TEST_F(SpiceDesignTest, PathExpandedAccess) { + PathEndSeq path_ends = sta_->findPathEnds( + nullptr, nullptr, nullptr, false, + sta_->cmdCorner(), MinMaxAll::max(), + 10, 1, false, false, -INF, INF, false, nullptr, + true, false, false, false, false, false + ); + ASSERT_GT(path_ends.size(), 0u); + Path *path = path_ends[0]->path(); + ASSERT_NE(path, nullptr); + + PathExpanded expanded(path, sta_); + // The expanded path should have multiple elements + EXPECT_GT(expanded.size(), 0u); +} + +// Verify all top-level ports are accessible (for SPICE port mapping) +TEST_F(SpiceDesignTest, TopLevelPorts) { + Network *network = sta_->cmdNetwork(); + Instance *top = network->topInstance(); + ASSERT_NE(top, nullptr); + + // search_test1.v: input clk, in1, in2; output out1 + Pin *clk = network->findPin(top, "clk"); + Pin *in1 = network->findPin(top, "in1"); + Pin *in2 = network->findPin(top, "in2"); + Pin *out1 = network->findPin(top, "out1"); + EXPECT_NE(clk, nullptr); + EXPECT_NE(in1, nullptr); + EXPECT_NE(in2, nullptr); + EXPECT_NE(out1, nullptr); +} + +// Verify register cell identification (used in SPICE sequential port values) +TEST_F(SpiceDesignTest, RegisterCellForSpice) { + LibertyCell *dff_cell = lib_->findLibertyCell("DFF_X1"); + ASSERT_NE(dff_cell, nullptr); + + // DFF should have timing arcs for setup/hold checks + EXPECT_GT(dff_cell->timingArcSets().size(), 0u); + + // Verify DFF ports needed for SPICE + EXPECT_NE(dff_cell->findLibertyPort("D"), nullptr); + EXPECT_NE(dff_cell->findLibertyPort("CK"), nullptr); + EXPECT_NE(dff_cell->findLibertyPort("Q"), nullptr); +} + +// Verify CircuitSim enum values used in WriteSpice +TEST_F(SpiceDesignTest, CircuitSimEnum) { + // These enum values are used by writePathSpice + CircuitSim hspice = CircuitSim::hspice; + CircuitSim ngspice = CircuitSim::ngspice; + CircuitSim xyce = CircuitSim::xyce; + EXPECT_NE(static_cast(hspice), static_cast(ngspice)); + EXPECT_NE(static_cast(ngspice), static_cast(xyce)); + EXPECT_NE(static_cast(hspice), static_cast(xyce)); +} + } // namespace sta diff --git a/verilog/test/verilog_gcd_writer.tcl b/verilog/test/verilog_gcd_writer.tcl index ae5dd576..71ada642 100644 --- a/verilog/test/verilog_gcd_writer.tcl +++ b/verilog/test/verilog_gcd_writer.tcl @@ -113,7 +113,7 @@ if { $sz7 >= $sz6 } { #--------------------------------------------------------------- puts "--- Test 5: -sort option ---" set out8 [make_result_file verilog_gcd_sort.v] -catch {write_verilog -sort $out8} msg_sort +set msg_sort [write_verilog -sort $out8] puts "write_verilog -sort: $msg_sort" if { [file exists $out8] } { set sz8 [file size $out8] diff --git a/verilog/test/verilog_write_options.tcl b/verilog/test/verilog_write_options.tcl index ea0add99..fc43ba81 100644 --- a/verilog/test/verilog_write_options.tcl +++ b/verilog/test/verilog_write_options.tcl @@ -32,7 +32,7 @@ puts "basic size: $sz1, remove_cells size: $sz3" puts "--- write_verilog -sort (deprecated, should warn) ---" set out4 [make_result_file verilog_write_options_out4.v] -catch {write_verilog -sort $out4} msg_sort +set msg_sort [write_verilog -sort $out4] puts "write_verilog -sort: $msg_sort" puts "--- read_verilog / write_verilog roundtrip ---" # Read back the written verilog to exercise reader code paths