test: improve test stability and assertions

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
This commit is contained in:
Jaehyun Kim 2026-02-22 20:34:07 +09:00
parent 76b12eb2d2
commit b55fcabee4
11 changed files with 229 additions and 64 deletions

View File

@ -6,6 +6,7 @@ sta_module_tests("liberty"
cell_classify_pgpin
cell_deep
clkgate_lvlshift
ecsm
equiv_cells
equiv_cross_lib
equiv_deep

View File

@ -1578,6 +1578,12 @@ TEST(TimingArcAttrsTest, DestructorCleanup) {
attrs->setSdfCondEnd("end");
attrs->setModeName("mode1");
attrs->setModeValue("val1");
EXPECT_EQ(attrs->cond(), cond);
EXPECT_NE(attrs->sdfCond(), nullptr);
EXPECT_NE(attrs->sdfCondStart(), nullptr);
EXPECT_NE(attrs->sdfCondEnd(), nullptr);
EXPECT_STREQ(attrs->modeName(), "mode1");
EXPECT_STREQ(attrs->modeValue(), "val1");
// Destructor should clean up cond, sdf strings, mode strings
delete attrs;
// If we get here without crash, cleanup succeeded

View File

@ -0,0 +1,3 @@
ecsm cell count: 2
ecsm cell: ECSM1
ecsm cell: ECSM2

View File

@ -0,0 +1,78 @@
source ../../test/helpers.tcl
set lib_file [make_result_file liberty_ecsm_generated.lib]
set f [open $lib_file w]
puts $f {
library(test_ecsm_lib) {
delay_model : table_lookup ;
time_unit : "1ns" ;
voltage_unit : "1V" ;
current_unit : "1mA" ;
capacitive_load_unit(1, ff) ;
input_threshold_pct_rise : 50 ;
output_threshold_pct_rise : 50 ;
slew_lower_threshold_pct_rise : 20 ;
slew_upper_threshold_pct_rise : 80 ;
input_threshold_pct_fall : 50 ;
output_threshold_pct_fall : 50 ;
slew_lower_threshold_pct_fall : 20 ;
slew_upper_threshold_pct_fall : 80 ;
lu_table_template(delay_template_2x2) {
variable_1 : input_net_transition ;
variable_2 : total_output_net_capacitance ;
index_1("0.01, 0.1") ;
index_2("0.001, 0.01") ;
}
cell(ECSM1) {
area : 2.0 ;
pin(A) { direction : input ; capacitance : 0.01 ; }
pin(Z) {
direction : output ;
function : "A" ;
timing() {
related_pin : "A" ;
timing_sense : positive_unate ;
cell_rise(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
cell_fall(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
rise_transition(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
fall_transition(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
ecsm_waveform() {}
}
}
}
cell(ECSM2) {
area : 2.0 ;
pin(A) { direction : input ; capacitance : 0.01 ; }
pin(Z) {
direction : output ;
function : "A" ;
timing() {
related_pin : "A" ;
timing_sense : positive_unate ;
cell_rise(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
cell_fall(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
rise_transition(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
fall_transition(delay_template_2x2) { values("0.01, 0.02", "0.03, 0.04") ; }
ecsm_waveform_set() {}
ecsm_capacitance() {}
}
}
}
}
}
close $f
read_liberty $lib_file
set cell_names {}
foreach cell [get_lib_cells test_ecsm_lib/*] {
lappend cell_names [get_name $cell]
}
set cell_names [lsort $cell_names]
puts "ecsm cell count: [llength $cell_names]"
foreach cell_name $cell_names {
puts "ecsm cell: $cell_name"
}

View File

@ -45,6 +45,21 @@ readTextFile(const char *filename)
std::istreambuf_iterator<char>());
}
static size_t
countSubstring(const std::string &text,
const std::string &needle)
{
if (needle.empty())
return 0;
size_t count = 0;
size_t pos = 0;
while ((pos = text.find(needle, pos)) != std::string::npos) {
++count;
pos += needle.size();
}
return count;
}
// RiseFall tests
class RiseFallTest : public ::testing::Test {};
@ -981,8 +996,16 @@ class DeratingFactorsGlobalTest : public ::testing::Test {};
TEST_F(DeratingFactorsGlobalTest, DefaultConstruction) {
DeratingFactorsGlobal dfg;
// Should be constructible and clearable
float factor = 0.0f;
bool exists = true;
dfg.factor(TimingDerateType::cell_delay, PathClkOrData::data,
RiseFall::rise(), MinMax::max(), factor, exists);
EXPECT_FALSE(exists);
dfg.clear();
exists = true;
dfg.factor(TimingDerateType::cell_delay, PathClkOrData::data,
RiseFall::rise(), MinMax::max(), factor, exists);
EXPECT_FALSE(exists);
}
TEST_F(DeratingFactorsGlobalTest, SetFactorCellDelay) {
@ -1685,8 +1708,16 @@ TEST_F(SdcInitTest, ClockSlew) {
Sdc *sdc = sta_->sdc();
Clock *clk = sdc->findClock("slew_clk");
ASSERT_NE(clk, nullptr);
sta_->setClockSlew(clk, RiseFallBoth::riseFall(), MinMaxAll::all(), 0.5);
float slew = 0.0f;
bool exists = false;
clk->slew(RiseFall::rise(), MinMax::max(), slew, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(slew, 0.5f);
sta_->removeClockSlew(clk);
clk->slew(RiseFall::rise(), MinMax::max(), slew, exists);
EXPECT_FALSE(exists);
}
// Clock latency with clock
@ -1698,9 +1729,17 @@ TEST_F(SdcInitTest, ClockLatencyOnClock) {
Sdc *sdc = sta_->sdc();
Clock *clk = sdc->findClock("lat_clk");
ASSERT_NE(clk, nullptr);
sta_->setClockLatency(clk, nullptr, RiseFallBoth::riseFall(),
MinMaxAll::all(), 1.0);
float latency = 0.0f;
bool exists = false;
sdc->clockLatency(clk, RiseFall::rise(), MinMax::max(), latency, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(latency, 1.0f);
sta_->removeClockLatency(clk, nullptr);
sdc->clockLatency(clk, RiseFall::rise(), MinMax::max(), latency, exists);
EXPECT_FALSE(exists);
}
// Clock insertion delay
@ -1712,9 +1751,19 @@ TEST_F(SdcInitTest, ClockInsertionOnClock) {
Sdc *sdc = sta_->sdc();
Clock *clk = sdc->findClock("ins_clk");
ASSERT_NE(clk, nullptr);
sta_->setClockInsertion(clk, nullptr, RiseFallBoth::riseFall(),
MinMaxAll::all(), EarlyLateAll::all(), 0.5);
float insertion = 0.0f;
bool exists = false;
sdc->clockInsertion(clk, nullptr, RiseFall::rise(), MinMax::max(),
EarlyLate::early(), insertion, exists);
EXPECT_TRUE(exists);
EXPECT_FLOAT_EQ(insertion, 0.5f);
sta_->removeClockInsertion(clk, nullptr);
sdc->clockInsertion(clk, nullptr, RiseFall::rise(), MinMax::max(),
EarlyLate::early(), insertion, exists);
EXPECT_FALSE(exists);
}
// Clock uncertainty
@ -10207,34 +10256,48 @@ TEST_F(SdcDesignTest, DisabledInstancePortsDisable) {
Network *network = sta_->cmdNetwork();
Instance *top = network->topInstance();
InstanceChildIterator *iter = network->childIterator(top);
if (iter->hasNext()) {
Instance *inst = iter->next();
LibertyCell *lib_cell = network->libertyCell(inst);
if (lib_cell) {
LibertyPort *in_port = nullptr;
LibertyPort *out_port = nullptr;
LibertyCellPortIterator port_iter(lib_cell);
while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next();
if (port->direction()->isInput() && !in_port)
in_port = port;
else if (port->direction()->isOutput() && !out_port)
out_port = port;
}
if (in_port && out_port) {
// Disable on instance with from/to
sta_->disable(inst, in_port, out_port);
// Write SDC to exercise the disabled instance path
const char *filename = "/tmp/test_sdc_r11_disinstports.sdc";
sta_->writeSdc(filename, false, false, 4, false, true);
FILE *f = fopen(filename, "r");
EXPECT_NE(f, nullptr);
if (f) fclose(f);
// Remove the disable
sta_->removeDisable(inst, in_port, out_port);
}
}
ASSERT_TRUE(iter->hasNext());
Instance *inst = iter->next();
ASSERT_NE(inst, nullptr);
LibertyCell *lib_cell = network->libertyCell(inst);
ASSERT_NE(lib_cell, nullptr);
LibertyPort *in_port = nullptr;
LibertyPort *out_port = nullptr;
LibertyCellPortIterator port_iter(lib_cell);
while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next();
if (port->direction()->isInput() && !in_port)
in_port = port;
else if (port->direction()->isOutput() && !out_port)
out_port = port;
}
ASSERT_NE(in_port, nullptr);
ASSERT_NE(out_port, nullptr);
// Compare emitted SDC before/after disabling this specific arc.
const char *filename = "/tmp/test_sdc_r11_disinstports.sdc";
sta_->writeSdc(filename, false, false, 4, false, true);
std::string before = readTextFile(filename);
ASSERT_FALSE(before.empty());
size_t before_disable_cnt = countSubstring(before, "set_disable_timing");
sta_->disable(inst, in_port, out_port);
sta_->writeSdc(filename, false, false, 4, false, true);
std::string after_disable = readTextFile(filename);
ASSERT_FALSE(after_disable.empty());
size_t after_disable_cnt = countSubstring(after_disable, "set_disable_timing");
EXPECT_GT(after_disable_cnt, before_disable_cnt);
EXPECT_NE(after_disable.find("-from"), std::string::npos);
EXPECT_NE(after_disable.find("-to"), std::string::npos);
sta_->removeDisable(inst, in_port, out_port);
sta_->writeSdc(filename, false, false, 4, false, true);
std::string after_remove = readTextFile(filename);
ASSERT_FALSE(after_remove.empty());
size_t after_remove_cnt = countSubstring(after_remove, "set_disable_timing");
EXPECT_EQ(after_remove_cnt, before_disable_cnt);
delete iter;
}

View File

@ -35,6 +35,8 @@
#include "Bfs.hh"
#include "search/WorstSlack.hh"
#include "search/ReportPath.hh"
#include "GraphDelayCalc.hh"
#include "Debug.hh"
#include "PowerClass.hh"
#include "search/CheckCapacitanceLimits.hh"
#include "search/CheckSlewLimits.hh"
@ -2328,9 +2330,7 @@ TEST_F(StaInitTest, MakeExceptionToNull) {
// Path group names
TEST_F(StaInitTest, PathGroupNames) {
StdStringSeq names = sta_->pathGroupNames();
// Default path groups exist even without design
// (may include "**default**" and similar)
(void)names; // Just ensure no crash
EXPECT_FALSE(names.empty());
}
TEST_F(StaInitTest, IsPathGroupName) {
@ -2340,26 +2340,33 @@ TEST_F(StaInitTest, IsPathGroupName) {
// Debug level
TEST_F(StaInitTest, SetDebugLevel) {
sta_->setDebugLevel("search", 0);
EXPECT_EQ(sta_->debug()->level("search"), 0);
sta_->setDebugLevel("search", 1);
EXPECT_EQ(sta_->debug()->level("search"), 1);
sta_->setDebugLevel("search", 0);
EXPECT_EQ(sta_->debug()->level("search"), 0);
}
// Incremental delay tolerance
TEST_F(StaInitTest, IncrementalDelayTolerance) {
GraphDelayCalc *gdc = sta_->graphDelayCalc();
ASSERT_NE(gdc, nullptr);
sta_->setIncrementalDelayTolerance(0.0);
EXPECT_FLOAT_EQ(gdc->incrementalDelayTolerance(), 0.0f);
sta_->setIncrementalDelayTolerance(0.01);
EXPECT_FLOAT_EQ(gdc->incrementalDelayTolerance(), 0.01f);
}
// Sigma factor for statistical timing
TEST_F(StaInitTest, SigmaFactor) {
sta_->setSigmaFactor(3.0);
ASSERT_NO_THROW(sta_->setSigmaFactor(3.0));
}
// Properties
TEST_F(StaInitTest, PropertiesAccess) {
Properties &props = sta_->properties();
// Properties object should exist
(void)props;
Properties &props2 = sta_->properties();
EXPECT_EQ(&props, &props2);
}
// TclInterp

View File

@ -1,19 +1,10 @@
--- write_timing_model propagated clock ---
--- read back clktree model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_clktree1.lib line 1, library clktree_lib already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model with latency + uncertainty ---
--- read back clktree2 model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_clktree2.lib line 1, library clktree2_lib already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model latch with min/max ---
--- read back latch model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_clktree_latch.lib line 1, library search_latch already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model multicorner propagated ---
--- read back multicorner propagated model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_clktree_mc.lib line 1, library mc_prop_lib already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model with clock transition ---
--- read back clock transition model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_clk_transition.lib line 1, library ct_lib already exists.

View File

@ -8,6 +8,18 @@
# OutputDelays::timingSense, makeInputOutputTimingArcs
source ../../test/helpers.tcl
proc rename_timing_model_library {lib_file new_lib_name} {
set in [open $lib_file r]
set lib_text [read $in]
close $in
regsub {library[[:space:]]*\([^)]+\)} $lib_text "library ($new_lib_name)" lib_text
set out [open $lib_file w]
puts -nonewline $out $lib_text
close $out
}
############################################################
# Part 1: Propagated clock model with clock tree buffers
############################################################
@ -29,6 +41,7 @@ report_checks -path_delay min > /dev/null
puts "--- write_timing_model propagated clock ---"
set model1 [make_result_file "model_clktree1.lib"]
write_timing_model -library_name clktree_lib -cell_name clktree_cell $model1
rename_timing_model_library $model1 clktree_lib_readback
puts "--- read back clktree model ---"
read_liberty $model1
@ -36,7 +49,6 @@ read_liberty $model1
############################################################
# Part 2: Model with clock latency + uncertainty
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_crpr.v
link_design search_crpr
@ -56,6 +68,7 @@ report_checks -path_delay min > /dev/null
puts "--- write_timing_model with latency + uncertainty ---"
set model2 [make_result_file "model_clktree2.lib"]
write_timing_model -library_name clktree2_lib -cell_name clktree2_cell $model2
rename_timing_model_library $model2 clktree2_lib_readback
puts "--- read back clktree2 model ---"
read_liberty $model2
@ -63,7 +76,6 @@ read_liberty $model2
############################################################
# Part 3: Model from latch design with propagated clock
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_latch.v
link_design search_latch
@ -80,6 +92,7 @@ report_checks -path_delay min > /dev/null
puts "--- write_timing_model latch with min/max ---"
set model3 [make_result_file "model_clktree_latch.lib"]
write_timing_model $model3
rename_timing_model_library $model3 clktree_latch_lib_readback
puts "--- read back latch model ---"
read_liberty $model3
@ -87,7 +100,6 @@ read_liberty $model3
############################################################
# Part 4: Model from multicorner design with propagated clock
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_multicorner_analysis.v
link_design search_multicorner_analysis
@ -106,6 +118,7 @@ report_checks -path_delay min > /dev/null
puts "--- write_timing_model multicorner propagated ---"
set model4 [make_result_file "model_clktree_mc.lib"]
write_timing_model -library_name mc_prop_lib -cell_name mc_prop $model4
rename_timing_model_library $model4 mc_prop_lib_readback
puts "--- read back multicorner propagated model ---"
read_liberty $model4
@ -113,7 +126,6 @@ read_liberty $model4
############################################################
# Part 5: Model with clock transition
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_path_end_types.v
link_design search_path_end_types
@ -132,6 +144,7 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model with clock transition ---"
set model5 [make_result_file "model_clk_transition.lib"]
write_timing_model -library_name ct_lib -cell_name ct_cell $model5
rename_timing_model_library $model5 ct_lib_readback
puts "--- read back clock transition model ---"
read_liberty $model5

View File

@ -1,20 +1,11 @@
--- write_timing_model for search_path_end_types ---
--- read back model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_pet.lib line 1, library model_pet_lib already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model for crpr design ---
--- read back crpr model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_crpr.lib line 1, library model_crpr_lib already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model for latch design ---
--- read back latch model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_latch.lib line 1, library search_latch already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model default ---
--- write_timing_model with corner ---
--- read back and use as block ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_simple.lib line 1, library search_test1 already exists.
Warning: ../../test/nangate45/Nangate45_typ.lib line 37, library NangateOpenCellLibrary already exists.
--- write_timing_model for multicorner analysis ---
--- read back multicorner model ---
Warning: /workspace/sta/OpenSTA/search/test/results/model_multicorner.lib line 1, library mc_lib already exists.

View File

@ -7,6 +7,18 @@
# Sta.cc writeTimingModel
source ../../test/helpers.tcl
proc rename_timing_model_library {lib_file new_lib_name} {
set in [open $lib_file r]
set lib_text [read $in]
close $in
regsub {library[[:space:]]*\([^)]+\)} $lib_text "library ($new_lib_name)" lib_text
set out [open $lib_file w]
puts -nonewline $out $lib_text
close $out
}
############################################################
# Part 1: Model from search_path_end_types (flops with async reset)
############################################################
@ -28,6 +40,7 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model for search_path_end_types ---"
set model1 [make_result_file "model_pet.lib"]
write_timing_model -library_name model_pet_lib -cell_name model_pet $model1
rename_timing_model_library $model1 model_pet_lib_readback
# Read model back
puts "--- read back model ---"
@ -36,7 +49,6 @@ read_liberty $model1
############################################################
# Part 2: Model from search_crpr (clock tree reconvergence)
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_crpr.v
link_design search_crpr
@ -52,6 +64,7 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model for crpr design ---"
set model2 [make_result_file "model_crpr.lib"]
write_timing_model -library_name model_crpr_lib -cell_name model_crpr $model2
rename_timing_model_library $model2 model_crpr_lib_readback
puts "--- read back crpr model ---"
read_liberty $model2
@ -59,7 +72,6 @@ read_liberty $model2
############################################################
# Part 3: Model from search_latch (latch design)
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_latch.v
link_design search_latch
@ -75,6 +87,7 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model for latch design ---"
set model3 [make_result_file "model_latch.lib"]
write_timing_model $model3
rename_timing_model_library $model3 model_latch_readback
puts "--- read back latch model ---"
read_liberty $model3
@ -82,7 +95,6 @@ read_liberty $model3
############################################################
# Part 4: Model from search_test1 (simple flop design)
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_test1.v
link_design search_test1
@ -97,11 +109,13 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model default ---"
set model4 [make_result_file "model_simple.lib"]
write_timing_model $model4
rename_timing_model_library $model4 model_simple_readback
puts "--- write_timing_model with corner ---"
set corner [sta::cmd_corner]
set model5 [make_result_file "model_simple_corner.lib"]
write_timing_model -corner [$corner name] $model5
rename_timing_model_library $model5 model_simple_corner_readback
# Read model back and use it as a block
puts "--- read back and use as block ---"
@ -110,7 +124,6 @@ read_liberty $model4
############################################################
# Part 5: write_timing_model on multicorner design
############################################################
read_liberty ../../test/nangate45/Nangate45_typ.lib
read_verilog search_multicorner_analysis.v
link_design search_multicorner_analysis
@ -127,6 +140,7 @@ report_checks -path_delay max > /dev/null
puts "--- write_timing_model for multicorner analysis ---"
set model6 [make_result_file "model_multicorner.lib"]
write_timing_model -library_name mc_lib -cell_name mc_cell $model6
rename_timing_model_library $model6 model_multicorner_readback
puts "--- read back multicorner model ---"
read_liberty $model6

View File

@ -96,10 +96,8 @@ puts "--- Test 5: -sort option ---"
set out8 [make_result_file verilog_gcd_sort.v]
set msg_sort [write_verilog -sort $out8]
puts "write_verilog -sort: $msg_sort"
if { [file exists $out8] } {
set sz8 [file size $out8]
puts "sort write: $sz8 bytes"
}
set sz8 [file size $out8]
puts "sort write: $sz8 bytes"
#---------------------------------------------------------------
# Test 6: Network modification then write