test: Add comprehensive test infrastructure and test cases across all OpenSTA modules
Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
This commit is contained in:
parent
8e08483e0e
commit
92bb9b8ec9
|
|
@ -12,6 +12,7 @@ Makefile
|
|||
gmon.out
|
||||
|
||||
cmake-build-debug
|
||||
coverage-output
|
||||
build
|
||||
pvt
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ examples/gcd_tb
|
|||
doc/._Sta.docx
|
||||
|
||||
test/results
|
||||
*/test/results
|
||||
# ngspice turd
|
||||
test/b3v3_1check.log
|
||||
|
||||
|
|
|
|||
|
|
@ -646,3 +646,44 @@ add_custom_command(
|
|||
COMMAND ${STA_HOME}/etc/FindMessages.tcl > ${STA_HOME}/doc/messages.txt || true
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
)
|
||||
|
||||
################################################################
|
||||
# Tests
|
||||
################################################################
|
||||
|
||||
option(BUILD_TESTS "Build unit tests" ON)
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
find_package(GTest REQUIRED)
|
||||
include(GoogleTest)
|
||||
|
||||
# Helper: register a list of Tcl tests for a module.
|
||||
# Usage:
|
||||
# sta_module_tests("search" TESTS timing analysis ...)
|
||||
function(sta_module_tests module_name)
|
||||
cmake_parse_arguments(ARG "" "" "TESTS" ${ARGN})
|
||||
foreach(test_name ${ARG_TESTS})
|
||||
add_test(
|
||||
NAME tcl.${module_name}.${test_name}
|
||||
COMMAND bash ${STA_HOME}/test/regression.sh $<TARGET_FILE:sta> ${module_name}_${test_name}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
set_tests_properties(tcl.${module_name}.${test_name} PROPERTIES LABELS "tcl;module_${module_name}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(test)
|
||||
# Per-module tests
|
||||
add_subdirectory(util/test)
|
||||
add_subdirectory(liberty/test)
|
||||
add_subdirectory(graph/test)
|
||||
add_subdirectory(network/test)
|
||||
add_subdirectory(sdc/test)
|
||||
add_subdirectory(sdf/test)
|
||||
add_subdirectory(dcalc/test)
|
||||
add_subdirectory(search/test)
|
||||
add_subdirectory(parasitics/test)
|
||||
add_subdirectory(power/test)
|
||||
add_subdirectory(verilog/test)
|
||||
add_subdirectory(spice/test)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestFindRoot TestFindRoot.cc)
|
||||
target_link_libraries(TestFindRoot
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestFindRoot PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestFindRoot
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_dcalc"
|
||||
)
|
||||
|
|
@ -0,0 +1,672 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include "dcalc/FindRoot.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class FindRootTest : public ::testing::Test {};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Original 7 tests
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Test finding root of f(x) = x^2 - 4 (root at x=2)
|
||||
TEST_F(FindRootTest, QuadraticPositiveRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
// Test finding root of f(x) = x^2 - 4 (root at x=-2)
|
||||
TEST_F(FindRootTest, QuadraticNegativeRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -3.0, -1.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, -2.0, 1e-8);
|
||||
}
|
||||
|
||||
// Test finding root of f(x) = x - 1 (linear, root at x=1)
|
||||
TEST_F(FindRootTest, LinearRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 1.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.0, 2.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 1.0, 1e-8);
|
||||
}
|
||||
|
||||
// Test finding root of f(x) = sin(x) near pi
|
||||
TEST_F(FindRootTest, SinRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = sin(x);
|
||||
dy = cos(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 2.5, 3.8, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, M_PI, 1e-6);
|
||||
}
|
||||
|
||||
// Test finding root of f(x) = e^x - 2 (root at x=ln(2))
|
||||
TEST_F(FindRootTest, ExponentialRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = exp(x) - 2.0;
|
||||
dy = exp(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.0, 1.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, log(2.0), 1e-8);
|
||||
}
|
||||
|
||||
// Test with tight tolerance
|
||||
TEST_F(FindRootTest, TightTolerance) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 2.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 2.0, 1e-14, 200, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, sqrt(2.0), 1e-12);
|
||||
}
|
||||
|
||||
// Test the 4-argument version with pre-computed y values
|
||||
TEST_F(FindRootTest, WithPrecomputedY) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 9.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
// x1=2, y1=4-9=-5, x2=4, y2=16-9=7
|
||||
double root = findRoot(func, 2.0, -5.0, 4.0, 7.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 3.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Tolerance edge cases
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Very tight tolerance: 1e-15 (near machine epsilon)
|
||||
TEST_F(FindRootTest, VeryTightTolerance) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 5.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 3.0, 7.0, 1e-15, 500, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 5.0, 1e-13);
|
||||
}
|
||||
|
||||
// Very loose tolerance: 1e-1
|
||||
TEST_F(FindRootTest, LooseTolerance) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 25.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 3.0, 7.0, 1e-1, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
// With 10% relative tolerance, result should still be in the right ballpark
|
||||
EXPECT_NEAR(root, 5.0, 0.6);
|
||||
}
|
||||
|
||||
// Zero tolerance: convergence check becomes abs(dx) <= 0, which is only
|
||||
// satisfied when dx is exactly 0. Likely hits max_iter and fails.
|
||||
TEST_F(FindRootTest, ZeroTolerance) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 3.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 5.0, 0.0, 100, fail);
|
||||
// May or may not converge -- for a linear function Newton converges in 1 step
|
||||
// so dx can be exactly 0. Accept either outcome.
|
||||
if (!fail) {
|
||||
EXPECT_NEAR(root, 3.0, 1e-10);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Iteration limit edge cases
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Only 1 iteration allowed
|
||||
TEST_F(FindRootTest, OneIteration) {
|
||||
ASSERT_NO_THROW(( [&](){
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 3.0, 1e-10, 1, fail);
|
||||
// With only 1 iteration, a quadratic likely won't converge to tight tol
|
||||
// The algorithm may or may not fail depending on initial bisection step
|
||||
// Root should still be a finite number within the bracket
|
||||
EXPECT_GE(root, 1.0);
|
||||
EXPECT_LE(root, 3.0);
|
||||
|
||||
}() ));
|
||||
}
|
||||
|
||||
// Two iterations
|
||||
TEST_F(FindRootTest, TwoIterations) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 7.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 5.0, 9.0, 1e-10, 2, fail);
|
||||
// Linear function: Newton should converge very fast
|
||||
// After the initial midpoint (7.0), Newton step should nail it
|
||||
if (!fail) {
|
||||
EXPECT_NEAR(root, 7.0, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero max iterations: the for-loop body never executes, so fail is set to true
|
||||
TEST_F(FindRootTest, ZeroMaxIterations) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 1.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
findRoot(func, 0.0, 2.0, 1e-10, 0, fail);
|
||||
EXPECT_TRUE(fail);
|
||||
}
|
||||
|
||||
// Large max_iter (should still converge quickly and not hang)
|
||||
TEST_F(FindRootTest, LargeMaxIter) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 16.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 10.0, 1e-12, 10000, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 4.0, 1e-10);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Special function types
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Cubic: f(x) = x^3 - 8 (root at x=2)
|
||||
TEST_F(FindRootTest, CubicRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x * x - 8.0;
|
||||
dy = 3.0 * x * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
// Quartic: f(x) = x^4 - 16 (root at x=2)
|
||||
TEST_F(FindRootTest, QuarticRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x * x * x - 16.0;
|
||||
dy = 4.0 * x * x * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
// Exponential: f(x) = e^x - 10 (root at x=ln(10))
|
||||
TEST_F(FindRootTest, ExponentialRoot2) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = exp(x) - 10.0;
|
||||
dy = exp(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 4.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, log(10.0), 1e-8);
|
||||
}
|
||||
|
||||
// Square root function: f(x) = sqrt(x) - 3, root at x=9
|
||||
// Derivative: 1/(2*sqrt(x))
|
||||
TEST_F(FindRootTest, SqrtFunctionRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = sqrt(x) - 3.0;
|
||||
dy = 0.5 / sqrt(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 20.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 9.0, 1e-6);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Near-zero roots
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = x - 1e-10 (root very close to zero)
|
||||
// Note: convergence check is abs(dx) <= x_tol * abs(root).
|
||||
// When root is near zero, the relative tolerance is very tight.
|
||||
// This may require many iterations or not converge.
|
||||
TEST_F(FindRootTest, NearZeroRootLinear) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 1e-10;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -1.0, 1.0, 1e-6, 200, fail);
|
||||
// Newton on a linear function converges in 1-2 steps regardless of root location
|
||||
if (!fail) {
|
||||
EXPECT_NEAR(root, 1e-10, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
// f(x) = x (root exactly at zero)
|
||||
// Convergence test: abs(dx) <= x_tol * abs(root) = x_tol * 0 = 0
|
||||
// Will likely hit max_iter because relative tolerance at root=0 requires dx=0 exactly
|
||||
TEST_F(FindRootTest, RootExactlyAtZero) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -1.0, 1.0, 1e-10, 200, fail);
|
||||
// Even if fail is true, root should be very close to 0
|
||||
EXPECT_NEAR(root, 0.0, 1e-6);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Negative domain
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Root in deeply negative domain: f(x) = x + 100, root at x=-100
|
||||
TEST_F(FindRootTest, NegativeDomainRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x + 100.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -200.0, 0.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, -100.0, 1e-6);
|
||||
}
|
||||
|
||||
// Both bracket endpoints negative: f(x) = x^2 - 1, root at x=-1
|
||||
TEST_F(FindRootTest, NegativeBracketRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 1.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -2.0, -0.5, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, -1.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Trigonometric functions
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// sin(x) root at x=0 (bracket [-1, 1])
|
||||
TEST_F(FindRootTest, SinRootAtZero) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = sin(x);
|
||||
dy = cos(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -1.0, 1.0, 1e-10, 100, fail);
|
||||
// Root at 0 has the relative-tolerance issue, but Newton converges fast for sin
|
||||
EXPECT_NEAR(root, 0.0, 1e-4);
|
||||
}
|
||||
|
||||
// sin(x) root at x=2*pi (bracket [5.5, 7.0])
|
||||
TEST_F(FindRootTest, SinRootAt2Pi) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = sin(x);
|
||||
dy = cos(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 5.5, 7.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0 * M_PI, 1e-6);
|
||||
}
|
||||
|
||||
// cos(x) root at x=pi/2
|
||||
TEST_F(FindRootTest, CosRootAtPiOver2) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = cos(x);
|
||||
dy = -sin(x);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 2.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, M_PI / 2.0, 1e-6);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Multiple roots nearby
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = (x-1)(x-2) = x^2 - 3x + 2, roots at x=1 and x=2
|
||||
// Bracket [0.5, 1.5] should find x=1
|
||||
TEST_F(FindRootTest, MultipleRootsFindFirst) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = (x - 1.0) * (x - 2.0);
|
||||
dy = 2.0 * x - 3.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.5, 1.5, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 1.0, 1e-8);
|
||||
}
|
||||
|
||||
// Same function, bracket [1.5, 2.5] should find x=2
|
||||
TEST_F(FindRootTest, MultipleRootsFindSecond) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = (x - 1.0) * (x - 2.0);
|
||||
dy = 2.0 * x - 3.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.5, 2.5, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Discontinuous derivative (sharp corner)
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = |x| - 1 with piecewise derivative.
|
||||
// Root at x=1 (bracket [0.5, 2.0] avoids the corner at 0)
|
||||
TEST_F(FindRootTest, AbsValueRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = fabs(x) - 1.0;
|
||||
dy = (x >= 0.0) ? 1.0 : -1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.5, 2.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 1.0, 1e-8);
|
||||
}
|
||||
|
||||
// f(x) = |x| - 1, root at x=-1
|
||||
TEST_F(FindRootTest, AbsValueNegativeRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = fabs(x) - 1.0;
|
||||
dy = (x >= 0.0) ? 1.0 : -1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -2.0, -0.5, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, -1.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Very flat function (slow convergence)
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = (x - 3)^5 has a repeated root at x=3 where the derivative is also
|
||||
// zero. Newton-Raphson divides by dy which becomes 0, producing NaN.
|
||||
// The algorithm is expected to fail on this degenerate case.
|
||||
TEST_F(FindRootTest, FlatFifthOrderRootFails) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
double d = x - 3.0;
|
||||
double d2 = d * d;
|
||||
double d4 = d2 * d2;
|
||||
y = d4 * d; // (x-3)^5
|
||||
dy = 5.0 * d4; // 5*(x-3)^4
|
||||
};
|
||||
bool fail = false;
|
||||
findRoot(func, 2.0, 4.0, 1e-6, 500, fail);
|
||||
// The algorithm is expected to fail because dy -> 0 at the root
|
||||
EXPECT_TRUE(fail);
|
||||
}
|
||||
|
||||
// A function that is very flat near the root but still has nonzero derivative
|
||||
// at the root: f(x) = sinh(x - 3) which is ~0 near x=3 but never has dy=0.
|
||||
// sinh is flat near 0 (sinh(e) ~ e for small e) but derivative cosh(e) >= 1.
|
||||
TEST_F(FindRootTest, FlatSinhRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = sinh(x - 3.0);
|
||||
dy = cosh(x - 3.0);
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 2.0, 4.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 3.0, 1e-6);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Very steep function (fast convergence)
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = 1000*(x - 5), root at x=5. Very steep gradient.
|
||||
TEST_F(FindRootTest, SteepLinearRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = 1000.0 * (x - 5.0);
|
||||
dy = 1000.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 3.0, 7.0, 1e-12, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 5.0, 1e-10);
|
||||
}
|
||||
|
||||
// f(x) = 1e6 * (x - 2), very steep
|
||||
TEST_F(FindRootTest, VerySteepLinearRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = 1e6 * (x - 2.0);
|
||||
dy = 1e6;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 3.0, 1e-14, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-12);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Large bracket
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = x - 42, bracket [-1000, 1000]
|
||||
TEST_F(FindRootTest, LargeBracket) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 42.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -1000.0, 1000.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 42.0, 1e-6);
|
||||
}
|
||||
|
||||
// Quadratic with large bracket: f(x) = x^2 - 100, root at 10
|
||||
TEST_F(FindRootTest, LargeBracketQuadratic) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 100.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.0, 1000.0, 1e-10, 200, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 10.0, 1e-6);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Small bracket
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = x - 1.0, bracket [0.999999, 1.000001] (very tight bracket around root)
|
||||
TEST_F(FindRootTest, SmallBracket) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 1.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.999999, 1.000001, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 1.0, 1e-6);
|
||||
}
|
||||
|
||||
// Quadratic with very small bracket around root=2
|
||||
TEST_F(FindRootTest, SmallBracketQuadratic) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 1.9999, 2.0001, 1e-12, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Both overloads tested together
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Compare 2-arg and 4-arg overloads produce same result
|
||||
TEST_F(FindRootTest, OverloadsProduceSameResult) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x * x - 27.0;
|
||||
dy = 3.0 * x * x;
|
||||
};
|
||||
|
||||
bool fail_2arg = false;
|
||||
double root_2arg = findRoot(func, 2.0, 4.0, 1e-12, 100, fail_2arg);
|
||||
|
||||
// Pre-compute y values for 4-arg version
|
||||
double y1 = 2.0 * 2.0 * 2.0 - 27.0; // 8 - 27 = -19
|
||||
double y2 = 4.0 * 4.0 * 4.0 - 27.0; // 64 - 27 = 37
|
||||
bool fail_4arg = false;
|
||||
double root_4arg = findRoot(func, 2.0, y1, 4.0, y2, 1e-12, 100, fail_4arg);
|
||||
|
||||
EXPECT_FALSE(fail_2arg);
|
||||
EXPECT_FALSE(fail_4arg);
|
||||
EXPECT_NEAR(root_2arg, 3.0, 1e-10);
|
||||
EXPECT_NEAR(root_4arg, 3.0, 1e-10);
|
||||
EXPECT_NEAR(root_2arg, root_4arg, 1e-14);
|
||||
}
|
||||
|
||||
// 4-arg overload: x1 endpoint is exact root (y1 == 0)
|
||||
TEST_F(FindRootTest, FourArgX1IsRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 5.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
// y1 = 5 - 5 = 0
|
||||
double root = findRoot(func, 5.0, 0.0, 8.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_DOUBLE_EQ(root, 5.0);
|
||||
}
|
||||
|
||||
// 4-arg overload: x2 endpoint is exact root (y2 == 0)
|
||||
TEST_F(FindRootTest, FourArgX2IsRoot) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 5.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
// y2 = 5 - 5 = 0
|
||||
double root = findRoot(func, 2.0, -3.0, 5.0, 0.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_DOUBLE_EQ(root, 5.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Same-sign y values (should fail)
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Both endpoints positive: should fail
|
||||
TEST_F(FindRootTest, BothEndpointsPositiveFails) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x + 1.0; // Always positive, no real root
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
findRoot(func, 1.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_TRUE(fail);
|
||||
}
|
||||
|
||||
// Both endpoints negative: should fail
|
||||
TEST_F(FindRootTest, BothEndpointsNegativeFails) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = -x * x - 1.0; // Always negative
|
||||
dy = -2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
findRoot(func, -3.0, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_TRUE(fail);
|
||||
}
|
||||
|
||||
// 4-arg version: same-sign y values
|
||||
TEST_F(FindRootTest, FourArgSameSignFails) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
// Both y values positive
|
||||
findRoot(func, 1.0, 1.0, 2.0, 4.0, 1e-10, 100, fail);
|
||||
EXPECT_TRUE(fail);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Symmetry test
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// f(x) = x^2 - 4: bracket [0, 3] finds +2, bracket [-3, 0] finds -2
|
||||
TEST_F(FindRootTest, SymmetryPositiveBracket) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, 0.5, 3.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 2.0, 1e-8);
|
||||
}
|
||||
|
||||
TEST_F(FindRootTest, SymmetryNegativeBracket) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x * x - 4.0;
|
||||
dy = 2.0 * x;
|
||||
};
|
||||
bool fail = false;
|
||||
double root = findRoot(func, -3.0, -0.5, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, -2.0, 1e-8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Swapped bracket order (x1 > x2)
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// The algorithm should work regardless of bracket order
|
||||
TEST_F(FindRootTest, SwappedBracketOrder) {
|
||||
FindRootFunc func = [](double x, double &y, double &dy) {
|
||||
y = x - 3.0;
|
||||
dy = 1.0;
|
||||
};
|
||||
bool fail = false;
|
||||
// x1=5 > x2=1 (reversed order)
|
||||
double root = findRoot(func, 5.0, 1.0, 1e-10, 100, fail);
|
||||
EXPECT_FALSE(fail);
|
||||
EXPECT_NEAR(root, 3.0, 1e-8);
|
||||
}
|
||||
|
||||
} // namespace sta
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2025, The OpenROAD Authors
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$(dirname $(readlink -f $0))"
|
||||
cd "$DIR/../"
|
||||
|
||||
# default values, can be overwritten by cmdline args
|
||||
buildDir="build"
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
numThreads=$(nproc --all)
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
numThreads=$(sysctl -n hw.ncpu)
|
||||
else
|
||||
cat << EOF
|
||||
WARNING: Unsupported OSTYPE: cannot determine number of host CPUs"
|
||||
Defaulting to 2 threads. Use -threads=N to use N threads"
|
||||
EOF
|
||||
numThreads=2
|
||||
fi
|
||||
cmakeOptions=""
|
||||
cleanBefore=no
|
||||
compiler=gcc
|
||||
|
||||
_help() {
|
||||
cat <<EOF
|
||||
usage: $0 [OPTIONS]
|
||||
|
||||
Build OpenSTA from source.
|
||||
|
||||
OPTIONS:
|
||||
-cmake='-<key>=<value> ...' User defined cmake options
|
||||
Note: use single quote after
|
||||
-cmake= and double quotes if
|
||||
<key> has multiple <values>
|
||||
e.g.: -cmake='-DFLAGS="-a -b"'
|
||||
-compiler=COMPILER_NAME Compiler name: gcc or clang
|
||||
Default: gcc
|
||||
-dir=PATH Path to store build files.
|
||||
Default: ./build
|
||||
-coverage Enable cmake coverage options
|
||||
-clean Remove build dir before compile
|
||||
-threads=NUM_THREADS Number of threads to use during
|
||||
compile. Default: \`nproc\` on linux
|
||||
or \`sysctl -n hw.ncpu\` on macOS
|
||||
-O0 Disable optimizations for accurate
|
||||
coverage measurement
|
||||
-help Shows this message
|
||||
|
||||
EOF
|
||||
exit "${1:-1}"
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|-help)
|
||||
_help 0
|
||||
;;
|
||||
-coverage )
|
||||
cmakeOptions+=" -DCMAKE_BUILD_TYPE=Debug"
|
||||
cmakeOptions+=" -DCMAKE_CXX_FLAGS='--coverage'"
|
||||
cmakeOptions+=" -DCMAKE_EXE_LINKER_FLAGS='--coverage'"
|
||||
;;
|
||||
-O0 )
|
||||
cmakeOptions+=" -DCMAKE_CXX_FLAGS_DEBUG='-g -O0'"
|
||||
;;
|
||||
-cmake=*)
|
||||
cmakeOptions+=" ${1#*=}"
|
||||
;;
|
||||
-clean )
|
||||
cleanBefore=yes
|
||||
;;
|
||||
-compiler=*)
|
||||
compiler="${1#*=}"
|
||||
;;
|
||||
-dir=* )
|
||||
buildDir="${1#*=}"
|
||||
;;
|
||||
-threads=* )
|
||||
numThreads="${1#*=}"
|
||||
;;
|
||||
-compiler | -cmake | -dir | -threads )
|
||||
echo "${1} requires an argument" >&2
|
||||
_help
|
||||
;;
|
||||
*)
|
||||
echo "unknown option: ${1}" >&2
|
||||
_help
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
case "${compiler}" in
|
||||
"gcc" )
|
||||
export CC="$(command -v gcc)"
|
||||
export CXX="$(command -v g++)"
|
||||
;;
|
||||
"clang" )
|
||||
export CC="$(command -v clang)"
|
||||
export CXX="$(command -v clang++)"
|
||||
;;
|
||||
*)
|
||||
echo "Compiler $compiler not supported. Use gcc or clang." >&2
|
||||
_help 1
|
||||
esac
|
||||
|
||||
if [[ -z "${CC}" || -z "${CXX}" ]]; then
|
||||
echo "Compiler $compiler not installed." >&2
|
||||
_help 1
|
||||
fi
|
||||
|
||||
if [[ "${cleanBefore}" == "yes" ]]; then
|
||||
rm -rf "${buildDir}"
|
||||
fi
|
||||
|
||||
mkdir -p "${buildDir}"
|
||||
|
||||
echo "[INFO] Compiler: ${compiler} (${CC})"
|
||||
echo "[INFO] Build dir: ${buildDir}"
|
||||
echo "[INFO] Using ${numThreads} threads."
|
||||
|
||||
eval cmake "${cmakeOptions}" -B "${buildDir}" .
|
||||
eval time cmake --build "${buildDir}" -j "${numThreads}"
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2025, The OpenROAD Authors
|
||||
|
||||
# Generate an lcov/genhtml code coverage report for OpenSTA.
|
||||
# Requires a coverage build: ./etc/Build.sh -coverage
|
||||
#
|
||||
# Usage:
|
||||
# ./etc/CodeCoverage.sh Run all tests, generate report
|
||||
# ./etc/CodeCoverage.sh -tcl-only Run only Tcl tests (skip C++ unit tests)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname $(readlink -f $0))/../"
|
||||
|
||||
buildDir="build"
|
||||
reportDir="coverage-output"
|
||||
tclOnly=no
|
||||
|
||||
_help() {
|
||||
cat <<EOF
|
||||
usage: $0 [OPTIONS]
|
||||
|
||||
Generate an lcov/genhtml code coverage report for OpenSTA.
|
||||
Requires a coverage build first: ./etc/Build.sh -coverage
|
||||
|
||||
OPTIONS:
|
||||
-tcl-only Run only Tcl tests (skip C++ unit tests)
|
||||
-dir=PATH Build directory. Default: ./build
|
||||
-help Shows this message
|
||||
|
||||
OUTPUT:
|
||||
coverage-output/ HTML coverage report
|
||||
coverage-output/index.html Main report page
|
||||
|
||||
EOF
|
||||
exit "${1:-1}"
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-h|-help)
|
||||
_help 0
|
||||
;;
|
||||
-tcl-only)
|
||||
tclOnly=yes
|
||||
;;
|
||||
-dir=*)
|
||||
buildDir="${1#*=}"
|
||||
;;
|
||||
-dir )
|
||||
echo "${1} requires an argument" >&2
|
||||
_help
|
||||
;;
|
||||
*)
|
||||
echo "unknown option: ${1}" >&2
|
||||
_help
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
if [[ ! -d "${buildDir}" ]]; then
|
||||
echo "Build directory '${buildDir}' not found." >&2
|
||||
echo "Run ./etc/Build.sh -coverage first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Common lcov flags to suppress all known warnings:
|
||||
# mismatch - GCC/GoogleTest macro function range mismatches
|
||||
# gcov - unexecuted blocks on non-branch lines (GCC optimizer artifacts)
|
||||
# source - source file newer than .gcno notes file (stale build artifacts)
|
||||
# Double-specification (X,X) suppresses the warning output entirely.
|
||||
LCOV_IGNORE="--ignore-errors mismatch,mismatch,gcov,gcov,source,source,unused,unused,negative,negative"
|
||||
|
||||
# Clear stale coverage data before test execution.
|
||||
# Old .gcda files from previous runs can cause gcov checksum mismatch noise.
|
||||
find "${buildDir}" -name '*.gcda' -delete
|
||||
|
||||
# Step 1: Run tests
|
||||
if [[ "${tclOnly}" == "yes" ]]; then
|
||||
echo "[INFO] Running Tcl tests only..."
|
||||
ctest --test-dir "${buildDir}" -L tcl -j $(nproc) --output-on-failure || true
|
||||
else
|
||||
echo "[INFO] Running all tests..."
|
||||
ctest --test-dir "${buildDir}" -j $(nproc) --output-on-failure || true
|
||||
fi
|
||||
|
||||
# Step 2: Capture coverage
|
||||
echo "[INFO] Capturing coverage data..."
|
||||
lcov --capture \
|
||||
-d "${buildDir}" \
|
||||
-o "${buildDir}/coverage.info" \
|
||||
--quiet \
|
||||
${LCOV_IGNORE}
|
||||
|
||||
# Step 3: Filter system/build/test dirs
|
||||
lcov --remove "${buildDir}/coverage.info" \
|
||||
'/usr/*' \
|
||||
'*/build/*' \
|
||||
'*/test/*' \
|
||||
-o "${buildDir}/filtered.info" \
|
||||
--quiet \
|
||||
${LCOV_IGNORE}
|
||||
|
||||
# Step 4: Generate HTML report
|
||||
GENHTML_IGNORE="--ignore-errors unmapped,unmapped,inconsistent,inconsistent,corrupt,corrupt,negative,negative,empty,empty,format,format,mismatch,mismatch,source,source"
|
||||
|
||||
mkdir -p "${reportDir}"
|
||||
genhtml "${buildDir}/filtered.info" \
|
||||
--output-directory "${reportDir}" \
|
||||
--quiet \
|
||||
${GENHTML_IGNORE} || true
|
||||
|
||||
echo ""
|
||||
echo "=== Coverage report generated ==="
|
||||
echo "Open $(pwd)/${reportDir}/index.html in a browser to view."
|
||||
echo ""
|
||||
lcov --summary "${buildDir}/filtered.info" ${LCOV_IGNORE} 2>&1 || true
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("graph"
|
||||
TESTS
|
||||
make_verify
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestGraph TestGraph.cc)
|
||||
target_link_libraries(TestGraph
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestGraph PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestGraph
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_graph"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
No paths found.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# Read liberty and design, make graph, verify
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog graph_test1.v
|
||||
link_design graph_test1
|
||||
|
||||
# Creating the timing graph implicitly tests graph construction
|
||||
create_clock -name clk -period 10 [get_ports clk]
|
||||
|
||||
# report_checks exercises the graph
|
||||
report_checks -from [get_ports d] -to [get_ports q]
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module graph_test1 (clk, d, q);
|
||||
input clk, d;
|
||||
output q;
|
||||
wire n1;
|
||||
|
||||
DFF_X1 reg1 (.D(d), .CK(clk), .Q(n1));
|
||||
DFF_X1 reg2 (.D(n1), .CK(clk), .Q(q));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
module graph_test2 (clk, d1, d2, en, q1, q2);
|
||||
input clk, d1, d2, en;
|
||||
output q1, q2;
|
||||
wire n1, n2, n3, n4, n5, n6;
|
||||
|
||||
BUF_X1 buf1 (.A(d1), .Z(n1));
|
||||
BUF_X2 buf2 (.A(d2), .Z(n2));
|
||||
INV_X1 inv1 (.A(n1), .ZN(n3));
|
||||
AND2_X1 and1 (.A1(n3), .A2(en), .ZN(n4));
|
||||
OR2_X1 or1 (.A1(n2), .A2(n4), .ZN(n5));
|
||||
BUF_X1 buf3 (.A(n5), .Z(n6));
|
||||
DFF_X1 reg1 (.D(n4), .CK(clk), .Q(q1));
|
||||
DFF_X1 reg2 (.D(n6), .CK(clk), .Q(q2));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Larger design for graph operations testing: more cell types, fan-in/fan-out,
|
||||
// multiple clock domains, and reconvergent paths.
|
||||
module graph_test3 (clk1, clk2, rst, d1, d2, d3, d4, q1, q2, q3);
|
||||
input clk1, clk2, rst, d1, d2, d3, d4;
|
||||
output q1, q2, q3;
|
||||
wire n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12;
|
||||
|
||||
// Input stage: buffers and inverters
|
||||
BUF_X1 buf1 (.A(d1), .Z(n1));
|
||||
BUF_X2 buf2 (.A(d2), .Z(n2));
|
||||
INV_X1 inv1 (.A(d3), .ZN(n3));
|
||||
INV_X2 inv2 (.A(d4), .ZN(n4));
|
||||
|
||||
// Middle stage: logic gates
|
||||
AND2_X1 and1 (.A1(n1), .A2(n2), .ZN(n5));
|
||||
OR2_X1 or1 (.A1(n3), .A2(n4), .ZN(n6));
|
||||
NAND2_X1 nand1 (.A1(n5), .A2(n6), .ZN(n7));
|
||||
NOR2_X1 nor1 (.A1(n1), .A2(n3), .ZN(n8));
|
||||
|
||||
// Reconvergent fan-out
|
||||
AND2_X2 and2 (.A1(n7), .A2(n8), .ZN(n9));
|
||||
OR2_X2 or2 (.A1(n7), .A2(n8), .ZN(n10));
|
||||
|
||||
// Clock domain 1 registers
|
||||
DFF_X1 reg1 (.D(n9), .CK(clk1), .Q(n11));
|
||||
DFF_X1 reg2 (.D(n10), .CK(clk1), .Q(q1));
|
||||
|
||||
// Clock domain 2 register (cross-domain)
|
||||
DFF_X1 reg3 (.D(n11), .CK(clk2), .Q(n12));
|
||||
BUF_X1 buf3 (.A(n12), .Z(q2));
|
||||
|
||||
// Combinational output
|
||||
BUF_X4 buf4 (.A(n7), .Z(q3));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("liberty"
|
||||
TESTS
|
||||
read_nangate
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestLibertyClasses TestLibertyClasses.cc)
|
||||
target_link_libraries(TestLibertyClasses
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestLibertyClasses PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestLibertyClasses
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_liberty"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,165 @@
|
|||
Cell INV_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 1.55-1.70
|
||||
ZN output function=!A
|
||||
Cell BUF_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 0.88-0.97
|
||||
Z output function=A
|
||||
Cell NAND2_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A1 input 1.53-1.60
|
||||
A2 input 1.50-1.66
|
||||
ZN output function=!(A1*A2)
|
||||
Cell NOR2_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A1 input 1.41-1.71
|
||||
A2 input 1.56-1.65
|
||||
ZN output function=!(A1+A2)
|
||||
Cell AND2_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A1 input 0.87-0.92
|
||||
A2 input 0.89-0.97
|
||||
ZN output function=A1*A2
|
||||
Cell OR2_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A1 input 0.79-0.95
|
||||
A2 input 0.90-0.94
|
||||
ZN output function=A1+A2
|
||||
Cell MUX2_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 0.91-0.95
|
||||
B input 0.90-0.94
|
||||
S input 1.81-1.92
|
||||
Z output function=(S*B)+(A*!S)
|
||||
Cell DFF_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
IQ internal
|
||||
IQN internal
|
||||
VDD power
|
||||
VSS ground
|
||||
D input 1.06-1.14
|
||||
CK input 0.86-0.95
|
||||
Q output function=IQ
|
||||
QN output function=IQN
|
||||
Cell DFFR_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
IQ internal
|
||||
IQN internal
|
||||
VDD power
|
||||
VSS ground
|
||||
D input 1.05-1.13
|
||||
RN input 1.74-1.78
|
||||
CK input 0.88-0.98
|
||||
Q output function=IQ
|
||||
QN output function=IQN
|
||||
Cell DFFS_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
IQ internal
|
||||
IQN internal
|
||||
VDD power
|
||||
VSS ground
|
||||
D input 1.09-1.16
|
||||
SN input 1.33-1.36
|
||||
CK input 0.88-0.97
|
||||
Q output function=IQ
|
||||
QN output function=IQN
|
||||
Cell DFFRS_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
IQ internal
|
||||
IQN internal
|
||||
VDD power
|
||||
VSS ground
|
||||
D input 1.08-1.15
|
||||
RN input 1.38-1.41
|
||||
SN input 2.10-2.21
|
||||
CK input 0.87-0.96
|
||||
Q output function=IQ
|
||||
QN output function=IQN
|
||||
Cell TLAT_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
IQ internal
|
||||
IQN internal
|
||||
VDD power
|
||||
VSS ground
|
||||
D input 1.07-1.14
|
||||
G input 0.92-1.02
|
||||
OE input 1.42-1.50
|
||||
Q tristate enable=OE function=IQ 0.79-0.79
|
||||
Cell AOI21_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 1.54-1.63
|
||||
B1 input 1.45-1.65
|
||||
B2 input 1.41-1.68
|
||||
ZN output function=!(A+(B1*B2))
|
||||
Cell OAI21_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 1.52-1.67
|
||||
B1 input 1.46-1.66
|
||||
B2 input 1.56-1.57
|
||||
ZN output function=!(A*(B1+B2))
|
||||
Cell HA_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 3.06-3.19
|
||||
B input 3.34-3.45
|
||||
CO output function=A*B
|
||||
S output function=A^B
|
||||
Cell FA_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 3.61-3.75
|
||||
B input 3.40-3.47
|
||||
CI input 2.66-2.76
|
||||
CO output function=(A*B)+(CI*(A+B))
|
||||
S output function=CI^(A^B)
|
||||
Cell CLKBUF_X1
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 0.70-0.78
|
||||
Z output function=A
|
||||
Cell CLKBUF_X2
|
||||
Library NangateOpenCellLibrary
|
||||
File ../../test/nangate45/Nangate45_typ.lib
|
||||
VDD power
|
||||
VSS ground
|
||||
A input 1.24-1.41
|
||||
Z output function=A
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
# Test Nangate45 library reading and cell/pin queries for code coverage
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
|
||||
############################################################
|
||||
# Library queries
|
||||
############################################################
|
||||
|
||||
set lib [get_libs NangateOpenCellLibrary]
|
||||
if { $lib == "" } {
|
||||
puts "FAIL: library not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Inverter cells
|
||||
############################################################
|
||||
|
||||
set inv1 [get_lib_cells NangateOpenCellLibrary/INV_X1]
|
||||
if { $inv1 == "" } {
|
||||
puts "FAIL: INV_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/INV_X1
|
||||
|
||||
set inv_pins [get_lib_pins NangateOpenCellLibrary/INV_X1/*]
|
||||
if { [llength $inv_pins] != 2 } {
|
||||
error "expected 2 pins on INV_X1, found [llength $inv_pins]"
|
||||
}
|
||||
|
||||
# Other inverter sizes
|
||||
foreach sz {X2 X4 X8 X16 X32} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/INV_$sz]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: INV_$sz not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Buffer cells
|
||||
############################################################
|
||||
|
||||
set buf1 [get_lib_cells NangateOpenCellLibrary/BUF_X1]
|
||||
if { $buf1 == "" } {
|
||||
puts "FAIL: BUF_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/BUF_X1
|
||||
|
||||
set buf_pins [get_lib_pins NangateOpenCellLibrary/BUF_X1/*]
|
||||
if { [llength $buf_pins] != 2 } {
|
||||
error "expected 2 pins on BUF_X1, found [llength $buf_pins]"
|
||||
}
|
||||
|
||||
foreach sz {X2 X4 X8 X16 X32} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/BUF_$sz]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: BUF_$sz not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# NAND cells
|
||||
############################################################
|
||||
|
||||
set nand2 [get_lib_cells NangateOpenCellLibrary/NAND2_X1]
|
||||
if { $nand2 == "" } {
|
||||
puts "FAIL: NAND2_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/NAND2_X1
|
||||
|
||||
set nand_pins [get_lib_pins NangateOpenCellLibrary/NAND2_X1/*]
|
||||
if { [llength $nand_pins] != 3 } {
|
||||
error "expected 3 pins on NAND2_X1, found [llength $nand_pins]"
|
||||
}
|
||||
|
||||
foreach cell_name {NAND2_X2 NAND2_X4 NAND3_X1 NAND3_X2 NAND4_X1} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/$cell_name]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: $cell_name not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# NOR cells
|
||||
############################################################
|
||||
|
||||
set nor2 [get_lib_cells NangateOpenCellLibrary/NOR2_X1]
|
||||
if { $nor2 == "" } {
|
||||
puts "FAIL: NOR2_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/NOR2_X1
|
||||
|
||||
foreach cell_name {NOR2_X2 NOR2_X4 NOR3_X1 NOR4_X1} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/$cell_name]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: $cell_name not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# AND cells
|
||||
############################################################
|
||||
|
||||
set and2 [get_lib_cells NangateOpenCellLibrary/AND2_X1]
|
||||
if { $and2 == "" } {
|
||||
puts "FAIL: AND2_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/AND2_X1
|
||||
|
||||
foreach cell_name {AND2_X2 AND2_X4 AND3_X1 AND4_X1} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/$cell_name]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: $cell_name not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# OR cells
|
||||
############################################################
|
||||
|
||||
set or2 [get_lib_cells NangateOpenCellLibrary/OR2_X1]
|
||||
if { $or2 == "" } {
|
||||
puts "FAIL: OR2_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/OR2_X1
|
||||
|
||||
foreach cell_name {OR2_X2 OR2_X4 OR3_X1 OR4_X1} {
|
||||
set cell [get_lib_cells NangateOpenCellLibrary/$cell_name]
|
||||
if { $cell == "" } {
|
||||
puts "FAIL: $cell_name not found"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
############################################################
|
||||
# MUX cells
|
||||
############################################################
|
||||
|
||||
set mux [get_lib_cells NangateOpenCellLibrary/MUX2_X1]
|
||||
if { $mux == "" } {
|
||||
puts "FAIL: MUX2_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/MUX2_X1
|
||||
|
||||
############################################################
|
||||
# DFF cells
|
||||
############################################################
|
||||
|
||||
set dff [get_lib_cells NangateOpenCellLibrary/DFF_X1]
|
||||
if { $dff == "" } {
|
||||
puts "FAIL: DFF_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/DFF_X1
|
||||
|
||||
set dff_pins [get_lib_pins NangateOpenCellLibrary/DFF_X1/*]
|
||||
|
||||
# DFF with reset
|
||||
set dffr [get_lib_cells NangateOpenCellLibrary/DFFR_X1]
|
||||
if { $dffr == "" } {
|
||||
puts "FAIL: DFFR_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/DFFR_X1
|
||||
|
||||
# DFF with set
|
||||
set dffs [get_lib_cells NangateOpenCellLibrary/DFFS_X1]
|
||||
if { $dffs == "" } {
|
||||
puts "FAIL: DFFS_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/DFFS_X1
|
||||
|
||||
# DFF with reset and set
|
||||
set dffrs [get_lib_cells NangateOpenCellLibrary/DFFRS_X1]
|
||||
if { $dffrs == "" } {
|
||||
puts "FAIL: DFFRS_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/DFFRS_X1
|
||||
|
||||
############################################################
|
||||
# Latch (TLAT)
|
||||
############################################################
|
||||
|
||||
set tlat [get_lib_cells NangateOpenCellLibrary/TLAT_X1]
|
||||
if { $tlat == "" } {
|
||||
puts "FAIL: TLAT_X1 not found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/TLAT_X1
|
||||
|
||||
############################################################
|
||||
# Complex cells: AOI, OAI, HA, FA
|
||||
############################################################
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/AOI21_X1
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/OAI21_X1
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/HA_X1
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/FA_X1
|
||||
|
||||
############################################################
|
||||
# get_lib_cells with pattern matching
|
||||
############################################################
|
||||
|
||||
set all_inv [get_lib_cells NangateOpenCellLibrary/INV_*]
|
||||
if { [llength $all_inv] < 6 } {
|
||||
error "expected multiple INV_* cells, found [llength $all_inv]"
|
||||
}
|
||||
|
||||
set all_buf [get_lib_cells NangateOpenCellLibrary/BUF_*]
|
||||
if { [llength $all_buf] < 6 } {
|
||||
error "expected multiple BUF_* cells, found [llength $all_buf]"
|
||||
}
|
||||
|
||||
set all_dff [get_lib_cells NangateOpenCellLibrary/DFF*]
|
||||
if { [llength $all_dff] < 4 } {
|
||||
error "expected multiple DFF* cells, found [llength $all_dff]"
|
||||
}
|
||||
|
||||
set all_cells [get_lib_cells NangateOpenCellLibrary/*]
|
||||
if { [llength $all_cells] < 100 } {
|
||||
error "expected full Nangate library cell list, found [llength $all_cells]"
|
||||
}
|
||||
|
||||
############################################################
|
||||
# get_lib_pins with patterns
|
||||
############################################################
|
||||
|
||||
set all_inv_pins [get_lib_pins NangateOpenCellLibrary/INV_X1/*]
|
||||
if { [llength $all_inv_pins] != 2 } {
|
||||
error "expected 2 INV_X1 pins from wildcard, found [llength $all_inv_pins]"
|
||||
}
|
||||
|
||||
set all_dff_pins [get_lib_pins NangateOpenCellLibrary/DFF_X1/*]
|
||||
if { [llength $all_dff_pins] < 4 } {
|
||||
error "expected DFF_X1 pins to include D/CK/Q(+variants), found [llength $all_dff_pins]"
|
||||
}
|
||||
|
||||
set nand_a1 [get_lib_pins NangateOpenCellLibrary/NAND2_X1/A1]
|
||||
if { [llength $nand_a1] != 1 } {
|
||||
error "expected single NAND2_X1/A1 pin match"
|
||||
}
|
||||
|
||||
############################################################
|
||||
# Clock buffer
|
||||
############################################################
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/CLKBUF_X1
|
||||
|
||||
report_lib_cell NangateOpenCellLibrary/CLKBUF_X2
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("network"
|
||||
TESTS
|
||||
query
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestNetwork TestNetwork.cc)
|
||||
target_link_libraries(TestNetwork
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestNetwork PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestNetwork
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_network"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
|||
Cells: 3
|
||||
Nets: 6
|
||||
Ports: 4
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# Read design and query network objects
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog network_test1.v
|
||||
link_design network_test1
|
||||
|
||||
# Query cells
|
||||
set cells [get_cells *]
|
||||
puts "Cells: [llength $cells]"
|
||||
if { [llength $cells] != 3 } {
|
||||
puts "FAIL: expected 3 cells"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Query nets
|
||||
set nets [get_nets *]
|
||||
puts "Nets: [llength $nets]"
|
||||
if { [llength $nets] == 0 } {
|
||||
puts "FAIL: no nets found"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Query pins
|
||||
set pins [get_pins buf1/*]
|
||||
if { [llength $pins] == 0 } {
|
||||
puts "FAIL: no pins found on buf1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Query ports
|
||||
set ports [get_ports *]
|
||||
puts "Ports: [llength $ports]"
|
||||
if { [llength $ports] != 4 } {
|
||||
puts "FAIL: expected 4 ports"
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
module network_test1 (clk, in1, in2, out1);
|
||||
input clk, in1, in2;
|
||||
output out1;
|
||||
wire n1, n2;
|
||||
|
||||
BUF_X1 buf1 (.A(in1), .Z(n1));
|
||||
AND2_X1 and1 (.A1(n1), .A2(in2), .ZN(n2));
|
||||
DFF_X1 reg1 (.D(n2), .CK(clk), .Q(out1));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("parasitics"
|
||||
TESTS
|
||||
spef
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestParasitics TestParasitics.cc)
|
||||
target_link_libraries(TestParasitics
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestParasitics PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestParasitics
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_parasitics"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,15 @@
|
|||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13178, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13211, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13244, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13277, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13310, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13343, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 13376, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 14772, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 14805, timing group from output port.
|
||||
Warning 1212: ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz line 14838, timing group from output port.
|
||||
r1q total_cap=1.3922564510505161e-14 pin_cap=5.225650124681606e-16 wire_cap=1.3399999392157882e-14
|
||||
r2q total_cap=1.3977042281540768e-14 pin_cap=5.770419894103802e-16 wire_cap=1.3400000239190829e-14
|
||||
u1z total_cap=1.3965708133673559e-14 pin_cap=5.65708000361848e-16 wire_cap=1.3400000239190829e-14
|
||||
u2z total_cap=1.4021215896773027e-14 pin_cap=6.212170340107377e-16 wire_cap=1.3399998545124935e-14
|
||||
No paths found.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# Test SPEF read and parasitics reporting
|
||||
# reg1_asap7 uses ASAP7 cells
|
||||
read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib
|
||||
read_liberty ../../test/asap7/asap7sc7p5t_INVBUF_RVT_FF_nldm_220122.lib.gz
|
||||
read_liberty ../../test/asap7/asap7sc7p5t_SIMPLE_RVT_FF_nldm_211120.lib.gz
|
||||
read_liberty ../../test/asap7/asap7sc7p5t_OA_RVT_FF_nldm_211120.lib.gz
|
||||
read_liberty ../../test/asap7/asap7sc7p5t_AO_RVT_FF_nldm_211120.lib.gz
|
||||
|
||||
read_verilog ../../test/reg1_asap7.v
|
||||
link_design top
|
||||
|
||||
create_clock -name clk1 -period 10 [get_ports clk1]
|
||||
|
||||
# Read SPEF
|
||||
read_spef ../../test/reg1_asap7.spef
|
||||
|
||||
set corner [sta::cmd_scene]
|
||||
foreach net_name {r1q r2q u1z u2z} {
|
||||
set net [get_nets $net_name]
|
||||
set total_cap [$net capacitance $corner "max"]
|
||||
set pin_cap [$net pin_capacitance $corner "max"]
|
||||
set wire_cap [$net wire_capacitance $corner "max"]
|
||||
puts "$net_name total_cap=$total_cap pin_cap=$pin_cap wire_cap=$wire_cap"
|
||||
if {$total_cap <= 0.0} {
|
||||
error "expected positive capacitance on net $net_name after SPEF read"
|
||||
}
|
||||
}
|
||||
|
||||
report_checks -fields {slew cap input_pins fanout}
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("power"
|
||||
TESTS
|
||||
report
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestPower TestPower.cc)
|
||||
target_link_libraries(TestPower
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestPower PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestPower
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_power"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,27 @@
|
|||
# Test power reporting
|
||||
read_liberty ../../test/sky130hd/sky130_fd_sc_hd__tt_025C_1v80.lib
|
||||
read_verilog power_test1.v
|
||||
link_design power_test1
|
||||
|
||||
create_clock -name clk -period 10 [get_ports clk]
|
||||
set_input_delay -clock clk 0 [get_ports in1]
|
||||
set_output_delay -clock clk 0 [get_ports out1]
|
||||
set_input_transition 0.1 [get_ports in1]
|
||||
|
||||
set_power_activity -global -activity 0.5 -duty 0.5
|
||||
|
||||
# Report power with explicit checks on returned content.
|
||||
with_output_to_variable pwr_default { report_power }
|
||||
if {![regexp {Total} $pwr_default]} {
|
||||
error "report_power output missing Total section"
|
||||
}
|
||||
|
||||
with_output_to_variable pwr_inst { report_power -instances [get_cells reg1] }
|
||||
if {![regexp {reg1} $pwr_inst]} {
|
||||
error "instance power report missing reg1 entry"
|
||||
}
|
||||
|
||||
with_output_to_variable pwr_json { report_power -format json }
|
||||
if {![regexp {"Total"} $pwr_json]} {
|
||||
error "json power report missing Total field"
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module power_test1 (clk, in1, out1);
|
||||
input clk, in1;
|
||||
output out1;
|
||||
wire n1;
|
||||
|
||||
sky130_fd_sc_hd__buf_1 buf1 (.A(in1), .X(n1));
|
||||
sky130_fd_sc_hd__dfxtp_1 reg1 (.D(n1), .CLK(clk), .Q(out1));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("sdc"
|
||||
TESTS
|
||||
clocks
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestSdcClasses TestSdcClasses.cc)
|
||||
target_link_libraries(TestSdcClasses
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestSdcClasses PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestSdcClasses
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_sdc"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Clock Period Waveform
|
||||
----------------------------------------------------
|
||||
clk1 10.00 0.00 5.00
|
||||
clk2 20.00 0.00 10.00
|
||||
vclk 5.00 0.00 2.50
|
||||
clk1_fast 5.00 0.00 2.50
|
||||
Warning 1061: generated clock gen_clk_div2 pin clk1 is in the fanout of multiple clocks.
|
||||
Clock Period Waveform
|
||||
----------------------------------------------------
|
||||
clk1 10.00 0.00 5.00
|
||||
clk2 20.00 0.00 10.00
|
||||
vclk 5.00 0.00 2.50
|
||||
clk1_fast 5.00 0.00 2.50
|
||||
gen_clk_div2 10.00 0.00 5.00 (generated)
|
||||
gen_clk_mul3 6.67 0.00 3.33 (generated)
|
||||
Warning 415: sdc_clocks.tcl line 1, set_clock_sense is deprecated as of SDC 2.1. Use set_sense -type clock.
|
||||
No paths found.
|
||||
Clock Period Waveform
|
||||
----------------------------------------------------
|
||||
clk1 10.00 0.00 5.00
|
||||
clk2 20.00 0.00 10.00
|
||||
clk1_fast 5.00 0.00 2.50
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
# Test comprehensive clock SDC commands for code coverage
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog sdc_test2.v
|
||||
link_design sdc_test2
|
||||
|
||||
############################################################
|
||||
# create_clock with various options
|
||||
############################################################
|
||||
|
||||
# Basic clock
|
||||
create_clock -name clk1 -period 10 [get_ports clk1]
|
||||
|
||||
# Clock with waveform
|
||||
create_clock -name clk2 -period 20 -waveform {0 10} [get_ports clk2]
|
||||
|
||||
# Virtual clock (no port)
|
||||
create_clock -name vclk -period 5
|
||||
|
||||
# Clock with -add on same port (additional clock definition)
|
||||
create_clock -name clk1_fast -period 5 -add [get_ports clk1]
|
||||
|
||||
# Report clock properties
|
||||
report_clock_properties
|
||||
|
||||
############################################################
|
||||
# create_generated_clock
|
||||
############################################################
|
||||
|
||||
create_generated_clock -name gen_clk_div2 -source [get_ports clk1] -divide_by 2 [get_pins reg1/Q]
|
||||
|
||||
create_generated_clock -name gen_clk_mul3 -source [get_ports clk2] -multiply_by 3 [get_pins reg3/Q]
|
||||
|
||||
report_clock_properties
|
||||
|
||||
############################################################
|
||||
# set_clock_latency
|
||||
############################################################
|
||||
|
||||
# Source latency with rise/fall min/max
|
||||
set_clock_latency -source 0.5 [get_clocks clk1]
|
||||
|
||||
set_clock_latency -source -rise -max 0.6 [get_clocks clk1]
|
||||
|
||||
set_clock_latency -source -fall -min 0.3 [get_clocks clk1]
|
||||
|
||||
# Network latency
|
||||
set_clock_latency 0.2 [get_clocks clk2]
|
||||
|
||||
set_clock_latency -rise -max 0.4 [get_clocks clk2]
|
||||
|
||||
set_clock_latency -fall -min 0.1 [get_clocks clk2]
|
||||
|
||||
############################################################
|
||||
# set_clock_uncertainty
|
||||
############################################################
|
||||
|
||||
# Simple clock uncertainty
|
||||
set_clock_uncertainty -setup 0.2 [get_clocks clk1]
|
||||
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk1]
|
||||
|
||||
# Inter-clock uncertainty
|
||||
set_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -setup 0.3
|
||||
|
||||
set_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -hold 0.15
|
||||
|
||||
############################################################
|
||||
# set_clock_transition
|
||||
############################################################
|
||||
|
||||
set_clock_transition -rise -max 0.15 [get_clocks clk1]
|
||||
|
||||
set_clock_transition -fall -min 0.08 [get_clocks clk1]
|
||||
|
||||
set_clock_transition 0.1 [get_clocks clk2]
|
||||
|
||||
############################################################
|
||||
# set_propagated_clock
|
||||
############################################################
|
||||
|
||||
set_propagated_clock [get_clocks clk1]
|
||||
|
||||
############################################################
|
||||
# set_clock_groups
|
||||
############################################################
|
||||
|
||||
set_clock_groups -logically_exclusive -group [get_clocks clk1] -group [get_clocks clk2]
|
||||
|
||||
# Remove and re-add as physically exclusive
|
||||
unset_clock_groups -logically_exclusive -all
|
||||
|
||||
set_clock_groups -physically_exclusive -group [get_clocks clk1] -group [get_clocks clk2]
|
||||
|
||||
unset_clock_groups -physically_exclusive -all
|
||||
|
||||
set_clock_groups -asynchronous -group [get_clocks clk1] -group [get_clocks clk2]
|
||||
|
||||
unset_clock_groups -asynchronous -all
|
||||
|
||||
############################################################
|
||||
# set_clock_sense
|
||||
############################################################
|
||||
|
||||
set_clock_sense -positive -clocks [get_clocks clk1] [get_pins buf1/Z]
|
||||
|
||||
############################################################
|
||||
# report_checks to verify constraint effects
|
||||
############################################################
|
||||
|
||||
report_checks -from [get_ports in1] -to [get_ports out1]
|
||||
|
||||
############################################################
|
||||
# Unset/cleanup operations
|
||||
############################################################
|
||||
|
||||
unset_propagated_clock [get_clocks clk1]
|
||||
|
||||
unset_clock_latency [get_clocks clk1]
|
||||
|
||||
unset_clock_latency [get_clocks clk2]
|
||||
|
||||
unset_clock_latency -source [get_clocks clk1]
|
||||
|
||||
unset_clock_transition [get_clocks clk1]
|
||||
|
||||
unset_clock_uncertainty -setup [get_clocks clk1]
|
||||
|
||||
unset_clock_uncertainty -hold [get_clocks clk1]
|
||||
|
||||
unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -setup
|
||||
|
||||
unset_clock_uncertainty -from [get_clocks clk1] -to [get_clocks clk2] -hold
|
||||
|
||||
# Delete generated clocks
|
||||
delete_generated_clock [get_clocks gen_clk_div2]
|
||||
|
||||
delete_generated_clock [get_clocks gen_clk_mul3]
|
||||
|
||||
# Delete regular clocks
|
||||
delete_clock [get_clocks vclk]
|
||||
|
||||
report_clock_properties
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
module sdc_test2 (clk1, clk2, in1, in2, in3, out1, out2);
|
||||
input clk1, clk2, in1, in2, in3;
|
||||
output out1, out2;
|
||||
wire n1, n2, n3, n4, n5, n6, n7;
|
||||
|
||||
BUF_X1 buf1 (.A(in1), .Z(n1));
|
||||
INV_X1 inv1 (.A(in2), .ZN(n2));
|
||||
AND2_X1 and1 (.A1(n1), .A2(n2), .ZN(n3));
|
||||
OR2_X1 or1 (.A1(n1), .A2(in3), .ZN(n4));
|
||||
NAND2_X1 nand1 (.A1(n3), .A2(n4), .ZN(n5));
|
||||
NOR2_X1 nor1 (.A1(n3), .A2(n4), .ZN(n6));
|
||||
|
||||
DFF_X1 reg1 (.D(n5), .CK(clk1), .Q(n7));
|
||||
DFF_X1 reg2 (.D(n6), .CK(clk1), .Q(out1));
|
||||
DFF_X1 reg3 (.D(n7), .CK(clk2), .Q(out2));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("sdf"
|
||||
TESTS
|
||||
annotation
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestSdf TestSdf.cc)
|
||||
target_link_libraries(TestSdf
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestSdf PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestSdf
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_sdf"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
--- read_sdf ---
|
||||
--- report_annotated_delay (all) ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
internal net arcs 1 0 1
|
||||
net arcs from primary inputs 2 0 2
|
||||
net arcs to primary outputs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
7 2 5
|
||||
--- report_annotated_delay -cell ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
----------------------------------------------------------------
|
||||
3 2 1
|
||||
--- report_annotated_delay -net ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
internal net arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
--- report_annotated_delay -from_in_ports ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
net arcs from primary inputs 2 0 2
|
||||
----------------------------------------------------------------
|
||||
2 0 2
|
||||
--- report_annotated_delay -to_out_ports ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
net arcs to primary outputs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
--- report_annotated_delay -cell -report_annotated ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
----------------------------------------------------------------
|
||||
3 2 1
|
||||
|
||||
Annotated Arcs
|
||||
delay buf1/A -> buf1/Z
|
||||
delay reg1/CK -> reg1/Q
|
||||
--- report_annotated_delay -cell -report_unannotated ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
----------------------------------------------------------------
|
||||
3 2 1
|
||||
|
||||
Unannotated Arcs
|
||||
delay reg1/CK -> reg1/QN
|
||||
--- report_annotated_delay -constant_arcs ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
constant arcs 0 0
|
||||
internal net arcs 1 0 1
|
||||
constant arcs 0 0
|
||||
net arcs from primary inputs 2 0 2
|
||||
constant arcs 0 0
|
||||
net arcs to primary outputs 1 0 1
|
||||
constant arcs 0 0
|
||||
----------------------------------------------------------------
|
||||
7 2 5
|
||||
--- report_annotated_delay -max_lines 5 ---
|
||||
Not
|
||||
Delay type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell arcs 3 2 1
|
||||
internal net arcs 1 0 1
|
||||
net arcs from primary inputs 2 0 2
|
||||
net arcs to primary outputs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
7 2 5
|
||||
--- report_annotated_check (all) ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
cell hold arcs 1 0 1
|
||||
cell width arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
3 0 3
|
||||
--- report_annotated_check -setup ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
--- report_annotated_check -hold ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell hold arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
--- report_annotated_check -recovery ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
----------------------------------------------------------------
|
||||
0 0 0
|
||||
--- report_annotated_check -removal ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
----------------------------------------------------------------
|
||||
0 0 0
|
||||
--- report_annotated_check -width ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell width arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
--- report_annotated_check -period ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
----------------------------------------------------------------
|
||||
0 0 0
|
||||
--- report_annotated_check -setup -report_annotated ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
|
||||
Annotated Arcs
|
||||
--- report_annotated_check -setup -report_unannotated ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
1 0 1
|
||||
|
||||
Unannotated Arcs
|
||||
setup reg1/CK -> reg1/D
|
||||
--- report_annotated_check -constant_arcs ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
constant arcs 0 0
|
||||
cell hold arcs 1 0 1
|
||||
constant arcs 0 0
|
||||
cell width arcs 1 0 1
|
||||
constant arcs 0 0
|
||||
----------------------------------------------------------------
|
||||
3 0 3
|
||||
--- report_annotated_check -max_lines 5 ---
|
||||
Not
|
||||
Check type Total Annotated Annotated
|
||||
----------------------------------------------------------------
|
||||
cell setup arcs 1 0 1
|
||||
cell hold arcs 1 0 1
|
||||
cell width arcs 1 0 1
|
||||
----------------------------------------------------------------
|
||||
3 0 3
|
||||
--- report_checks (shows annotated delays) ---
|
||||
Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Endpoint: q (output port clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: max
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
0.00 0.00 ^ reg1/CK (DFF_X1)
|
||||
0.40 0.40 ^ reg1/Q (DFF_X1)
|
||||
0.00 0.40 ^ q (out)
|
||||
0.40 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
|
||||
0.00 10.00 output external delay
|
||||
10.00 data required time
|
||||
---------------------------------------------------------
|
||||
10.00 data required time
|
||||
-0.40 data arrival time
|
||||
---------------------------------------------------------
|
||||
9.60 slack (MET)
|
||||
|
||||
|
||||
--- report_checks -format full_clock ---
|
||||
Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Endpoint: q (output port clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: max
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
0.00 0.00 ^ reg1/CK (DFF_X1)
|
||||
0.40 0.40 ^ reg1/Q (DFF_X1)
|
||||
0.00 0.40 ^ q (out)
|
||||
0.40 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
|
||||
0.00 10.00 output external delay
|
||||
10.00 data required time
|
||||
---------------------------------------------------------
|
||||
10.00 data required time
|
||||
-0.40 data arrival time
|
||||
---------------------------------------------------------
|
||||
9.60 slack (MET)
|
||||
|
||||
|
||||
--- report_checks -path_delay min ---
|
||||
Startpoint: d (input port clocked by clk)
|
||||
Endpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: min
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
0.00 0.00 ^ input external delay
|
||||
0.00 0.00 ^ d (in)
|
||||
0.10 0.10 ^ buf1/Z (BUF_X1)
|
||||
0.00 0.10 ^ reg1/D (DFF_X1)
|
||||
0.10 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 ^ reg1/CK (DFF_X1)
|
||||
0.00 0.00 library hold time
|
||||
0.00 data required time
|
||||
---------------------------------------------------------
|
||||
0.00 data required time
|
||||
-0.10 data arrival time
|
||||
---------------------------------------------------------
|
||||
0.10 slack (MET)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# Test SDF annotation and reporting commands
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog sdf_test1.v
|
||||
link_design sdf_test1
|
||||
|
||||
create_clock -name clk -period 10 [get_ports clk]
|
||||
set_input_delay -clock clk 0 [get_ports d]
|
||||
set_output_delay -clock clk 0 [get_ports q]
|
||||
|
||||
puts "--- read_sdf ---"
|
||||
read_sdf sdf_test1.sdf
|
||||
|
||||
puts "--- report_annotated_delay (all) ---"
|
||||
report_annotated_delay
|
||||
|
||||
puts "--- report_annotated_delay -cell ---"
|
||||
report_annotated_delay -cell
|
||||
|
||||
puts "--- report_annotated_delay -net ---"
|
||||
report_annotated_delay -net
|
||||
|
||||
puts "--- report_annotated_delay -from_in_ports ---"
|
||||
report_annotated_delay -from_in_ports
|
||||
|
||||
puts "--- report_annotated_delay -to_out_ports ---"
|
||||
report_annotated_delay -to_out_ports
|
||||
|
||||
puts "--- report_annotated_delay -cell -report_annotated ---"
|
||||
report_annotated_delay -cell -report_annotated
|
||||
|
||||
puts "--- report_annotated_delay -cell -report_unannotated ---"
|
||||
report_annotated_delay -cell -report_unannotated
|
||||
|
||||
puts "--- report_annotated_delay -constant_arcs ---"
|
||||
report_annotated_delay -constant_arcs
|
||||
|
||||
puts "--- report_annotated_delay -max_lines 5 ---"
|
||||
report_annotated_delay -max_lines 5
|
||||
|
||||
puts "--- report_annotated_check (all) ---"
|
||||
report_annotated_check
|
||||
|
||||
puts "--- report_annotated_check -setup ---"
|
||||
report_annotated_check -setup
|
||||
|
||||
puts "--- report_annotated_check -hold ---"
|
||||
report_annotated_check -hold
|
||||
|
||||
puts "--- report_annotated_check -recovery ---"
|
||||
report_annotated_check -recovery
|
||||
|
||||
puts "--- report_annotated_check -removal ---"
|
||||
report_annotated_check -removal
|
||||
|
||||
puts "--- report_annotated_check -width ---"
|
||||
report_annotated_check -width
|
||||
|
||||
puts "--- report_annotated_check -period ---"
|
||||
report_annotated_check -period
|
||||
|
||||
puts "--- report_annotated_check -setup -report_annotated ---"
|
||||
report_annotated_check -setup -report_annotated
|
||||
|
||||
puts "--- report_annotated_check -setup -report_unannotated ---"
|
||||
report_annotated_check -setup -report_unannotated
|
||||
|
||||
puts "--- report_annotated_check -constant_arcs ---"
|
||||
report_annotated_check -constant_arcs
|
||||
|
||||
puts "--- report_annotated_check -max_lines 5 ---"
|
||||
report_annotated_check -max_lines 5
|
||||
|
||||
puts "--- report_checks (shows annotated delays) ---"
|
||||
report_checks
|
||||
|
||||
puts "--- report_checks -format full_clock ---"
|
||||
report_checks -format full_clock
|
||||
|
||||
puts "--- report_checks -path_delay min ---"
|
||||
report_checks -path_delay min
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
(DELAYFILE
|
||||
(SDFVERSION "3.0")
|
||||
(DESIGN "sdf_test1")
|
||||
(TIMESCALE 1ns)
|
||||
(CELL
|
||||
(CELLTYPE "BUF_X1")
|
||||
(INSTANCE buf1)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH A Z (0.1:0.2:0.3) (0.1:0.2:0.3))
|
||||
)
|
||||
)
|
||||
)
|
||||
(CELL
|
||||
(CELLTYPE "DFF_X1")
|
||||
(INSTANCE reg1)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH CK Q (0.2:0.3:0.4) (0.2:0.3:0.4))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module sdf_test1 (clk, d, q);
|
||||
input clk, d;
|
||||
output q;
|
||||
wire n1;
|
||||
|
||||
BUF_X1 buf1 (.A(d), .Z(n1));
|
||||
DFF_X1 reg1 (.D(n1), .CK(clk), .Q(q));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("search"
|
||||
TESTS
|
||||
timing
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
add_executable(TestSearchClasses TestSearchClasses.cc)
|
||||
target_link_libraries(TestSearchClasses
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestSearchClasses PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestSearchClasses
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_search"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
module search_test1 (clk, in1, in2, out1);
|
||||
input clk, in1, in2;
|
||||
output out1;
|
||||
wire n1, n2, n3;
|
||||
|
||||
AND2_X1 and1 (.A1(in1), .A2(in2), .ZN(n1));
|
||||
BUF_X1 buf1 (.A(n1), .Z(n2));
|
||||
DFF_X1 reg1 (.D(n2), .CK(clk), .Q(n3));
|
||||
BUF_X1 buf2 (.A(n3), .Z(out1));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Endpoint: out1 (output port clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: max
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
0.00 0.00 ^ reg1/CK (DFF_X1)
|
||||
0.08 0.08 ^ reg1/Q (DFF_X1)
|
||||
0.02 0.10 ^ buf2/Z (BUF_X1)
|
||||
0.00 0.10 ^ out1 (out)
|
||||
0.10 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
|
||||
-2.00 8.00 output external delay
|
||||
8.00 data required time
|
||||
---------------------------------------------------------
|
||||
8.00 data required time
|
||||
-0.10 data arrival time
|
||||
---------------------------------------------------------
|
||||
7.90 slack (MET)
|
||||
|
||||
|
||||
Startpoint: in1 (input port clocked by clk)
|
||||
Endpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: min
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
1.00 1.00 ^ input external delay
|
||||
0.00 1.00 ^ in1 (in)
|
||||
0.02 1.02 ^ and1/ZN (AND2_X1)
|
||||
0.02 1.04 ^ buf1/Z (BUF_X1)
|
||||
0.00 1.04 ^ reg1/D (DFF_X1)
|
||||
1.04 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 ^ reg1/CK (DFF_X1)
|
||||
0.00 0.00 library hold time
|
||||
0.00 data required time
|
||||
---------------------------------------------------------
|
||||
0.00 data required time
|
||||
-1.04 data arrival time
|
||||
---------------------------------------------------------
|
||||
1.04 slack (MET)
|
||||
|
||||
|
||||
Worst slack: 7.899713772019368e-9
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Full timing analysis flow test
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog search_test1.v
|
||||
link_design search_test1
|
||||
|
||||
create_clock -name clk -period 10 [get_ports clk]
|
||||
set_input_delay -clock clk 1.0 [get_ports in1]
|
||||
set_input_delay -clock clk 1.0 [get_ports in2]
|
||||
set_output_delay -clock clk 2.0 [get_ports out1]
|
||||
|
||||
# Setup analysis
|
||||
report_checks -path_delay max
|
||||
|
||||
# Hold analysis
|
||||
report_checks -path_delay min
|
||||
|
||||
# Check worst slack
|
||||
set slack [sta::worst_slack_cmd "max"]
|
||||
puts "Worst slack: $slack"
|
||||
if { $slack == "" } {
|
||||
puts "FAIL: no slack found"
|
||||
exit 1
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
sta_module_tests("spice"
|
||||
TESTS
|
||||
write
|
||||
)
|
||||
|
||||
add_subdirectory(cpp)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
add_executable(TestSpice TestSpice.cc)
|
||||
target_link_libraries(TestSpice
|
||||
OpenSTA
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
${TCL_LIBRARY}
|
||||
)
|
||||
target_include_directories(TestSpice PRIVATE
|
||||
${STA_HOME}/include/sta
|
||||
${STA_HOME}
|
||||
${STA_HOME}/spice
|
||||
${CMAKE_BINARY_DIR}/include/sta
|
||||
)
|
||||
gtest_discover_tests(TestSpice
|
||||
WORKING_DIRECTORY ${STA_HOME}
|
||||
PROPERTIES LABELS "cpp\;module_spice"
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
../../test/regression
|
||||
|
|
@ -0,0 +1 @@
|
|||
../../test/shared/save_ok
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
module spice_test1 (clk, in1, out1);
|
||||
input clk, in1;
|
||||
output out1;
|
||||
wire n1;
|
||||
|
||||
BUF_X1 buf1 (.A(in1), .Z(n1));
|
||||
DFF_X1 reg1 (.D(n1), .CK(clk), .Q(out1));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
Startpoint: reg1 (rising edge-triggered flip-flop clocked by clk)
|
||||
Endpoint: out1 (output port clocked by clk)
|
||||
Path Group: clk
|
||||
Path Type: max
|
||||
|
||||
Delay Time Description
|
||||
---------------------------------------------------------
|
||||
0.00 0.00 clock clk (rise edge)
|
||||
0.00 0.00 clock network delay (ideal)
|
||||
0.00 0.00 ^ reg1/CK (DFF_X1)
|
||||
0.08 0.08 ^ reg1/Q (DFF_X1)
|
||||
0.00 0.08 ^ out1 (out)
|
||||
0.08 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
|
||||
0.00 10.00 output external delay
|
||||
10.00 data required time
|
||||
---------------------------------------------------------
|
||||
10.00 data required time
|
||||
-0.08 data arrival time
|
||||
---------------------------------------------------------
|
||||
9.92 slack (MET)
|
||||
|
||||
|
||||
Differences found at line 2.
|
||||
.include "/workspace/sta/OpenSTA/spice/test/results/spice_out/mock_model.sp"
|
||||
.include "/workspace/sta2/OpenSTA/spice/test/results/spice_out/mock_model.sp"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
* Path from reg1/Q ^ to out1 ^
|
||||
.include "/workspace/sta/OpenSTA/spice/test/results/spice_out/mock_model.sp"
|
||||
.include "path_1.subckt"
|
||||
.tran 1e-13 3.1e-08
|
||||
|
||||
.print tran v(clk) v(reg1/CK) v(reg1/Q) v(out1)
|
||||
|
||||
**************
|
||||
* Input source
|
||||
**************
|
||||
|
||||
v1 clk 0 pwl(
|
||||
+0.000e+00 0.000e+00
|
||||
+9.985e-10 0.000e+00
|
||||
+1.001e-09 1.100e+00
|
||||
+5.999e-09 1.100e+00
|
||||
+6.001e-09 0.000e+00
|
||||
+1.100e-08 0.000e+00
|
||||
+1.100e-08 1.100e+00
|
||||
+1.600e-08 1.100e+00
|
||||
+1.600e-08 0.000e+00
|
||||
+2.100e-08 0.000e+00
|
||||
+2.100e-08 1.100e+00
|
||||
+2.600e-08 1.100e+00
|
||||
+2.600e-08 0.000e+00
|
||||
+3.100e-08 0.000e+00
|
||||
+)
|
||||
|
||||
*****************
|
||||
* Stage instances
|
||||
*****************
|
||||
|
||||
xstage1 clk reg1/CK stage1
|
||||
xstage2 reg1/CK reg1/Q out1 stage2
|
||||
|
||||
***************
|
||||
* Stage subckts
|
||||
***************
|
||||
|
||||
.subckt stage1 clk reg1/CK
|
||||
* Net clk
|
||||
* Net has no parasitics.
|
||||
R1 clk reg1/CK 1.000e-04
|
||||
.ends
|
||||
|
||||
.subckt stage2 reg1/CK reg1/Q out1
|
||||
* Gate reg1 CK -> Q
|
||||
xreg1 reg1/D reg1/CK reg1/Q reg1/VDD reg1/VSS DFF_X1
|
||||
v1 reg1/D 0 1.100
|
||||
v2 reg1/VDD 0 1.100
|
||||
v3 reg1/VSS 0 0.000
|
||||
|
||||
* Load pins
|
||||
* Net out1
|
||||
* Net has no parasitics.
|
||||
R1 reg1/Q out1 1.000e-04
|
||||
.ends
|
||||
|
||||
.end
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# Test spice-related functionality
|
||||
source ../../test/helpers.tcl
|
||||
set test_name spice_write
|
||||
|
||||
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
||||
read_verilog spice_test1.v
|
||||
link_design spice_test1
|
||||
|
||||
create_clock -name clk -period 10 [get_ports clk]
|
||||
set_input_delay -clock clk 0 [get_ports in1]
|
||||
set_output_delay -clock clk 0 [get_ports out1]
|
||||
|
||||
# Run timing analysis (needed before write_path_spice)
|
||||
report_checks
|
||||
|
||||
# Create mock SPICE model and subckt files for write_path_spice
|
||||
set spice_dir [make_result_file spice_out]
|
||||
file mkdir $spice_dir
|
||||
|
||||
set model_file [file join $spice_dir mock_model.sp]
|
||||
set model_fh [open $model_file w]
|
||||
puts $model_fh "* Mock SPICE model file"
|
||||
puts $model_fh ".model nmos nmos level=1"
|
||||
puts $model_fh ".model pmos pmos level=1"
|
||||
close $model_fh
|
||||
|
||||
set subckt_file [file join $spice_dir mock_subckt.sp]
|
||||
set subckt_fh [open $subckt_file w]
|
||||
puts $subckt_fh "* Mock SPICE subckt file"
|
||||
puts $subckt_fh ".subckt BUF_X1 A Z VDD VSS"
|
||||
puts $subckt_fh "M1 Z A VDD VDD pmos W=1u L=100n"
|
||||
puts $subckt_fh "M2 Z A VSS VSS nmos W=1u L=100n"
|
||||
puts $subckt_fh ".ends"
|
||||
puts $subckt_fh ""
|
||||
puts $subckt_fh ".subckt DFF_X1 D CK Q VDD VSS"
|
||||
puts $subckt_fh "M1 Q D VDD VDD pmos W=1u L=100n"
|
||||
puts $subckt_fh "M2 Q D VSS VSS nmos W=1u L=100n"
|
||||
puts $subckt_fh ".ends"
|
||||
close $subckt_fh
|
||||
|
||||
# write_path_spice - exercises the Tcl command parsing and
|
||||
# C++ WritePathSpice code paths.
|
||||
write_path_spice \
|
||||
-path_args {-sort_by_slack} \
|
||||
-spice_directory $spice_dir \
|
||||
-lib_subckt_file $subckt_file \
|
||||
-model_file $model_file \
|
||||
-power VDD \
|
||||
-ground VSS
|
||||
diff_files $test_name.spok [file join $spice_dir path_1.sp]
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Register existing upstream Tcl tests for ctest coverage
|
||||
set(STA_EXE $<TARGET_FILE:sta>)
|
||||
set(TEST_DIR ${STA_HOME}/test)
|
||||
set(EXAMPLES_DIR ${STA_HOME}/examples)
|
||||
|
||||
function(sta_tcl_test test_name)
|
||||
add_test(
|
||||
NAME tcl.${test_name}
|
||||
COMMAND ${STA_EXE} -no_init -no_splash -exit ${TEST_DIR}/${test_name}.tcl
|
||||
WORKING_DIRECTORY ${TEST_DIR}
|
||||
)
|
||||
set_tests_properties(tcl.${test_name} PROPERTIES LABELS "tcl")
|
||||
endfunction()
|
||||
|
||||
function(sta_example_test test_name)
|
||||
add_test(
|
||||
NAME tcl.example.${test_name}
|
||||
COMMAND ${STA_EXE} -no_init -no_splash -exit ${EXAMPLES_DIR}/${test_name}.tcl
|
||||
WORKING_DIRECTORY ${EXAMPLES_DIR}
|
||||
)
|
||||
set_tests_properties(tcl.example.${test_name} PROPERTIES LABELS "tcl;example")
|
||||
endfunction()
|
||||
|
||||
# Auto-detect public tests: register all *.ok files that have a matching *.tcl
|
||||
file(GLOB ok_files "${TEST_DIR}/*.ok")
|
||||
foreach(ok_file ${ok_files})
|
||||
get_filename_component(test_name ${ok_file} NAME_WE)
|
||||
if(EXISTS "${TEST_DIR}/${test_name}.tcl")
|
||||
sta_tcl_test(${test_name})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Auto-detect example tests: register all *.tcl files in examples/
|
||||
file(GLOB example_tcl_files "${EXAMPLES_DIR}/*.tcl")
|
||||
foreach(tcl_file ${example_tcl_files})
|
||||
get_filename_component(test_name ${tcl_file} NAME_WE)
|
||||
sta_example_test(${test_name})
|
||||
endforeach()
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue