Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-02-02 16:48:27 +00:00
commit 2c5df8ccbc
54 changed files with 1533 additions and 1257 deletions

View File

@ -101,8 +101,7 @@ set(STA_SOURCE
liberty/LeakagePower.cc liberty/LeakagePower.cc
liberty/Liberty.cc liberty/Liberty.cc
liberty/LibertyBuilder.cc liberty/LibertyBuilder.cc
liberty/LibertyExpr.cc liberty/LibExprReader.cc
liberty/LibertyExprPvt.hh
liberty/LibertyParser.cc liberty/LibertyParser.cc
liberty/LibertyReader.cc liberty/LibertyReader.cc
liberty/LibertyWriter.cc liberty/LibertyWriter.cc
@ -271,61 +270,48 @@ set(STA_TCL_FILES
# Earlier versions of flex use 'register' declarations that are illegal in c++17. # Earlier versions of flex use 'register' declarations that are illegal in c++17.
#find_package(FLEX 2.6.4) #find_package(FLEX 2.6.4)
find_package(FLEX) find_package(FLEX)
find_package(BISON) find_package(BISON REQUIRED 3.2)
# Liberty scan/parse.
flex_target(LibertyLex ${STA_HOME}/liberty/LibertyLex.ll
${CMAKE_CURRENT_BINARY_DIR}/LibertyLex.cc)
bison_target(LibertyParse ${STA_HOME}/liberty/LibertyParse.yy
${CMAKE_CURRENT_BINARY_DIR}/LibertyParse.cc
# centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class
COMPILE_FLAGS "-Wno-deprecated")
add_flex_bison_dependency(LibertyLex LibertyParse)
# LibertyExpr scan/parse.
flex_target(LibertyExprLex ${STA_HOME}/liberty/LibertyExprLex.ll
${CMAKE_CURRENT_BINARY_DIR}/LibertyExprLex.cc
COMPILE_FLAGS --prefix=LibertyExprLex_)
bison_target(LibertyExprParse ${STA_HOME}/liberty/LibertyExprParse.yy
${CMAKE_CURRENT_BINARY_DIR}/LibertyExprParse.cc
COMPILE_FLAGS --name-prefix=LibertyExprParse_
)
add_flex_bison_dependency(LibertyExprLex LibertyExprParse)
# Spef scan/parse.
flex_target(SpefLex ${STA_HOME}/parasitics/SpefLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SpefLex.cc
COMPILE_FLAGS --prefix=SpefLex_
)
bison_target(SpefParse ${STA_HOME}/parasitics/SpefParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SpefParse.cc
COMPILE_FLAGS --name-prefix=SpefParse_
)
add_flex_bison_dependency(SpefLex SpefParse)
# Verilog scan/parse. # Verilog scan/parse.
flex_target(VerilogLex ${STA_HOME}/verilog/VerilogLex.ll flex_target(VerilogLex ${STA_HOME}/verilog/VerilogLex.ll
${CMAKE_CURRENT_BINARY_DIR}/VerilogLex.cc) ${CMAKE_CURRENT_BINARY_DIR}/VerilogLex.cc)
bison_target(VerilogParse ${STA_HOME}/verilog/VerilogParse.yy bison_target(VerilogParse ${STA_HOME}/verilog/VerilogParse.yy
${CMAKE_CURRENT_BINARY_DIR}/VerilogParse.cc ${CMAKE_CURRENT_BINARY_DIR}/VerilogParse.cc)
# centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class
COMPILE_FLAGS "-Wno-deprecated")
add_flex_bison_dependency(VerilogLex VerilogParse) add_flex_bison_dependency(VerilogLex VerilogParse)
# Liberty scan/parse.
flex_target(LibertyLex ${STA_HOME}/liberty/LibertyLex.ll
${CMAKE_CURRENT_BINARY_DIR}/LibertyLex.cc)
bison_target(LibertyParse ${STA_HOME}/liberty/LibertyParse.yy
${CMAKE_CURRENT_BINARY_DIR}/LibertyParse.cc)
add_flex_bison_dependency(LibertyLex LibertyParse)
# Liberty Expr scan/parse.
flex_target(LibExprLex ${STA_HOME}/liberty/LibExprLex.ll
${CMAKE_CURRENT_BINARY_DIR}/LibExprLex.cc)
bison_target(LibExprParse ${STA_HOME}/liberty/LibExprParse.yy
${CMAKE_CURRENT_BINARY_DIR}/LibExprParse.cc)
add_flex_bison_dependency(LibExprLex LibExprParse)
# Sdf scan/parse. # Sdf scan/parse.
flex_target(SdfLex ${STA_HOME}/sdf/SdfLex.ll flex_target(SdfLex ${STA_HOME}/sdf/SdfLex.ll
${CMAKE_CURRENT_BINARY_DIR}/SdfLex.cc) ${CMAKE_CURRENT_BINARY_DIR}/SdfLex.cc)
bison_target(SdfParse ${STA_HOME}/sdf/SdfParse.yy bison_target(SdfParse ${STA_HOME}/sdf/SdfParse.yy
${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc ${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc)
# centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class
COMPILE_FLAGS "-Wno-deprecated")
add_flex_bison_dependency(SdfLex SdfParse) add_flex_bison_dependency(SdfLex SdfParse)
# Spef scan/parse.
flex_target(SpefLex ${STA_HOME}/parasitics/SpefLex.ll
${CMAKE_CURRENT_BINARY_DIR}/SpefLex.cc)
bison_target(SpefParse ${STA_HOME}/parasitics/SpefParse.yy
${CMAKE_CURRENT_BINARY_DIR}/SpefParse.cc)
add_flex_bison_dependency(SpefLex SpefParse)
# Saif scan/parse. # Saif scan/parse.
flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll
COMPILE_FLAGS --prefix=SaifLex_ ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc)
) bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy
bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc)
COMPILE_FLAGS --name-prefix=SaifParse_
)
add_flex_bison_dependency(SaifLex SaifParse) add_flex_bison_dependency(SaifLex SaifParse)
################################################################ ################################################################
@ -497,8 +483,8 @@ target_sources(OpenSTA
${STA_TCL_INIT} ${STA_TCL_INIT}
${FLEX_LibertyExprLex_OUTPUTS} ${FLEX_LibExprLex_OUTPUTS}
${BISON_LibertyExprParse_OUTPUTS} ${BISON_LibExprParse_OUTPUTS}
${FLEX_LibertyLex_OUTPUTS} ${FLEX_LibertyLex_OUTPUTS}
${BISON_LibertyParse_OUTPUTS} ${BISON_LibertyParse_OUTPUTS}

View File

@ -2,7 +2,7 @@ FROM centos:centos7 AS base-dependencies
LABEL author="James Cherry" LABEL author="James Cherry"
LABEL maintainer="James Cherry <cherry@parallaxsw.com>" LABEL maintainer="James Cherry <cherry@parallaxsw.com>"
# Install dev and runtime dependencies # Install dev and runtime dependencies (use vault repos since mirror repos are discontinued)
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \ RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \
&& sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo \ && sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo \
&& sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo \ && sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo \
@ -11,20 +11,33 @@ RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \ RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo \
&& sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo \ && sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo \
&& sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo \ && sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo \
&& yum install -y devtoolset-8 wget cmake3 make eigen3-devel tcl-devel tcl-tclreadline-devel swig3 bison flex zlib-devel valgrind \ && yum install -y devtoolset-11 wget cmake3 make eigen3-devel tcl-devel swig3 flex zlib-devel valgrind \
&& yum clean -y all && yum clean -y all
# Download Bison
RUN wget https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.gz && \
tar -xvf bison-3.8.2.tar.gz && \
rm bison-3.8.2.tar.gz
# Build Bison
RUN source /opt/rh/devtoolset-11/enable && \
cd bison-3.8.2 && \
./configure && \
make -j`nproc` && \
make install
# Download CUDD # Download CUDD
RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \ RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \
tar -xvf cudd-3.0.0.tar.gz && \ tar -xvf cudd-3.0.0.tar.gz && \
rm cudd-3.0.0.tar.gz rm cudd-3.0.0.tar.gz
# Build CUDD # Build CUDD
RUN source /opt/rh/devtoolset-8/enable && \ RUN source /opt/rh/devtoolset-11/enable && \
cd cudd-3.0.0 && \ cd cudd-3.0.0 && \
mkdir ../cudd && \ mkdir ../cudd && \
./configure && \ ./configure && \
make -j`nproc` make -j`nproc` && \
make install
FROM base-dependencies AS builder FROM base-dependencies AS builder
@ -33,9 +46,9 @@ WORKDIR /OpenSTA
# Build # Build
RUN rm -rf build && mkdir build RUN rm -rf build && mkdir build
RUN source /opt/rh/devtoolset-8/enable && \ RUN source /opt/rh/devtoolset-11/enable && \
cd build && \ cd build && \
cmake3 -DCUDD_DIR=../cudd-3.0.0 .. && \ cmake3 .. && \
make -j`nproc` make -j`nproc`
# Run sta on entry # Run sta on entry

View File

@ -321,8 +321,8 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex,
Port *port = network_->port(drvr_pin); Port *port = network_->port(drvr_pin);
drive = sdc_->findInputDrive(port); drive = sdc_->findInputDrive(port);
} }
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
if (drive) { if (drive) {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
const LibertyCell *drvr_cell; const LibertyCell *drvr_cell;
@ -350,8 +350,8 @@ void
GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex, GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
InputDrive *drive, const InputDrive *drive,
DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc)
{ {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
@ -397,7 +397,7 @@ void
GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex, GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc)
{ {
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
@ -429,8 +429,8 @@ GraphDelayCalc::seedLoadSlew(Vertex *vertex)
vertex->name(sdc_network_)); vertex->name(sdc_network_));
ClockSet *clks = sdc_->findLeafPinClocks(pin); ClockSet *clks = sdc_->findLeafPinClocks(pin);
initSlew(vertex); initSlew(vertex);
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
if (!vertex->slewAnnotated(rf, slew_min_max)) { if (!vertex->slewAnnotated(rf, slew_min_max)) {
float slew = 0.0; float slew = 0.0;
@ -807,11 +807,11 @@ GraphDelayCalc::initLoadSlews(Vertex *drvr_vertex)
Edge *wire_edge = edge_iter.next(); Edge *wire_edge = edge_iter.next();
if (wire_edge->isWire()) { if (wire_edge->isWire()) {
Vertex *load_vertex = wire_edge->to(graph_); Vertex *load_vertex = wire_edge->to(graph_);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
Slew slew_init_value(slew_min_max->initValue()); Slew slew_init_value(slew_min_max->initValue());
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
if (!load_vertex->slewAnnotated(rf, slew_min_max)) if (!load_vertex->slewAnnotated(rf, slew_min_max))
graph_->setSlew(load_vertex, rf, ap_index, slew_init_value); graph_->setSlew(load_vertex, rf, ap_index, slew_init_value);
} }
@ -842,7 +842,7 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
arc_delay_calc, load_pin_index_map, arc_delay_calc, load_pin_index_map,
delay_exists); delay_exists);
} }
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
if (!delay_exists[rf->index()]) if (!delay_exists[rf->index()])
zeroSlewAndWireDelays(drvr_vertex, rf); zeroSlewAndWireDelays(drvr_vertex, rf);
} }
@ -856,10 +856,10 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
void void
GraphDelayCalc::initRootSlews(Vertex *vertex) GraphDelayCalc::initRootSlews(Vertex *vertex)
{ {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
if (!vertex->slewAnnotated(rf, slew_min_max)) if (!vertex->slewAnnotated(rf, slew_min_max))
graph_->setSlew(vertex, rf, ap_index, default_slew); graph_->setSlew(vertex, rf, ap_index, default_slew);
} }
@ -895,7 +895,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
Vertex *from_vertex = edge->from(graph_); Vertex *from_vertex = edge->from(graph_);
const TimingArcSet *arc_set = edge->timingArcSet(); const TimingArcSet *arc_set = edge->timingArcSet();
bool delay_changed = false; bool delay_changed = false;
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
for (const TimingArc *arc : arc_set->arcs()) { for (const TimingArc *arc : arc_set->arcs()) {
delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc, delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc,
dcalc_ap, arc_delay_calc, dcalc_ap, arc_delay_calc,
@ -982,7 +982,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc)
{ {
ArcDcalcArgSeq dcalc_args; ArcDcalcArgSeq dcalc_args;
for (auto drvr_vertex1 : multi_drvr->drvrs()) { for (Vertex *drvr_vertex1 : multi_drvr->drvrs()) {
Edge *edge1 = nullptr; Edge *edge1 = nullptr;
const TimingArc *arc1 = nullptr; const TimingArc *arc1 = nullptr;
if (drvr_vertex1 == drvr_vertex) { if (drvr_vertex1 == drvr_vertex) {
@ -1212,7 +1212,7 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
{ {
const MinMax *min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
float load_cap = min_max->initValue(); float load_cap = min_max->initValue();
for (auto drvr_rf : RiseFall::range()) { for (const RiseFall *drvr_rf : RiseFall::range()) {
float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap); float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap);
load_cap = min_max->minMax(cap, load_cap); load_cap = min_max->minMax(cap, load_cap);
} }
@ -1359,8 +1359,8 @@ GraphDelayCalc::netCaps(const Pin *drvr_pin,
void void
GraphDelayCalc::initSlew(Vertex *vertex) GraphDelayCalc::initSlew(Vertex *vertex)
{ {
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
if (!vertex->slewAnnotated(rf, slew_min_max)) { if (!vertex->slewAnnotated(rf, slew_min_max)) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
@ -1374,7 +1374,7 @@ void
GraphDelayCalc::zeroSlewAndWireDelays(Vertex *drvr_vertex, GraphDelayCalc::zeroSlewAndWireDelays(Vertex *drvr_vertex,
const RiseFall *rf) const RiseFall *rf)
{ {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
const MinMax *slew_min_max = dcalc_ap->slewMinMax(); const MinMax *slew_min_max = dcalc_ap->slewMinMax();
// Init drvr slew. // Init drvr slew.
@ -1406,11 +1406,11 @@ GraphDelayCalc::initWireDelays(Vertex *drvr_vertex)
while (edge_iter.hasNext()) { while (edge_iter.hasNext()) {
Edge *wire_edge = edge_iter.next(); Edge *wire_edge = edge_iter.next();
if (wire_edge->isWire()) { if (wire_edge->isWire()) {
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt * dcalc_ap : corners_->dcalcAnalysisPts()) {
const MinMax *delay_min_max = dcalc_ap->delayMinMax(); const MinMax *delay_min_max = dcalc_ap->delayMinMax();
Delay delay_init_value(delay_min_max->initValue()); Delay delay_init_value(delay_min_max->initValue());
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
for (auto rf : RiseFall::range()) { for (const RiseFall *rf : RiseFall::range()) {
if (!graph_->wireDelayAnnotated(wire_edge, rf, ap_index)) if (!graph_->wireDelayAnnotated(wire_edge, rf, ap_index))
graph_->setWireArcDelay(wire_edge, rf, ap_index, delay_init_value); graph_->setWireArcDelay(wire_edge, rf, ap_index, delay_init_value);
} }
@ -1466,7 +1466,7 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
const Pin *related_out_pin = 0; const Pin *related_out_pin = 0;
if (related_out_port) if (related_out_port)
related_out_pin = network_->findPin(inst, related_out_port); related_out_pin = network_->findPin(inst, related_out_port);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) { if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf,
@ -1583,7 +1583,7 @@ GraphDelayCalc::minPeriod(const Pin *pin,
{ {
exists = false; exists = false;
const MinMax *min_max = MinMax::max(); const MinMax *min_max = MinMax::max();
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
// Sdf annotation. // Sdf annotation.
float min_period1 = 0.0; float min_period1 = 0.0;
bool exists1 = false; bool exists1 = false;
@ -1639,11 +1639,11 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
int count = RiseFall::index_count * corners->dcalcAnalysisPtCount(); int count = RiseFall::index_count * corners->dcalcAnalysisPtCount();
net_caps_.resize(count); net_caps_.resize(count);
const Pin *drvr_pin = dcalc_drvr_->pin(); const Pin *drvr_pin = dcalc_drvr_->pin();
for (auto dcalc_ap : corners->dcalcAnalysisPts()) { for (const DcalcAnalysisPt *dcalc_ap : corners->dcalcAnalysisPts()) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
const MinMax *min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
for (auto drvr_rf : RiseFall::range()) { for (const RiseFall *drvr_rf : RiseFall::range()) {
int drvr_rf_index = drvr_rf->index(); int drvr_rf_index = drvr_rf->index();
int index = ap_index * RiseFall::index_count + drvr_rf_index; int index = ap_index * RiseFall::index_count + drvr_rf_index;
NetCaps &net_caps = net_caps_[index]; NetCaps &net_caps = net_caps_[index];

View File

@ -83,18 +83,6 @@ private:
%inline %{ %inline %{
int
graph_vertex_count()
{
return Sta::sta()->ensureGraph()->vertexCount();
}
int
graph_edge_count()
{
return Sta::sta()->ensureGraph()->edgeCount();
}
int int
graph_arc_count() graph_arc_count()
{ {

View File

@ -125,7 +125,7 @@ public:
virtual float delay() const { return 0.0; } virtual float delay() const { return 0.0; }
virtual const char *name() const { return nullptr; } virtual const char *name() const { return nullptr; }
virtual bool isDefault() const { return false; } virtual bool isDefault() const { return false; }
virtual bool ignoreClkLatency() { return false; } virtual bool ignoreClkLatency() const { return false; }
protected: protected:
virtual const char *typeString() const = 0; virtual const char *typeString() const = 0;
@ -210,7 +210,7 @@ public:
virtual float delay() const { return delay_; } virtual float delay() const { return delay_; }
virtual int typePriority() const; virtual int typePriority() const;
virtual bool tighterThan(ExceptionPath *exception) const; virtual bool tighterThan(ExceptionPath *exception) const;
virtual bool ignoreClkLatency() { return ignore_clk_latency_; } virtual bool ignoreClkLatency() const { return ignore_clk_latency_; }
protected: protected:
bool ignore_clk_latency_; bool ignore_clk_latency_;

View File

@ -116,8 +116,6 @@ public:
Required *requireds(Vertex *vertex); Required *requireds(Vertex *vertex);
void deleteRequireds(Vertex *vertex, void deleteRequireds(Vertex *vertex,
uint32_t count); uint32_t count);
size_t arrivalCount() const { return arrivals_.size(); }
size_t requiredCount() const { return requireds_.size(); }
PathVertexRep *makePrevPaths(Vertex *vertex, PathVertexRep *makePrevPaths(Vertex *vertex,
uint32_t count); uint32_t count);
PathVertexRep *prevPaths(Vertex *vertex) const; PathVertexRep *prevPaths(Vertex *vertex) const;
@ -217,8 +215,8 @@ public:
void removeDelaySlewAnnotations(); void removeDelaySlewAnnotations();
VertexSet *regClkVertices() { return reg_clk_vertices_; } VertexSet *regClkVertices() { return reg_clk_vertices_; }
static const int vertex_level_bits = 24; static constexpr int vertex_level_bits = 24;
static const int vertex_level_max = (1<<vertex_level_bits)-1; static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
protected: protected:
void makeVerticesAndEdges(); void makeVerticesAndEdges();

View File

@ -62,9 +62,9 @@ typedef vector<Slew> SlewSeq;
static constexpr int level_max = std::numeric_limits<Level>::max(); static constexpr int level_max = std::numeric_limits<Level>::max();
// 16,777,215 tags // 16,777,215 tags
static const int tag_group_index_bits = 24; static constexpr int tag_group_index_bits = 24;
static const TagGroupIndex tag_group_index_max = (1<<tag_group_index_bits)-1; static constexpr TagGroupIndex tag_group_index_max = (1<<tag_group_index_bits)-1;
static const int slew_annotated_bits = MinMax::index_count * RiseFall::index_count; static constexpr int slew_annotated_bits = MinMax::index_count * RiseFall::index_count;
// Bit shifts used to mark vertices in a Bfs queue. // Bit shifts used to mark vertices in a Bfs queue.
enum class BfsIndex { dcalc, arrival, required, other, bits }; enum class BfsIndex { dcalc, arrival, required, other, bits };

View File

@ -144,13 +144,13 @@ protected:
void seedNoDrvrSlew(Vertex *drvr_vertex, void seedNoDrvrSlew(Vertex *drvr_vertex,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
void seedNoDrvrCellSlew(Vertex *drvr_vertex, void seedNoDrvrCellSlew(Vertex *drvr_vertex,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
InputDrive *drive, const InputDrive *drive,
DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
void seedLoadSlew(Vertex *vertex); void seedLoadSlew(Vertex *vertex);
void setInputPortWireDelays(Vertex *vertex); void setInputPortWireDelays(Vertex *vertex);

View File

@ -51,10 +51,10 @@ public:
void driveResistance(const RiseFall *rf, void driveResistance(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
float &res, float &res,
bool &exists); bool &exists) const;
bool hasDriveResistance(const RiseFall *rf, bool hasDriveResistance(const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max) const;
bool driveResistanceMinMaxEqual(const RiseFall *rf); bool driveResistanceMinMaxEqual(const RiseFall *rf) const;
void setDriveCell(const LibertyLibrary *library, void setDriveCell(const LibertyLibrary *library,
const LibertyCell *cell, const LibertyCell *cell,
const LibertyPort *from_port, const LibertyPort *from_port,
@ -68,18 +68,18 @@ public:
const LibertyCell *&cell, const LibertyCell *&cell,
const LibertyPort *&from_port, const LibertyPort *&from_port,
float *&from_slews, float *&from_slews,
const LibertyPort *&to_port); const LibertyPort *&to_port) const;
InputDriveCell *driveCell(const RiseFall *rf, InputDriveCell *driveCell(const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max) const;
bool hasDriveCell(const RiseFall *rf, bool hasDriveCell(const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max) const;
// True if rise/fall/min/max drive cells are equal. // True if rise/fall/min/max drive cells are equal.
bool driveCellsEqual(); bool driveCellsEqual() const;
void slew(const RiseFall *rf, void slew(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
float &slew, float &slew,
bool &exists); bool &exists) const;
RiseFallMinMax *slews() { return &slews_; } const RiseFallMinMax *slews() const { return &slews_; }
private: private:
RiseFallMinMax slews_; RiseFallMinMax slews_;

View File

@ -85,8 +85,8 @@ public:
const RiseFall *transition(const StaState *sta) const; const RiseFall *transition(const StaState *sta) const;
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
PathAPIndex pathIndex(const StaState *sta) const; PathAPIndex pathIndex(const StaState *sta) const;
virtual void reportShort(ReportPath *report) const = 0; virtual void reportShort(const ReportPath *report) const = 0;
virtual void reportFull(ReportPath *report) const = 0; virtual void reportFull(const ReportPath *report) const = 0;
// Predicates for PathEnd type. // Predicates for PathEnd type.
// Default methods overridden by respective types. // Default methods overridden by respective types.
@ -228,8 +228,8 @@ public:
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isUnconstrained() const; virtual bool isUnconstrained() const;
virtual Required requiredTime(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const;
virtual Required requiredTimeOffset(const StaState *sta) const; virtual Required requiredTimeOffset(const StaState *sta) const;
@ -327,8 +327,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isCheck() const { return true; } virtual bool isCheck() const { return true; }
virtual ArcDelay margin(const StaState *sta) const; virtual ArcDelay margin(const StaState *sta) const;
virtual float macroClkTreeDelay(const StaState *sta) const; virtual float macroClkTreeDelay(const StaState *sta) const;
@ -373,8 +373,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
PathVertex *latchDisable(); PathVertex *latchDisable();
const PathVertex *latchDisable() const; const PathVertex *latchDisable() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
virtual Required requiredTime(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const;
virtual Arrival borrow(const StaState *sta) const; virtual Arrival borrow(const StaState *sta) const;
@ -432,8 +432,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isOutputDelay() const { return true; } virtual bool isOutputDelay() const { return true; }
virtual ArcDelay margin(const StaState *sta) const; virtual ArcDelay margin(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
@ -478,8 +478,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isGatedClock() const { return true; } virtual bool isGatedClock() const { return true; }
virtual ArcDelay margin(const StaState *) const { return margin_; } virtual ArcDelay margin(const StaState *) const { return margin_; }
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
@ -510,8 +510,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isDataCheck() const { return true; } virtual bool isDataCheck() const { return true; }
virtual const ClockEdge *targetClkEdge(const StaState *sta) const; virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
@ -566,8 +566,8 @@ public:
virtual PathEnd *copy(); virtual PathEnd *copy();
virtual Type type() const; virtual Type type() const;
virtual const char *typeName() const; virtual const char *typeName() const;
virtual void reportShort(ReportPath *report) const; virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(ReportPath *report) const; virtual void reportFull(const ReportPath *report) const;
virtual bool isPathDelay() const { return true; } virtual bool isPathDelay() const { return true; }
virtual TimingRole *checkRole(const StaState *sta) const; virtual TimingRole *checkRole(const StaState *sta) const;
virtual bool pathDelayMarginIsExternal() const; virtual bool pathDelayMarginIsExternal() const;

View File

@ -49,20 +49,20 @@ public:
// path(0) is the startpoint. // path(0) is the startpoint.
// path(size()-1) is the endpoint. // path(size()-1) is the endpoint.
const PathRef *path(size_t index) const; const PathRef *path(size_t index) const;
TimingArc *prevArc(size_t index); TimingArc *prevArc(size_t index) const;
// Returns the path start point. // Returns the path start point.
// Register/Latch Q pin // Register/Latch Q pin
// Input pin // Input pin
PathRef *startPath(); const PathRef *startPath() const;
PathRef *startPrevPath(); const PathRef *startPrevPath() const;
PathRef *endPath(); const PathRef *endPath() const;
TimingArc *startPrevArc(); TimingArc *startPrevArc() const;
size_t startIndex() const; size_t startIndex() const;
void clkPath(PathRef &clk_path); void clkPath(PathRef &clk_path) const;
void latchPaths(// Return values. void latchPaths(// Return values.
PathRef *&d_path, const PathRef *&d_path,
PathRef *&q_path, const PathRef *&q_path,
Edge *&d_q_edge); Edge *&d_q_edge) const;
protected: protected:
void expandGenclk(PathRef *clk_path); void expandGenclk(PathRef *clk_path);

View File

@ -341,9 +341,9 @@ public:
Arrival insertion, Arrival insertion,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
// Timing derated arc delay for a path analysis point. // Timing derated arc delay for a path analysis point.
ArcDelay deratedDelay(Vertex *from_vertex, ArcDelay deratedDelay(const Vertex *from_vertex,
TimingArc *arc, const TimingArc *arc,
Edge *edge, const Edge *edge,
bool is_clk, bool is_clk,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
@ -501,9 +501,9 @@ protected:
void findArrivalsSeed(); void findArrivalsSeed();
void seedFilterStarts(); void seedFilterStarts();
bool hasEnabledChecks(Vertex *vertex) const; bool hasEnabledChecks(Vertex *vertex) const;
virtual float timingDerate(Vertex *from_vertex, virtual float timingDerate(const Vertex *from_vertex,
TimingArc *arc, const TimingArc *arc,
Edge *edge, const Edge *edge,
bool is_clk, bool is_clk,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
void deletePaths(); void deletePaths();

View File

@ -922,7 +922,7 @@ public:
void reportPathEnd(PathEnd *end); void reportPathEnd(PathEnd *end);
void reportPathEnds(PathEndSeq *ends); void reportPathEnds(PathEndSeq *ends);
ReportPath *reportPath() { return report_path_; } ReportPath *reportPath() { return report_path_; }
void reportPath(Path *path); void reportPath(const Path *path);
// Report clk skews for clks. // Report clk skews for clks.
void reportClkSkew(ConstClockSeq &clks, void reportClkSkew(ConstClockSeq &clks,

View File

@ -1,5 +1,4 @@
%{ %{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -29,31 +28,31 @@
#include "util/FlexDisableRegister.hh" #include "util/FlexDisableRegister.hh"
#include "Debug.hh" #include "Debug.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "liberty/LibertyExprPvt.hh" #include "liberty/LibExprReaderPvt.hh"
#include "liberty/LibExprReader.hh"
#include "liberty/LibExprScanner.hh"
using sta::libexpr_parser;
using sta::stringCopy; using sta::stringCopy;
using sta::FuncExpr; using sta::FuncExpr;
#include "LibertyExprParse.hh" #include "LibExprParse.hh"
#define YY_NO_INPUT #undef YY_DECL
#define YY_DECL \
int \
sta::LibExprScanner::lex(sta::LibExprParse::semantic_type *const yylval)
#define YY_INPUT(buf,result,max_size) \ typedef sta::LibExprParse::token token;
result = libexpr_parser->copyInput(buf, max_size)
void
libertyExprFlushBuffer()
{
YY_FLUSH_BUFFER;
}
%} %}
/* %option debug */ %option c++
%option yyclass="sta::LibExprScanner"
%option prefix="LibExpr"
%option noyywrap %option noyywrap
%option nounput
%option never-interactive %option never-interactive
%option stack
/* %option debug */
%x ESCAPED_STRING %x ESCAPED_STRING
@ -67,28 +66,28 @@ EOL \r?\n
%% %%
{OP}|{PAREN} { return ((int) LibertyExprLex_text[0]); } {OP}|{PAREN} { return ((int) yytext[0]); }
{ESCAPE}{EOL} { /* I doubt that escaped returns get thru the parser */ } {ESCAPE}{EOL} { /* I doubt that escaped returns get thru the parser */ }
{ESCAPE}{QUOTE} { BEGIN(ESCAPED_STRING); libexpr_parser->tokenErase(); } {ESCAPE}{QUOTE} { BEGIN(ESCAPED_STRING); token_.clear(); }
<ESCAPED_STRING>. { libexpr_parser->tokenAppend(LibertyExprLex_text[0]); } <ESCAPED_STRING>. { token_ += yytext[0]; }
<ESCAPED_STRING>{ESCAPE}{QUOTE} { <ESCAPED_STRING>{ESCAPE}{QUOTE} {
BEGIN(INITIAL); BEGIN(INITIAL);
LibertyExprParse_lval.string = libexpr_parser->tokenCopy(); yylval->string = stringCopy(token_.c_str());
return PORT; return token::PORT;
} }
{PORT} { {PORT} {
LibertyExprParse_lval.string = stringCopy(LibertyExprLex_text); yylval->string = stringCopy(yytext);
return PORT; return token::PORT;
} }
{BLANK} {} {BLANK} {}
/* Send out of bound characters to parser. */ /* Send out of bound characters to parser. */
. { return (int) LibertyExprLex_text[0]; } . { return (int) yytext[0]; }
%% %%

View File

@ -1,5 +1,3 @@
%{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -26,15 +24,35 @@
// Liberty function expression parser. // Liberty function expression parser.
%{
#include "FuncExpr.hh" #include "FuncExpr.hh"
#include "liberty/LibertyExpr.hh" #include "liberty/LibExprReader.hh"
#include "liberty/LibertyExprPvt.hh" #include "liberty/LibExprReaderPvt.hh"
#include "liberty/LibExprScanner.hh"
int LibertyExprLex_lex(); #undef yylex
#define LibertyExprParse_lex LibertyExprLex_lex #define yylex scanner->lex
// warning: variable 'yynerrs_' set but not used
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
void
sta::LibExprParse::error(const string &msg)
{
reader->parseError(msg.c_str());
}
%} %}
%require "3.2"
%skeleton "lalr1.cc"
%debug
%define api.namespace {sta}
%define parse.assert
%parse-param{LibExprScanner *scanner}
%parse-param{LibExprReader *reader}
%define api.parser.class {LibExprParse}
%union { %union {
int int_val; int int_val;
const char *string; const char *string;
@ -50,18 +68,15 @@ int LibertyExprLex_lex();
%type <string> PORT %type <string> PORT
%type <expr> expr terminal terminal_expr implicit_and %type <expr> expr terminal terminal_expr implicit_and
%{
%}
%% %%
result_expr: result_expr:
expr { sta::libexpr_parser->setResult($1); } expr { reader->setResult($1); }
| expr ';'{ sta::libexpr_parser->setResult($1); } | expr ';'{ reader->setResult($1); }
; ;
terminal: terminal:
PORT { $$ = sta::libexpr_parser->makeFuncExprPort($1); } PORT { $$ = reader->makeFuncExprPort($1); }
| '0' { $$ = sta::FuncExpr::makeZero(); } | '0' { $$ = sta::FuncExpr::makeZero(); }
| '1' { $$ = sta::FuncExpr::makeOne(); } | '1' { $$ = sta::FuncExpr::makeOne(); }
| '(' expr ')' { $$ = $2; } | '(' expr ')' { $$ = $2; }
@ -69,25 +84,25 @@ terminal:
terminal_expr: terminal_expr:
terminal terminal
| '!' terminal { $$ = sta::libexpr_parser->makeFuncExprNot($2); } | '!' terminal { $$ = reader->makeFuncExprNot($2); }
| terminal '\'' { $$ = sta::libexpr_parser->makeFuncExprNot($1); } | terminal '\'' { $$ = reader->makeFuncExprNot($1); }
; ;
implicit_and: implicit_and:
terminal_expr terminal_expr terminal_expr terminal_expr
{ $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); } { $$ = reader->makeFuncExprAnd($1, $2); }
| implicit_and terminal_expr | implicit_and terminal_expr
{ $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); } { $$ = reader->makeFuncExprAnd($1, $2); }
; ;
expr: expr:
terminal_expr terminal_expr
| implicit_and | implicit_and
| expr '+' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); } | expr '+' expr { $$ = reader->makeFuncExprOr($1, $3); }
| expr '|' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); } | expr '|' expr { $$ = reader->makeFuncExprOr($1, $3); }
| expr '*' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); } | expr '*' expr { $$ = reader->makeFuncExprAnd($1, $3); }
| expr '&' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); } | expr '&' expr { $$ = reader->makeFuncExprAnd($1, $3); }
| expr '^' expr { $$ = sta::libexpr_parser->makeFuncExprXor($1, $3); } | expr '^' expr { $$ = reader->makeFuncExprXor($1, $3); }
; ;
%% %%

View File

@ -24,19 +24,17 @@
#include "FuncExpr.hh" #include "FuncExpr.hh"
#include <algorithm> // min #include <iostream>
#include <sstream>
#include "Report.hh" #include "Report.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "LibertyExprPvt.hh" #include "LibExprReaderPvt.hh"
#include "LibExprScanner.hh"
extern int
LibertyExprParse_parse();
namespace sta { namespace sta {
LibExprParser *libexpr_parser;
FuncExpr * FuncExpr *
parseFuncExpr(const char *func, parseFuncExpr(const char *func,
LibertyCell *cell, LibertyCell *cell,
@ -44,18 +42,20 @@ parseFuncExpr(const char *func,
Report *report) Report *report)
{ {
if (func != nullptr && func[0] != '\0') { if (func != nullptr && func[0] != '\0') {
LibExprParser parser(func, cell, error_msg, report); string func1(func);
libexpr_parser = &parser; std::istringstream stream(func);
LibertyExprParse_parse(); LibExprReader reader(func, cell, error_msg, report);
FuncExpr *expr = parser.result(); LibExprScanner scanner(stream);
libexpr_parser = nullptr; LibExprParse parser(&scanner, &reader);
parser.parse();
FuncExpr *expr = reader.result();
return expr; return expr;
} }
else else
return nullptr; return nullptr;
} }
LibExprParser::LibExprParser(const char *func, LibExprReader::LibExprReader(const char *func,
LibertyCell *cell, LibertyCell *cell,
const char *error_msg, const char *error_msg,
Report *report) : Report *report) :
@ -63,24 +63,17 @@ LibExprParser::LibExprParser(const char *func,
cell_(cell), cell_(cell),
error_msg_(error_msg), error_msg_(error_msg),
report_(report), report_(report),
result_(nullptr), result_(nullptr)
token_length_(100),
token_(new char[token_length_]),
token_next_(token_)
{ {
} }
LibExprParser::~LibExprParser() // defined in LibertyReader.cc
{
stringDelete(token_);
}
LibertyPort * LibertyPort *
libertyReaderFindPort(LibertyCell *cell, libertyReaderFindPort(LibertyCell *cell,
const char *port_name); const char *port_name);
FuncExpr * FuncExpr *
LibExprParser::makeFuncExprPort(const char *port_name) LibExprReader::makeFuncExprPort(const char *port_name)
{ {
FuncExpr *expr = nullptr; FuncExpr *expr = nullptr;
LibertyPort *port = libertyReaderFindPort(cell_, port_name); LibertyPort *port = libertyReaderFindPort(cell_, port_name);
@ -94,7 +87,7 @@ LibExprParser::makeFuncExprPort(const char *port_name)
} }
FuncExpr * FuncExpr *
LibExprParser::makeFuncExprNot(FuncExpr *arg) LibExprReader::makeFuncExprNot(FuncExpr *arg)
{ {
if (arg) if (arg)
return FuncExpr::makeNot(arg); return FuncExpr::makeNot(arg);
@ -103,7 +96,7 @@ LibExprParser::makeFuncExprNot(FuncExpr *arg)
} }
FuncExpr * FuncExpr *
LibExprParser::makeFuncExprXor(FuncExpr *arg1, LibExprReader::makeFuncExprXor(FuncExpr *arg1,
FuncExpr *arg2) FuncExpr *arg2)
{ {
if (arg1 && arg2) if (arg1 && arg2)
@ -113,7 +106,7 @@ LibExprParser::makeFuncExprXor(FuncExpr *arg1,
} }
FuncExpr * FuncExpr *
LibExprParser::makeFuncExprAnd(FuncExpr *arg1, LibExprReader::makeFuncExprAnd(FuncExpr *arg1,
FuncExpr *arg2) FuncExpr *arg2)
{ {
if (arg1 && arg2) if (arg1 && arg2)
@ -123,7 +116,7 @@ LibExprParser::makeFuncExprAnd(FuncExpr *arg1,
} }
FuncExpr * FuncExpr *
LibExprParser::makeFuncExprOr(FuncExpr *arg1, LibExprReader::makeFuncExprOr(FuncExpr *arg1,
FuncExpr *arg2) FuncExpr *arg2)
{ {
if (arg1 && arg2) if (arg1 && arg2)
@ -133,65 +126,22 @@ LibExprParser::makeFuncExprOr(FuncExpr *arg1,
} }
void void
LibExprParser::setResult(FuncExpr *result) LibExprReader::setResult(FuncExpr *result)
{ {
result_ = result; result_ = result;
} }
size_t
LibExprParser::copyInput(char *buf,
size_t max_size)
{
strncpy(buf, func_, max_size);
int count = strlen(buf);
func_ += count;
return count;
}
char *
LibExprParser::tokenCopy()
{
return stringCopy(token_);
}
void void
LibExprParser::tokenErase() LibExprReader::parseError(const char *msg)
{
token_next_ = token_;
}
void
LibExprParser::tokenAppend(char ch)
{
if (token_next_ + 1 - token_ >= static_cast<signed int>(token_length_)) {
size_t index = token_next_ - token_;
token_length_ *= 2;
char *prev_token = token_;
token_ = new char[token_length_];
strcpy(token_, prev_token);
stringDelete(prev_token);
token_next_ = &token_[index];
}
*token_next_++ = ch;
// Make sure the token is always terminated.
*token_next_ = '\0';
}
void
LibExprParser::parseError(const char *msg)
{ {
report_->error(1131, "%s %s.", error_msg_, msg); report_->error(1131, "%s %s.", error_msg_, msg);
} }
} // namespace
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Global namespace
int LibExprScanner::LibExprScanner(std::istringstream &stream) :
LibertyExprParse_error(const char *msg) yyFlexLexer(&stream)
{ {
libertyExprFlushBuffer();
sta::libexpr_parser->parseError(msg);
return 0;
} }
} // namespace

View File

@ -29,15 +29,15 @@ namespace sta {
class Report; class Report;
class LibertyCell; class LibertyCell;
class FuncExpr; class FuncExpr;
class LibExprScanner;
class LibExprParser class LibExprReader
{ {
public: public:
LibExprParser(const char *func, LibExprReader(const char *func,
LibertyCell *cell, LibertyCell *cell,
const char *error_msg, const char *error_msg,
Report *report); Report *report);
~LibExprParser();
FuncExpr *makeFuncExprPort(const char *port_name); FuncExpr *makeFuncExprPort(const char *port_name);
FuncExpr *makeFuncExprOr(FuncExpr *arg1, FuncExpr *makeFuncExprOr(FuncExpr *arg1,
FuncExpr *arg2); FuncExpr *arg2);
@ -51,11 +51,7 @@ public:
void parseError(const char *msg); void parseError(const char *msg);
size_t copyInput(char *buf, size_t copyInput(char *buf,
size_t max_size); size_t max_size);
void tokenStart(); Report *report() const { return report_; }
const char *token();
char *tokenCopy();
void tokenErase();
void tokenAppend(char ch);
private: private:
const char *func_; const char *func_;
@ -63,18 +59,6 @@ private:
const char *error_msg_; const char *error_msg_;
Report *report_; Report *report_;
FuncExpr *result_; FuncExpr *result_;
size_t token_length_;
char *token_;
char *token_next_;
}; };
extern LibExprParser *libexpr_parser;
} // namespace } // namespace
// Global namespace
void
libertyExprFlushBuffer();
int
LibertyExprParse_error(const char *msg);

62
liberty/LibExprScanner.hh Normal file
View File

@ -0,0 +1,62 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include <string>
#include "LibExprParse.hh"
#ifndef __FLEX_LEXER_H
#undef yyFlexLexer
#define yyFlexLexer LibExprFlexLexer
#include <FlexLexer.h>
#endif
namespace sta {
using std::string;
class Report;
class LibExprParse;
class LibExprScanner : public LibExprFlexLexer
{
public:
LibExprScanner(std::istringstream &stream);
virtual ~LibExprScanner() {}
virtual int lex(LibExprParse::semantic_type *const yylval);
// YY_DECL defined in LibertyLex.ll
// Method body created by flex in LibertyLex.cc
// Get rid of override virtual function warning.
using FlexLexer::yylex;
private:
Report *report_;
string token_;
};
} // namespace

View File

@ -25,7 +25,7 @@
%{ %{
#include <cstdlib> #include <cstdlib>
#include "StringUtil.hh" #include "Report.hh"
#include "liberty/LibertyParser.hh" #include "liberty/LibertyParser.hh"
#include "liberty/LibertyScanner.hh" #include "liberty/LibertyScanner.hh"
@ -36,6 +36,15 @@
#pragma GCC diagnostic ignored "-Wunused-but-set-variable" #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#define loc_line(loc) loc.begin.line #define loc_line(loc) loc.begin.line
void
sta::LibertyParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164, reader->filename().c_str(),
loc.begin.line, "%s", msg.c_str());
}
%} %}
%require "3.2" %require "3.2"
@ -47,11 +56,7 @@
%define parse.assert %define parse.assert
%parse-param { LibertyScanner *scanner } %parse-param { LibertyScanner *scanner }
%parse-param { LibertyParser *reader } %parse-param { LibertyParser *reader }
%define api.parser.class {LibertyParse}
// bison 3.0.4 for centos7
%define parser_class_name {LibertyParse}
// bison 3.3.2
//%define api.parser.class {LibertyParse}
%expect 2 %expect 2

View File

@ -41,18 +41,15 @@ parseLibertyFile(const char *filename,
LibertyGroupVisitor *library_visitor, LibertyGroupVisitor *library_visitor,
Report *report) Report *report)
{ {
std::istream *stream = new gzstream::igzstream(filename); gzstream::igzstream stream(filename);
if (stream->good()) { if (stream.is_open()) {
LibertyParser reader(filename, library_visitor, report); LibertyParser reader(filename, library_visitor, report);
LibertyScanner scanner(stream, filename, &reader, report); LibertyScanner scanner(&stream, filename, &reader, report);
LibertyParse parser(&scanner, &reader); LibertyParse parser(&scanner, &reader);
parser.parse(); parser.parse();
delete stream;
} }
else { else
delete stream;
throw FileNotReadable(filename); throw FileNotReadable(filename);
}
} }
LibertyParser::LibertyParser(const char *filename, LibertyParser::LibertyParser(const char *filename,
@ -567,12 +564,4 @@ LibertyScanner::error(const char *msg)
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
} }
void
LibertyParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164, reader->filename().c_str(),
loc.begin.line, "%s", msg.c_str());
}
} // namespace } // namespace

View File

@ -41,7 +41,7 @@
#include "LinearModel.hh" #include "LinearModel.hh"
#include "Wireload.hh" #include "Wireload.hh"
#include "EquivCells.hh" #include "EquivCells.hh"
#include "LibertyExpr.hh" #include "LibExprReader.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "LibertyBuilder.hh" #include "LibertyBuilder.hh"
#include "LibertyReaderPvt.hh" #include "LibertyReaderPvt.hh"

View File

@ -31,15 +31,17 @@
#include "Map.hh" #include "Map.hh"
#include "StringSeq.hh" #include "StringSeq.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "NetworkClass.hh"
#include "Transition.hh" #include "Transition.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "InternalPower.hh" #include "InternalPower.hh"
#include "LeakagePower.hh" #include "LeakagePower.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "Sequential.hh" #include "Sequential.hh"
#include "TableModel.hh"
#include "LibertyParser.hh" #include "LibertyParser.hh"
#include "LibertyReader.hh" #include "LibertyReader.hh"
#include "NetworkClass.hh" #include "LibertyBuilder.hh"
namespace sta { namespace sta {
@ -494,6 +496,8 @@ public:
void endCcsn(LibertyGroup *group); void endCcsn(LibertyGroup *group);
void beginEcsmWaveform(LibertyGroup *group); void beginEcsmWaveform(LibertyGroup *group);
void endEcsmWaveform(LibertyGroup *group); void endEcsmWaveform(LibertyGroup *group);
LibertyPort *findPort(LibertyCell *cell,
const char *port_name);
protected: protected:
TimingModel *makeScalarCheckModel(float value, TimingModel *makeScalarCheckModel(float value,
@ -519,8 +523,6 @@ protected:
StdStringSeq parseTokenList(const char *token_str, StdStringSeq parseTokenList(const char *token_str,
const char separator); const char separator);
LibertyPort *findPort(const char *port_name); LibertyPort *findPort(const char *port_name);
LibertyPort *findPort(LibertyCell *cell,
const char *port_name);
float defaultCap(LibertyPort *port); float defaultCap(LibertyPort *port);
virtual void visitVariable(LibertyVariable *var); virtual void visitVariable(LibertyVariable *var);
void visitPorts(std::function<void (LibertyPort *port)> func); void visitPorts(std::function<void (LibertyPort *port)> func);

View File

@ -24,15 +24,15 @@
#pragma once #pragma once
#include "LibertyLocation.hh"
#include "LibertyParse.hh"
#ifndef __FLEX_LEXER_H #ifndef __FLEX_LEXER_H
#undef yyFlexLexer #undef yyFlexLexer
#define yyFlexLexer LibertyFlexLexer #define yyFlexLexer LibertyFlexLexer
#include <FlexLexer.h> #include <FlexLexer.h>
#endif #endif
#include "LibertyLocation.hh"
#include "LibertyParse.hh"
namespace sta { namespace sta {
class Report; class Report;

View File

@ -1,5 +1,4 @@
%{ %{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -31,30 +30,28 @@
#include "StringUtil.hh" #include "StringUtil.hh"
#include "parasitics/SpefReaderPvt.hh" #include "parasitics/SpefReaderPvt.hh"
#include "SpefParse.hh" #include "SpefParse.hh"
#include "parasitics/SpefScanner.hh"
#define YY_NO_INPUT #undef YY_DECL
#define YY_DECL \
int \
sta::SpefScanner::lex(sta::SpefParse::semantic_type *const yylval, \
sta::SpefParse::location_type *loc)
static std::string spef_token; // update location on matching
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
void
spefFlushBuffer()
{
YY_FLUSH_BUFFER;
}
// Reset the start condition to INITIAL.
void
spefResetScanner()
{
BEGIN(0);
}
typedef sta::SpefParse::token token;
%} %}
/* %option debug */ %option c++
%option yyclass="sta::SpefScanner"
%option prefix="Spef"
%option noyywrap %option noyywrap
%option nounput
%option never-interactive %option never-interactive
%option stack
%option yylineno
/* %option debug */
%x COMMENT %x COMMENT
%x QUOTE %x QUOTE
@ -93,123 +90,117 @@ INDEX "*"{POS_INTEGER}
%% %%
"*BUS_DELIMITER" { return BUS_DELIMITER; } "*BUS_DELIMITER" { return token::BUS_DELIMITER; }
"*C2_R1_C1" { return C2_R1_C1; } "*C2_R1_C1" { return token::C2_R1_C1; }
"*C" { return KW_C; } "*C" { return token::KW_C; }
"*CAP" { return CAP; } "*CAP" { return token::CAP; }
"*CELL" { return CELL; } "*CELL" { return token::CELL; }
"*CONN" { return CONN; } "*CONN" { return token::CONN; }
"*C_UNIT" { return C_UNIT; } "*C_UNIT" { return token::C_UNIT; }
"*SPEF" { return SPEF; } "*SPEF" { return token::SPEF; }
"*DATE" { return DATE; } "*DATE" { return token::DATE; }
"*DEFINE" { return DEFINE; } "*DEFINE" { return token::DEFINE; }
"*DELIMITER" { return DELIMITER; } "*DELIMITER" { return token::DELIMITER; }
"*DESIGN" { return DESIGN; } "*DESIGN" { return token::DESIGN; }
"*DESIGN_FLOW" { return DESIGN_FLOW; } "*DESIGN_FLOW" { return token::DESIGN_FLOW; }
"*DIVIDER" { return DIVIDER; } "*DIVIDER" { return token::DIVIDER; }
"*DRIVER" { return DRIVER; } "*DRIVER" { return token::DRIVER; }
"*D_NET" { return D_NET; } "*D_NET" { return token::D_NET; }
"*D_PNET" { return D_PNET; } "*D_PNET" { return token::D_PNET; }
"*D" { return KW_D; } "*D" { return token::KW_D; }
"*END" { return END; } "*END" { return token::END; }
"*GROUND_NETS" { return GROUND_NETS; } "*GROUND_NETS" { return token::GROUND_NETS; }
"*INDUC" { return INDUC; } "*INDUC" { return token::INDUC; }
"*I" { return KW_I; } "*I" { return token::KW_I; }
"*K" { return KW_K; } "*K" { return token::KW_K; }
"*L" { return KW_L; } "*L" { return token::KW_L; }
"*LOADS" { return LOADS; } "*LOADS" { return token::LOADS; }
"*L_UNIT" { return L_UNIT; } "*L_UNIT" { return token::L_UNIT; }
"*NAME_MAP" { return NAME_MAP; } "*NAME_MAP" { return token::NAME_MAP; }
"*N" { return KW_N; } "*N" { return token::KW_N; }
"*PDEFINE" { return PDEFINE; } "*PDEFINE" { return token::PDEFINE; }
"*PHYSICAL_PORTS" { return PHYSICAL_PORTS; } "*PHYSICAL_PORTS" { return token::PHYSICAL_PORTS; }
"*PORTS" { return PORTS; } "*PORTS" { return token::PORTS; }
"*POWER_NETS" { return POWER_NETS; } "*POWER_NETS" { return token::POWER_NETS; }
"*PROGRAM" { return PROGRAM; } "*PROGRAM" { return token::PROGRAM; }
"*P" { return KW_P; } "*P" { return token::KW_P; }
"*Q" { return KW_Q; } "*Q" { return token::KW_Q; }
"*RC" { return RC; } "*RC" { return token::RC; }
"*RES" { return RES; } "*RES" { return token::RES; }
"*R_NET" { return R_NET; } "*R_NET" { return token::R_NET; }
"*R_PNET" { return R_PNET; } "*R_PNET" { return token::R_PNET; }
"*R_UNIT" { return R_UNIT; } "*R_UNIT" { return token::R_UNIT; }
"*S" { return KW_S; } "*S" { return token::KW_S; }
"*T_UNIT" { return T_UNIT; } "*T_UNIT" { return token::T_UNIT; }
"*VENDOR" { return VENDOR; } "*VENDOR" { return token::VENDOR; }
"*VERSION" { return PVERSION; } "*VERSION" { return token::PVERSION; }
"*V" { return KW_V; } "*V" { return token::KW_V; }
"//".*\n { /* Single line comment */ "//".*\n { loc->lines(); loc->step(); } /* Single line comment */
sta::spef_reader->incrLine();
}
"/*" { BEGIN COMMENT; } "/*" { BEGIN COMMENT; }
<COMMENT>{ <COMMENT>{
. .
\n { sta::spef_reader->incrLine(); } \n { loc->lines(); loc->step(); }
"*/" { BEGIN INITIAL; } "*/" { BEGIN INITIAL; }
<<EOF>> { <<EOF>> {
SpefParse_error("unterminated comment"); error("unterminated comment");
BEGIN(INITIAL); BEGIN(INITIAL);
yyterminate(); yyterminate();
} }
} }
"\"" { BEGIN QUOTE; spef_token.erase(); } "\"" { BEGIN QUOTE; token_.erase(); }
<QUOTE>{ <QUOTE>{
\r?\n { \r?\n { loc->lines(); loc->step(); }
sta::spef_reader->incrLine();
}
"\\". { spef_token += yytext[1]; } "\\". { token_ += yytext[1]; }
"\"" { "\"" {
BEGIN INITIAL; BEGIN INITIAL;
SpefParse_lval.string = sta::stringCopy(spef_token.c_str()); yylval->string = sta::stringCopy(token_.c_str());
return QSTRING; return token::QSTRING;
} }
. { spef_token += yytext[0]; } . { token_ += yytext[0]; }
<<EOF>> { <<EOF>> {
SpefParse_error("unterminated quoted string"); error("unterminated quoted string");
BEGIN(INITIAL); BEGIN(INITIAL);
yyterminate(); yyterminate();
} }
} }
{BLANK}*\n { {BLANK}*\n { loc->lines(); loc->step(); }
sta::spef_reader->incrLine();
}
{INTEGER} { {INTEGER} {
SpefParse_lval.integer = atoi(yytext); yylval->integer = atoi(yytext);
return INTEGER; return token::INTEGER;
} }
{FLOAT} { {FLOAT} {
SpefParse_lval.number = static_cast<float>(atof(yytext)); yylval->number = static_cast<float>(atof(yytext));
return FLOAT; return token::FLOAT;
} }
{IDENT} { {IDENT} {
SpefParse_lval.string = sta::spef_reader->translated(yytext); yylval->string = reader_->translated(yytext);
return IDENT; return token::IDENT;
} }
{PATH}|{NAME_PAIR} { {PATH}|{NAME_PAIR} {
SpefParse_lval.string = sta::spef_reader->translated(yytext); yylval->string = reader_->translated(yytext);
return NAME; return token::NAME;
} }
{INDEX} { {INDEX} {
SpefParse_lval.string = sta::stringCopy(yytext); yylval->string = sta::stringCopy(yytext);
return INDEX; return token::INDEX;
} }
{HCHAR} { {HCHAR} {

View File

@ -1,5 +1,3 @@
%{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -24,19 +22,41 @@
// //
// This notice may not be removed or altered from any source distribution. // This notice may not be removed or altered from any source distribution.
%{
#include <cstring> #include <cstring>
#include "Report.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "StringSeq.hh" #include "StringSeq.hh"
#include "parasitics/SpefReaderPvt.hh" #include "parasitics/SpefReaderPvt.hh"
#include "parasitics/SpefScanner.hh"
int SpefLex_lex(); #undef yylex
#define SpefParse_lex SpefLex_lex #define yylex scanner->lex
// use yacc generated parser errors
#define YYERROR_VERBOSE
// warning: variable 'yynerrs_' set but not used
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
void
sta::SpefParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164,reader->filename(),
loc.begin.line,"%s",msg.c_str());
}
%} %}
%require "3.2"
%skeleton "lalr1.cc"
%debug
%define api.namespace {sta}
%locations
%define api.location.file "SpefLocation.hh"
%define parse.assert
%parse-param { SpefScanner *scanner }
%parse-param { SpefReader *reader }
%define api.parser.class {SpefParse}
%union { %union {
char ch; char ch;
char *string; char *string;
@ -195,7 +215,7 @@ vendor:
design_flow: design_flow:
DESIGN_FLOW qstrings DESIGN_FLOW qstrings
{ sta::spef_reader->setDesignFlow($2); } { reader->setDesignFlow($2); }
; ;
qstrings: qstrings:
@ -209,19 +229,19 @@ qstrings:
hierarchy_div_def: hierarchy_div_def:
DIVIDER hchar DIVIDER hchar
{ sta::spef_reader->setDivider($2); } { reader->setDivider($2); }
; ;
pin_delim_def: pin_delim_def:
DELIMITER hchar DELIMITER hchar
{ sta::spef_reader->setDelimiter($2); } { reader->setDelimiter($2); }
; ;
bus_delim_def: bus_delim_def:
BUS_DELIMITER prefix_bus_delim BUS_DELIMITER prefix_bus_delim
{ sta::spef_reader->setBusBrackets($2, '\0'); } { reader->setBusBrackets($2, '\0'); }
| BUS_DELIMITER prefix_bus_delim suffix_bus_delim | BUS_DELIMITER prefix_bus_delim suffix_bus_delim
{ sta::spef_reader->setBusBrackets($2, $3); } { reader->setBusBrackets($2, $3); }
; ;
/****************************************************************/ /****************************************************************/
@ -235,22 +255,22 @@ unit_def:
time_scale: time_scale:
T_UNIT pos_number IDENT T_UNIT pos_number IDENT
{ sta::spef_reader->setTimeScale($2, $3); } { reader->setTimeScale($2, $3); }
; ;
cap_scale: cap_scale:
C_UNIT pos_number IDENT C_UNIT pos_number IDENT
{ sta::spef_reader->setCapScale($2, $3); } { reader->setCapScale($2, $3); }
; ;
res_scale: res_scale:
R_UNIT pos_number IDENT R_UNIT pos_number IDENT
{ sta::spef_reader->setResScale($2, $3); } { reader->setResScale($2, $3); }
; ;
induc_scale: induc_scale:
L_UNIT pos_number IDENT L_UNIT pos_number IDENT
{ sta::spef_reader->setInductScale($2, $3); } { reader->setInductScale($2, $3); }
; ;
/****************************************************************/ /****************************************************************/
@ -267,7 +287,7 @@ name_map_entries:
name_map_entry: name_map_entry:
INDEX mapped_item INDEX mapped_item
{ sta::spef_reader->makeNameMapEntry($1, $2); { reader->makeNameMapEntry($1, $2);
sta::stringDelete($1); sta::stringDelete($1);
} }
; ;
@ -330,7 +350,7 @@ port_entry:
direction: direction:
IDENT IDENT
{ $$ = sta::spef_reader->portDirection($1); { $$ = reader->portDirection($1);
sta::stringDelete($1); sta::stringDelete($1);
} }
; ;
@ -474,14 +494,14 @@ nets:
d_net: d_net:
D_NET net total_cap D_NET net total_cap
{ sta::spef_reader->dspfBegin($2, $3); } { reader->dspfBegin($2, $3); }
routing_conf conn_sec cap_sec res_sec induc_sec END routing_conf conn_sec cap_sec res_sec induc_sec END
{ sta::spef_reader->dspfFinish(); } { reader->dspfFinish(); }
; ;
net: net:
name_or_index name_or_index
{ $$ = sta::spef_reader->findNet($1); { $$ = reader->findNet($1);
sta::stringDelete($1); sta::stringDelete($1);
} }
; ;
@ -531,7 +551,7 @@ internal_connection:
pin_name: pin_name:
name_or_index name_or_index
{ $$ = sta::spef_reader->findPin($1); { $$ = reader->findPin($1);
sta::stringDelete($1); sta::stringDelete($1);
} }
; ;
@ -565,9 +585,9 @@ cap_elems:
cap_elem: cap_elem:
cap_id parasitic_node par_value cap_id parasitic_node par_value
{ sta::spef_reader->makeCapacitor($1, $2, $3); } { reader->makeCapacitor($1, $2, $3); }
| cap_id parasitic_node parasitic_node par_value | cap_id parasitic_node parasitic_node par_value
{ sta::spef_reader->makeCapacitor($1, $2, $3, $4); } { reader->makeCapacitor($1, $2, $3, $4); }
; ;
cap_id: cap_id:
@ -593,7 +613,7 @@ res_elems:
res_elem: res_elem:
res_id parasitic_node parasitic_node par_value res_id parasitic_node parasitic_node par_value
{ sta::spef_reader->makeResistor($1, $2, $3, $4); } { reader->makeResistor($1, $2, $3, $4); }
; ;
res_id: res_id:
@ -626,9 +646,9 @@ induc_id:
r_net: r_net:
R_NET net total_cap R_NET net total_cap
{ sta::spef_reader->rspfBegin($2, $3); } { reader->rspfBegin($2, $3); }
routing_conf driver_reducs END routing_conf driver_reducs END
{ sta::spef_reader->rspfFinish(); } { reader->rspfFinish(); }
; ;
driver_reducs: driver_reducs:
@ -638,11 +658,11 @@ driver_reducs:
driver_reduc: driver_reduc:
driver_pair driver_cell pi_model driver_pair driver_cell pi_model
{ sta::spef_reader->rspfDrvrBegin($1, $3); { reader->rspfDrvrBegin($1, $3);
sta::stringDelete($2); sta::stringDelete($2);
} }
load_desc load_desc
{ sta::spef_reader->rspfDrvrFinish(); } { reader->rspfDrvrFinish(); }
; ;
driver_pair: driver_pair:
@ -673,9 +693,9 @@ rc_descs:
rc_desc: rc_desc:
RC pin_name par_value RC pin_name par_value
{ sta::spef_reader->rspfLoad($2, $3); } { reader->rspfLoad($2, $3); }
| RC pin_name par_value pole_residue_desc | RC pin_name par_value pole_residue_desc
{ sta::spef_reader->rspfLoad($2, $3); } { reader->rspfLoad($2, $3); }
; ;
pole_residue_desc: pole_residue_desc:
@ -810,7 +830,7 @@ pos_integer:
INTEGER INTEGER
{ int value = $1; { int value = $1;
if (value < 0) if (value < 0)
sta::spef_reader->warn(1525, "%d is not positive.", value); reader->warn(1525, "%d is not positive.", value);
$$ = value; $$ = value;
} }
; ;
@ -819,13 +839,13 @@ pos_number:
INTEGER INTEGER
{ float value = static_cast<float>($1); { float value = static_cast<float>($1);
if (value < 0) if (value < 0)
sta::spef_reader->warn(1526, "%.4f is not positive.", value); reader->warn(1526, "%.4f is not positive.", value);
$$ = value; $$ = value;
} }
| FLOAT | FLOAT
{ float value = static_cast<float>($1); { float value = static_cast<float>($1);
if (value < 0) if (value < 0)
sta::spef_reader->warn(1527, "%.4f is not positive.", value); reader->warn(1527, "%.4f is not positive.", value);
$$ = value; $$ = value;
} }
; ;

View File

@ -40,17 +40,10 @@
#include "ArcDelayCalc.hh" #include "ArcDelayCalc.hh"
#include "SpefReaderPvt.hh" #include "SpefReaderPvt.hh"
#include "SpefNamespace.hh" #include "SpefNamespace.hh"
#include "parasitics/SpefScanner.hh"
int
SpefParse_parse();
void
spefResetScanner();
namespace sta { namespace sta {
// Referenced by parser.
SpefReader *spef_reader;
bool bool
readSpefFile(const char *filename, readSpefFile(const char *filename,
Instance *instance, Instance *instance,
@ -63,35 +56,14 @@ readSpefFile(const char *filename,
const MinMaxAll *min_max, const MinMaxAll *min_max,
StaState *sta) StaState *sta)
{ {
bool success = false; SpefReader reader(filename, instance, ap,
const ArcDelayCalc *arc_delay_calc = sta->arcDelayCalc(); pin_cap_included, keep_coupling_caps, coupling_cap_factor,
if (reduce && !arc_delay_calc->reduceSupported()) { reduce, corner, min_max, sta);
sta->report()->warn(1658, "Delay calculator %s does not support reduction.", bool success = reader.read();
arc_delay_calc->name());
reduce = false;
}
// Use zlib to uncompress gzip'd files automagically.
gzFile stream = gzopen(filename, "rb");
if (stream) {
Stats stats(sta->debug(), sta->report());
SpefReader reader(filename, stream, instance, ap,
pin_cap_included, keep_coupling_caps, coupling_cap_factor,
reduce, corner, min_max, sta);
spef_reader = &reader;
::spefResetScanner();
// yyparse returns 0 on success.
success = (::SpefParse_parse() == 0);
gzclose(stream);
spef_reader = nullptr;
stats.report("Read spef");
}
else
throw FileNotReadable(filename);
return success; return success;
} }
SpefReader::SpefReader(const char *filename, SpefReader::SpefReader(const char *filename,
gzFile stream,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool pin_cap_included, bool pin_cap_included,
@ -110,8 +82,6 @@ SpefReader::SpefReader(const char *filename,
reduce_(reduce), reduce_(reduce),
corner_(corner), corner_(corner),
min_max_(min_max), min_max_(min_max),
stream_(stream),
line_(1),
// defaults // defaults
divider_('\0'), divider_('\0'),
delimiter_('\0'), delimiter_('\0'),
@ -141,6 +111,25 @@ SpefReader::~SpefReader()
stringDelete(name); stringDelete(name);
} }
bool
SpefReader::read()
{
bool success;
gzstream::igzstream stream(filename_);
if (stream.is_open()) {
Stats stats(debug_, report_);
SpefScanner scanner(&stream, filename_, this, report_);
scanner_ = &scanner;
SpefParse parser(&scanner, this);
// yyparse returns 0 on success.
success = (parser.parse() == 0);
stats.report("Read spef");
}
else
throw FileNotReadable(filename_);
return success;
}
void void
SpefReader::setDivider(char divider) SpefReader::setDivider(char divider)
{ {
@ -154,7 +143,8 @@ SpefReader::setDelimiter(char delimiter)
} }
void void
SpefReader::setBusBrackets(char left, char right) SpefReader::setBusBrackets(char left,
char right)
{ {
if (!((left == '[' && right == ']') if (!((left == '[' && right == ']')
|| (left == '{' && right == '}') || (left == '{' && right == '}')
@ -196,30 +186,6 @@ SpefReader::findPortPinRelative(const char *name)
return network_->findPin(instance_, name); return network_->findPin(instance_, name);
} }
void
SpefReader::getChars(char *buf,
int &result,
size_t max_size)
{
char *status = gzgets(stream_, buf, max_size);
if (status == Z_NULL)
result = 0; // YY_nullptr
else
result = static_cast<int>(strlen(buf));
}
void
SpefReader::getChars(char *buf,
size_t &result,
size_t max_size)
{
char *status = gzgets(stream_, buf, max_size);
if (status == Z_NULL)
result = 0; // YY_nullptr
else
result = strlen(buf);
}
char * char *
SpefReader::translated(const char *token) SpefReader::translated(const char *token)
{ {
@ -227,18 +193,12 @@ SpefReader::translated(const char *token)
network_->pathEscape()); network_->pathEscape());
} }
void
SpefReader::incrLine()
{
line_++;
}
void void
SpefReader::warn(int id, const char *fmt, ...) SpefReader::warn(int id, const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
report_->vfileWarn(id, filename_, line_, fmt, args); report_->vfileWarn(id, filename_, scanner_->line(), fmt, args);
va_end(args); va_end(args);
} }
@ -644,17 +604,23 @@ SpefTriple::value(int index) const
return values_[0]; return values_[0];
} }
} // namespace
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Global namespace
void spefFlushBuffer(); SpefScanner::SpefScanner(std::istream *stream,
const string &filename,
int SpefReader *reader,
SpefParse_error(const char *msg) Report *report) :
yyFlexLexer(stream),
filename_(filename),
reader_(reader),
report_(report)
{ {
spefFlushBuffer();
sta::spef_reader->warn(1657, "%s.", msg);
return 0;
} }
void
SpefScanner::error(const char *msg)
{
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
}
} // namespace

View File

@ -32,15 +32,6 @@
#include "ParasiticsClass.hh" #include "ParasiticsClass.hh"
#include "StaState.hh" #include "StaState.hh"
// Global namespace.
#define YY_INPUT(buf,result,max_size) \
sta::spef_reader->getChars(buf, result, max_size)
int
SpefParse_error(const char *msg);
////////////////////////////////////////////////////////////////
namespace sta { namespace sta {
class Report; class Report;
@ -48,6 +39,7 @@ class MinMaxAll;
class SpefRspfPi; class SpefRspfPi;
class SpefTriple; class SpefTriple;
class Corner; class Corner;
class SpefScanner;
typedef std::map<int, char*, std::less<int>> SpefNameMap; typedef std::map<int, char*, std::less<int>> SpefNameMap;
@ -55,7 +47,6 @@ class SpefReader : public StaState
{ {
public: public:
SpefReader(const char *filename, SpefReader(const char *filename,
gzFile stream,
Instance *instance, Instance *instance,
ParasiticAnalysisPt *ap, ParasiticAnalysisPt *ap,
bool pin_cap_included, bool pin_cap_included,
@ -66,21 +57,12 @@ public:
const MinMaxAll *min_max, const MinMaxAll *min_max,
StaState *sta); StaState *sta);
virtual ~SpefReader(); virtual ~SpefReader();
bool read();
char divider() const { return divider_; } char divider() const { return divider_; }
void setDivider(char divider); void setDivider(char divider);
char delimiter() const { return delimiter_; } char delimiter() const { return delimiter_; }
void setDelimiter(char delimiter); void setDelimiter(char delimiter);
void incrLine();
int line() const { return line_; }
const char *filename() const { return filename_; } const char *filename() const { return filename_; }
// flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
// so provide both forms.
void getChars(char *buf,
int &result,
size_t max_size);
void getChars(char *buf,
size_t &result,
size_t max_size);
// Translate from spf/spef namespace to sta namespace. // Translate from spf/spef namespace to sta namespace.
char *translated(const char *token); char *translated(const char *token);
void warn(int id, void warn(int id,
@ -136,6 +118,7 @@ private:
bool local_only); bool local_only);
const char *filename_; const char *filename_;
SpefScanner *scanner_;
Instance *instance_; Instance *instance_;
const ParasiticAnalysisPt *ap_; const ParasiticAnalysisPt *ap_;
bool pin_cap_included_; bool pin_cap_included_;
@ -144,8 +127,6 @@ private:
const Corner *corner_; const Corner *corner_;
const MinMaxAll *min_max_; const MinMaxAll *min_max_;
// Normally no need to keep device names. // Normally no need to keep device names.
gzFile stream_;
int line_;
char divider_; char divider_;
char delimiter_; char delimiter_;
char bus_brkt_left_; char bus_brkt_left_;

67
parasitics/SpefScanner.hh Normal file
View File

@ -0,0 +1,67 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SpefLocation.hh"
#include "SpefParse.hh"
#ifndef __FLEX_LEXER_H
#undef yyFlexLexer
#define yyFlexLexer SpefFlexLexer
#include <FlexLexer.h>
#endif
namespace sta {
class Report;
class SpefScanner : public SpefFlexLexer
{
public:
SpefScanner(std::istream *stream,
const string &filename,
SpefReader *reader,
Report *report);
virtual ~SpefScanner() {}
virtual int lex(SpefParse::semantic_type *const yylval,
SpefParse::location_type *yylloc);
// YY_DECL defined in SpefLex.ll
// Method body created by flex in SpefLex.cc
void error(const char *msg);
int line() const { return yylineno; }
// Get rid of override virtual function warning.
using FlexLexer::yylex;
private:
string filename_;
SpefReader *reader_;
Report *report_;
string token_;
};
} // namespace

View File

@ -1,5 +1,4 @@
%{ %{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -30,23 +29,28 @@
#include "StringUtil.hh" #include "StringUtil.hh"
#include "power/SaifReaderPvt.hh" #include "power/SaifReaderPvt.hh"
#include "SaifParse.hh" #include "SaifParse.hh"
#include "power/SaifScanner.hh"
#define YY_NO_INPUT #undef YY_DECL
#define YY_DECL \
int \
sta::SaifScanner::lex(sta::SaifParse::semantic_type *const yylval, \
sta::SaifParse::location_type *loc)
static std::string saif_token; // update location on matching
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
void
saifFlushBuffer()
{
YY_FLUSH_BUFFER;
}
typedef sta::SaifParse::token token;
%} %}
/* %option debug */ %option c++
%option yyclass="sta::SaifScanner"
%option prefix="Saif"
%option noyywrap %option noyywrap
%option nounput
%option never-interactive %option never-interactive
%option stack
%option yylineno
/* %option debug */
%x COMMENT %x COMMENT
%x QUOTE %x QUOTE
@ -65,74 +69,74 @@ EOL \r?\n
"*/" { BEGIN INITIAL; } "*/" { BEGIN INITIAL; }
. .
{EOL} { sta::saif_reader->incrLine(); } {EOL} { loc->lines(); loc->step(); }
<<EOF>> { <<EOF>> {
SaifParse_error("unterminated comment"); error("unterminated comment");
BEGIN(INITIAL); BEGIN(INITIAL);
yyterminate(); yyterminate();
} }
} }
"\"" { BEGIN QUOTE; saif_token.erase(); } "\"" { BEGIN QUOTE; token_.clear(); }
<QUOTE>{ <QUOTE>{
"\\". { saif_token += yytext[1]; } "\\". { token_ += yytext[1]; }
"\"" { "\"" {
BEGIN INITIAL; BEGIN INITIAL;
SaifParse_lval.string = sta::stringCopy(saif_token.c_str()); yylval->string = sta::stringCopy(token_.c_str());
return QSTRING; return token::QSTRING;
} }
. { saif_token += yytext[0]; } . { token_ += yytext[0]; }
<<EOF>> { <<EOF>> {
SaifParse_error("unterminated quoted string"); error("unterminated quoted string");
BEGIN(INITIAL); BEGIN(INITIAL);
yyterminate(); yyterminate();
} }
} }
"//"[^\n]*{EOL} { sta::saif_reader->incrLine(); } "//"[^\n]*{EOL} { loc->lines(); loc->step(); }
[0-9]+ { [0-9]+ {
SaifParse_lval.uint = atoll(yytext); yylval->uint = atoll(yytext);
return UINT; return token::UINT;
} }
":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} { ":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} {
return ((int) yytext[0]); return ((int) yytext[0]);
} }
SAIFILE { return SAIFILE; } SAIFILE { return token::SAIFILE; }
SAIFVERSION { return SAIFVERSION; } SAIFVERSION { return token::SAIFVERSION; }
DIRECTION { return DIRECTION; } DIRECTION { return token::DIRECTION; }
DESIGN { return DESIGN; } DESIGN { return token::DESIGN; }
DATE { return DATE; } DATE { return token::DATE; }
VENDOR { return VENDOR; } VENDOR { return token::VENDOR; }
PROGRAM_NAME { return PROGRAM_NAME; } PROGRAM_NAME { return token::PROGRAM_NAME; }
VERSION { return VERSION; } VERSION { return token::VERSION; }
DIVIDER { return DIVIDER; } DIVIDER { return token::DIVIDER; }
TIMESCALE { return TIMESCALE; } TIMESCALE { return token::TIMESCALE; }
DURATION { return DURATION; } DURATION { return token::DURATION; }
INSTANCE { return INSTANCE; } INSTANCE { return token::INSTANCE; }
NET { return NET; } NET { return token::NET; }
PORT { return PORT; } PORT { return token::PORT; }
T0 { return T0; } T0 { return token::T0; }
T1 { return T1; } T1 { return token::T1; }
TX { return TX; } TX { return token::TX; }
TZ { return TZ; } TZ { return token::TZ; }
TB { return TB; } TB { return token::TB; }
TC { return TC; } TC { return token::TC; }
IG { return IG; } IG { return token::IG; }
{ID} { {ID} {
SaifParse_lval.string = sta::stringCopy(yytext); yylval->string = sta::stringCopy(yytext);
return ID; return token::ID;
} }
{EOL} { sta::saif_reader->incrLine(); } {EOL} { loc->lines(); loc->step(); }
{BLANK} { /* Ignore blanks. */ } {BLANK} { /* Ignore blanks. */ }

View File

@ -1,5 +1,3 @@
%{
// OpenSTA, Static Timing Analyzer // OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc. // Copyright (c) 2025, Parallax Software, Inc.
// //
@ -24,20 +22,41 @@
// //
// This notice may not be removed or altered from any source distribution. // This notice may not be removed or altered from any source distribution.
%{
#include <cctype> #include <cctype>
#include "Report.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "power/SaifReaderPvt.hh" #include "power/SaifReaderPvt.hh"
#include "power/SaifScanner.hh"
int SaifLex_lex(); #undef yylex
#define SaifParse_lex SaifLex_lex #define yylex scanner->lex
// use yacc generated parser errors
#define YYERROR_VERBOSE
#define YYDEBUG 1 // warning: variable 'yynerrs_' set but not used
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#define loc_line(loc) loc.begin.line
void
sta::SaifParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str());
}
%} %}
%require "3.2"
%skeleton "lalr1.cc"
%debug
%define api.namespace {sta}
%locations
%define api.location.file "SaifLocation.hh"
%define parse.assert
%parse-param { SaifScanner *scanner }
%parse-param { SaifReader *reader }
%define api.parser.class {SaifParse}
// expected shift/reduce conflicts // expected shift/reduce conflicts
%expect 2 %expect 2
@ -86,9 +105,9 @@ header_stmt:
| '(' VENDOR QSTRING ')' { sta::stringDelete($3); } | '(' VENDOR QSTRING ')' { sta::stringDelete($3); }
| '(' PROGRAM_NAME QSTRING ')' { sta::stringDelete($3); } | '(' PROGRAM_NAME QSTRING ')' { sta::stringDelete($3); }
| '(' VERSION QSTRING ')' { sta::stringDelete($3); } | '(' VERSION QSTRING ')' { sta::stringDelete($3); }
| '(' DIVIDER hchar ')' { sta::saif_reader->setDivider($3); } | '(' DIVIDER hchar ')' { reader->setDivider($3); }
| '(' TIMESCALE UINT ID ')' { sta::saif_reader->setTimescale($3, $4); } | '(' TIMESCALE UINT ID ')' { reader->setTimescale($3, $4); }
| '(' DURATION UINT ')' { sta::saif_reader->setDuration($3); } | '(' DURATION UINT ')' { reader->setDuration($3); }
; ;
hchar: hchar:
@ -100,13 +119,13 @@ hchar:
instance: instance:
'(' INSTANCE ID '(' INSTANCE ID
{ sta::saif_reader->instancePush($3); } { reader->instancePush($3); }
instance_contents ')' instance_contents ')'
{ sta::saif_reader->instancePop(); } { reader->instancePop(); }
| '(' INSTANCE QSTRING ID | '(' INSTANCE QSTRING ID
{ sta::saif_reader->instancePush($3); } { reader->instancePush($3); }
instance_contents ')' instance_contents ')'
{ sta::saif_reader->instancePop(); } { reader->instancePop(); }
; ;
instance_contents: instance_contents:
@ -128,7 +147,7 @@ nets:
net: net:
'(' ID state_durations ')' '(' ID state_durations ')'
{ sta::saif_reader->setNetDurations($2, $3); } { reader->setNetDurations($2, $3); }
; ;
ports: ports:

View File

@ -29,33 +29,27 @@
#include "Error.hh" #include "Error.hh"
#include "Debug.hh" #include "Debug.hh"
#include "Stats.hh"
#include "Report.hh" #include "Report.hh"
#include "Network.hh" #include "Network.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Power.hh" #include "Power.hh"
#include "power/SaifReaderPvt.hh" #include "power/SaifReaderPvt.hh"
#include "power/SaifScanner.hh"
#include "Sta.hh" #include "Sta.hh"
extern int
SaifParse_parse();
extern int SaifParse_debug;
namespace sta { namespace sta {
using std::min; using std::min;
SaifReader *saif_reader = nullptr;
bool bool
readSaif(const char *filename, readSaif(const char *filename,
const char *scope, const char *scope,
Sta *sta) Sta *sta)
{ {
SaifReader reader(filename, scope, sta); SaifReader reader(filename, scope, sta);
saif_reader = &reader;
bool success = reader.read(); bool success = reader.read();
saif_reader = nullptr;
return success; return success;
} }
@ -65,8 +59,6 @@ SaifReader::SaifReader(const char *filename,
StaState(sta), StaState(sta),
filename_(filename), filename_(filename),
scope_(scope), scope_(scope),
stream_(nullptr),
line_(1),
divider_('/'), divider_('/'),
escape_('\\'), escape_('\\'),
timescale_(1.0E-9F), // default units of ns timescale_(1.0E-9F), // default units of ns
@ -76,23 +68,16 @@ SaifReader::SaifReader(const char *filename,
{ {
} }
SaifReader::~SaifReader()
{
}
bool bool
SaifReader::read() SaifReader::read()
{ {
// Use zlib to uncompress gzip'd files automagically. gzstream::igzstream stream(filename_);
stream_ = gzopen(filename_, "rb"); if (stream.is_open()) {
if (stream_) { Stats stats(debug_, report_);
saif_scope_.clear(); SaifScanner scanner(&stream, filename_, this, report_);
in_scope_level_ = 0; SaifParse parser(&scanner, this);
annotated_pins_.clear();
//::SaifParse_debug = 1;
// yyparse returns 0 on success. // yyparse returns 0 on success.
bool success = (::SaifParse_parse() == 0); bool success = (parser.parse() == 0);
gzclose(stream_);
report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size()); report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size());
return success; return success;
} }
@ -122,10 +107,10 @@ SaifReader::setTimescale(uint64_t multiplier,
else if (stringEq(units, "fs")) else if (stringEq(units, "fs"))
timescale_ = multiplier * 1E-15; timescale_ = multiplier * 1E-15;
else else
saifError(180, "TIMESCALE units not us, ns, or ps."); report_->error(180, "SAIF TIMESCALE units not us, ns, or ps.");
} }
else else
saifError(181, "TIMESCALE multiplier not 1, 10, or 100."); report_->error(181, "SAIF TIMESCALE multiplier not 1, 10, or 100.");
stringDelete(units); stringDelete(units);
} }
@ -221,72 +206,23 @@ SaifReader::unescaped(const char *token)
return unescaped; return unescaped;
} }
void ////////////////////////////////////////////////////////////////
SaifReader::incrLine()
SaifScanner::SaifScanner(std::istream *stream,
const string &filename,
SaifReader *reader,
Report *report) :
yyFlexLexer(stream),
filename_(filename),
reader_(reader),
report_(report)
{ {
line_++;
} }
void void
SaifReader::getChars(char *buf, SaifScanner::error(const char *msg)
size_t &result,
size_t max_size)
{ {
char *status = gzgets(stream_, buf, max_size); report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
if (status == Z_NULL)
result = 0; // YY_nullptr
else
result = strlen(buf);
}
void
SaifReader::getChars(char *buf,
int &result,
size_t max_size)
{
char *status = gzgets(stream_, buf, max_size);
if (status == Z_NULL)
result = 0; // YY_nullptr
else
result = strlen(buf);
}
void
SaifReader::notSupported(const char *feature)
{
saifError(193, "%s not supported.", feature);
}
void
SaifReader::saifWarn(int id,
const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
report_->vfileWarn(id, filename_, line_, fmt, args);
va_end(args);
}
void
SaifReader::saifError(int id,
const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
report_->vfileError(id, filename_, line_, fmt, args);
va_end(args);
} }
} // namespace } // namespace
// Global namespace
void saifFlushBuffer();
int
SaifParse_error(const char *msg)
{
saifFlushBuffer();
sta::saif_reader->saifError(196, "%s.\n", msg);
return 0;
}

View File

@ -39,15 +39,11 @@
// global namespace // global namespace
#define YY_INPUT(buf,result,max_size) \
sta::saif_reader->getChars(buf, result, max_size)
int
SaifParse_error(const char *msg);
namespace sta { namespace sta {
class Sta; class Sta;
class Power; class Power;
class SaifScanner;
using std::vector; using std::vector;
using std::string; using std::string;
@ -62,7 +58,6 @@ public:
SaifReader(const char *filename, SaifReader(const char *filename,
const char *scope, const char *scope,
Sta *sta); Sta *sta);
~SaifReader();
bool read(); bool read();
void setDivider(char divider); void setDivider(char divider);
@ -73,24 +68,7 @@ public:
void instancePop(); void instancePop();
void setNetDurations(const char *net_name, void setNetDurations(const char *net_name,
SaifStateDurations &durations); SaifStateDurations &durations);
// flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
// so provide both forms.
void getChars(char *buf,
size_t &result,
size_t max_size);
void getChars(char *buf,
int &result,
size_t max_size);
void incrLine();
const char *filename() { return filename_; } const char *filename() { return filename_; }
int line() { return line_; }
void saifWarn(int id,
const char *fmt, ...);
void saifError(int id,
const char *fmt,
...);
void notSupported(const char *feature);
private: private:
string unescaped(const char *token); string unescaped(const char *token);
@ -98,8 +76,6 @@ private:
const char *filename_; const char *filename_;
const char *scope_; // Divider delimited scope to begin annotation. const char *scope_; // Divider delimited scope to begin annotation.
gzFile stream_;
int line_;
char divider_; char divider_;
char escape_; char escape_;
double timescale_; double timescale_;
@ -112,6 +88,4 @@ private:
Power *power_; Power *power_;
}; };
extern SaifReader *saif_reader;
} // namespace } // namespace

66
power/SaifScanner.hh Normal file
View File

@ -0,0 +1,66 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SaifLocation.hh"
#include "SaifParse.hh"
#ifndef __FLEX_LEXER_H
#undef yyFlexLexer
#define yyFlexLexer SaifFlexLexer
#include <FlexLexer.h>
#endif
namespace sta {
class Report;
class SaifScanner : public SaifFlexLexer
{
public:
SaifScanner(std::istream *stream,
const string &filename,
SaifReader *reader,
Report *report);
virtual ~SaifScanner() {}
virtual int lex(SaifParse::semantic_type *const yylval,
SaifParse::location_type *yylloc);
// YY_DECL defined in SaifLex.ll
// Method body created by flex in SaifLex.cc
void error(const char *msg);
// Get rid of override virtual function warning.
using FlexLexer::yylex;
private:
string filename_;
SaifReader *reader_;
Report *report_;
string token_;
};
} // namespace

View File

@ -64,19 +64,20 @@ void
InputDrive::driveResistance(const RiseFall *rf, InputDrive::driveResistance(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
float &res, float &res,
bool &exists) bool &exists) const
{ {
drive_resistances_.value(rf, min_max, res, exists); drive_resistances_.value(rf, min_max, res, exists);
} }
bool bool
InputDrive::hasDriveResistance(const RiseFall *rf, const MinMax *min_max) InputDrive::hasDriveResistance(const RiseFall *rf,
const MinMax *min_max) const
{ {
return drive_resistances_.hasValue(rf, min_max); return drive_resistances_.hasValue(rf, min_max);
} }
bool bool
InputDrive::driveResistanceMinMaxEqual(const RiseFall *rf) InputDrive::driveResistanceMinMaxEqual(const RiseFall *rf) const
{ {
float min_res, max_res; float min_res, max_res;
bool min_exists, max_exists; bool min_exists, max_exists;
@ -120,7 +121,7 @@ InputDrive::driveCell(const RiseFall *rf,
const LibertyCell *&cell, const LibertyCell *&cell,
const LibertyPort *&from_port, const LibertyPort *&from_port,
float *&from_slews, float *&from_slews,
const LibertyPort *&to_port) const LibertyPort *&to_port) const
{ {
InputDriveCell *drive = drive_cells_[rf->index()][min_max->index()]; InputDriveCell *drive = drive_cells_[rf->index()][min_max->index()];
if (drive) { if (drive) {
@ -139,20 +140,20 @@ InputDrive::driveCell(const RiseFall *rf,
InputDriveCell * InputDriveCell *
InputDrive::driveCell(const RiseFall *rf, InputDrive::driveCell(const RiseFall *rf,
const MinMax *min_max) const MinMax *min_max) const
{ {
return drive_cells_[rf->index()][min_max->index()]; return drive_cells_[rf->index()][min_max->index()];
} }
bool bool
InputDrive::hasDriveCell(const RiseFall *rf, InputDrive::hasDriveCell(const RiseFall *rf,
const MinMax *min_max) const MinMax *min_max) const
{ {
return drive_cells_[rf->index()][min_max->index()] != nullptr; return drive_cells_[rf->index()][min_max->index()] != nullptr;
} }
bool bool
InputDrive::driveCellsEqual() InputDrive::driveCellsEqual() const
{ {
int rise_index = RiseFall::riseIndex(); int rise_index = RiseFall::riseIndex();
int fall_index = RiseFall::fallIndex(); int fall_index = RiseFall::fallIndex();
@ -171,7 +172,7 @@ void
InputDrive::slew(const RiseFall *rf, InputDrive::slew(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
float &slew, float &slew,
bool &exists) bool &exists) const
{ {
slews_.value(rf, min_max, slew, exists); slews_.value(rf, min_max, slew, exists);
} }

View File

@ -42,7 +42,13 @@ proc_redirect read_sdc {
check_argc_eq1 "read_sdc" $args check_argc_eq1 "read_sdc" $args
set echo [info exists flags(-echo)] set echo [info exists flags(-echo)]
set filename [file nativename [lindex $args 0]] set filename [file nativename [lindex $args 0]]
source_ $filename $echo 0 set prev_filename [info script]
try {
info script $filename
source_ $filename $echo 0
} finally {
info script $prev_filename
}
} }
################################################################ ################################################################
@ -70,7 +76,13 @@ proc_redirect source {
set echo [info exists flags(-echo)] set echo [info exists flags(-echo)]
set verbose [info exists flags(-verbose)] set verbose [info exists flags(-verbose)]
set filename [file nativename [lindex $args 0]] set filename [file nativename [lindex $args 0]]
source_ $filename $echo $verbose set prev_filename [info script]
try {
info script $filename
source_ $filename $echo $verbose
} finally {
info script $prev_filename
}
} }
proc source_ { filename echo verbose } { proc source_ { filename echo verbose } {

View File

@ -1716,7 +1716,7 @@ WriteSdc::writeInputTransitions() const
Port *port = port_iter->next(); Port *port = port_iter->next();
InputDrive *drive = sdc_->findInputDrive(port); InputDrive *drive = sdc_->findInputDrive(port);
if (drive) { if (drive) {
RiseFallMinMax *slews = drive->slews(); const RiseFallMinMax *slews = drive->slews();
WriteGetPort write_port(port, this); WriteGetPort write_port(port, this);
writeRiseFallMinMaxTimeCmd("set_input_transition", slews, write_port); writeRiseFallMinMaxTimeCmd("set_input_transition", slews, write_port);
} }

View File

@ -33,6 +33,14 @@
// warning: variable 'yynerrs_' set but not used // warning: variable 'yynerrs_' set but not used
#pragma GCC diagnostic ignored "-Wunused-but-set-variable" #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
void
sta::SdfParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164,reader->filename().c_str(),
loc.begin.line,"%s",msg.c_str());
}
%} %}
%require "3.2" %require "3.2"
@ -44,11 +52,7 @@
%define parse.assert %define parse.assert
%parse-param { SdfScanner *scanner } %parse-param { SdfScanner *scanner }
%parse-param { SdfReader *reader } %parse-param { SdfReader *reader }
%define api.parser.class {SdfParse}
// bison 3.0.4 for centos7
%define parser_class_name {SdfParse}
// bison 3.3.2
//%define api.parser.class {SdfParse}
// expected shift/reduce conflicts // expected shift/reduce conflicts
%expect 4 %expect 4

View File

@ -1103,14 +1103,4 @@ SdfScanner::error(const char *msg)
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
} }
////////////////////////////////////////////////////////////////
void
SdfParse::error(const location_type &loc,
const string &msg)
{
reader->report()->fileError(164,reader->filename().c_str(),
loc.begin.line,"%s",msg.c_str());
}
} // namespace } // namespace

View File

@ -24,15 +24,15 @@
#pragma once #pragma once
#include "SdfLocation.hh"
#include "SdfParse.hh"
#ifndef __FLEX_LEXER_H #ifndef __FLEX_LEXER_H
#undef yyFlexLexer #undef yyFlexLexer
#define yyFlexLexer SdfFlexLexer #define yyFlexLexer SdfFlexLexer
#include <FlexLexer.h> #include <FlexLexer.h>
#endif #endif
#include "SdfLocation.hh"
#include "SdfParse.hh"
namespace sta { namespace sta {
class Report; class Report;

View File

@ -61,9 +61,9 @@ public:
PathVertex *ref_path, PathVertex *ref_path,
TimingArc *check_arc, TimingArc *check_arc,
Edge *check_edge); Edge *check_edge);
PathVertex *clkPath() { return &clk_path_; } const PathVertex *clkPath() const { return &clk_path_; }
Pin *clkPin(const StaState *sta) const; Pin *clkPin(const StaState *sta) const;
PathVertex *refPath() { return &ref_path_; } const PathVertex *refPath() const { return &ref_path_; }
Pin *refPin(const StaState *sta) const; Pin *refPin(const StaState *sta) const;
Delay skew(const StaState *sta) const; Delay skew(const StaState *sta) const;
ArcDelay maxSkew(const StaState *sta) const; ArcDelay maxSkew(const StaState *sta) const;

View File

@ -51,15 +51,15 @@ void
Latches::latchRequired(const Path *data_path, Latches::latchRequired(const Path *data_path,
const PathVertex *enable_path, const PathVertex *enable_path,
const PathVertex *disable_path, const PathVertex *disable_path,
MultiCyclePath *mcp, const MultiCyclePath *mcp,
PathDelay *path_delay, const PathDelay *path_delay,
Arrival src_clk_latency, Arrival src_clk_latency,
const ArcDelay &margin, const ArcDelay &margin,
// Return values. // Return values.
Required &required, Required &required,
Arrival &borrow, Arrival &borrow,
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint) Delay &time_given_to_startpoint) const
{ {
const Arrival data_arrival = data_path->arrival(this); const Arrival data_arrival = data_path->arrival(this);
float max_delay = 0.0; float max_delay = 0.0;
@ -161,7 +161,7 @@ Latches::latchBorrowInfo(const Path *data_path,
Crpr &open_crpr, Crpr &open_crpr,
Crpr &crpr_diff, Crpr &crpr_diff,
Delay &max_borrow, Delay &max_borrow,
bool &borrow_limit_exists) bool &borrow_limit_exists) const
{ {
if (data_path && enable_path && disable_path) { if (data_path && enable_path && disable_path) {
const ClockEdge *data_clk_edge = data_path->clkEdge(this); const ClockEdge *data_clk_edge = data_path->clkEdge(this);
@ -220,7 +220,7 @@ Latches::latchRequired(const Path *data_path,
Required &required, Required &required,
Arrival &borrow, Arrival &borrow,
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint) Delay &time_given_to_startpoint) const
{ {
Vertex *data_vertex = data_path->vertex(this); Vertex *data_vertex = data_path->vertex(this);
const RiseFall *data_rf = data_path->transition(this); const RiseFall *data_rf = data_path->transition(this);
@ -244,10 +244,10 @@ Latches::latchRequired(const Path *data_path,
// Find the latch enable open/close path from the close/open path. // Find the latch enable open/close path from the close/open path.
void void
Latches::latchEnableOtherPath(Path *path, Latches::latchEnableOtherPath(const Path *path,
const PathAnalysisPt *tgt_clk_path_ap, const PathAnalysisPt *tgt_clk_path_ap,
// Return value. // Return value.
PathVertex &other_path) PathVertex &other_path) const
{ {
Vertex *vertex = path->vertex(this); Vertex *vertex = path->vertex(this);
const ClockEdge *clk_edge = path->clkEdge(this); const ClockEdge *clk_edge = path->clkEdge(this);
@ -266,8 +266,8 @@ Latches::latchEnableOtherPath(Path *path,
} }
void void
Latches::latchEnablePath(Path *q_path, Latches::latchEnablePath(const Path *q_path,
Edge *d_q_edge, const Edge *d_q_edge,
// Return value. // Return value.
PathVertex &enable_path) const PathVertex &enable_path) const
@ -299,9 +299,9 @@ Latches::latchEnablePath(Path *q_path,
// times of the enable. The to_tag for Q is adjusted to the that of // times of the enable. The to_tag for Q is adjusted to the that of
// the enable open edge. // the enable open edge.
void void
Latches::latchOutArrival(Path *data_path, Latches::latchOutArrival(const Path *data_path,
TimingArc *d_q_arc, const TimingArc *d_q_arc,
Edge *d_q_edge, const Edge *d_q_edge,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
// Return values. // Return values.
Tag *&q_tag, Tag *&q_tag,
@ -398,7 +398,7 @@ Latches::latchOutArrival(Path *data_path,
} }
ExceptionPath * ExceptionPath *
Latches::exceptionTo(Path *data_path, Latches::exceptionTo(const Path *data_path,
const ClockEdge *en_clk_edge) const ClockEdge *en_clk_edge)
{ {
// Look for exceptions -to data or -to enable clk. // Look for exceptions -to data or -to enable clk.
@ -415,7 +415,7 @@ ArcDelay
Latches::latchSetupMargin(Vertex *data_vertex, Latches::latchSetupMargin(Vertex *data_vertex,
const RiseFall *data_rf, const RiseFall *data_rf,
const Path *disable_path, const Path *disable_path,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap) const
{ {
if (disable_path) { if (disable_path) {
Vertex *enable_vertex = disable_path->vertex(this); Vertex *enable_vertex = disable_path->vertex(this);
@ -443,12 +443,12 @@ Latches::latchSetupMargin(Vertex *data_vertex,
} }
void void
Latches::latchTimeGivenToStartpoint(Path *d_path, Latches::latchTimeGivenToStartpoint(const Path *d_path,
Path *q_path, const Path *q_path,
Edge *d_q_edge, const Edge *d_q_edge,
// Return values. // Return values.
Arrival &time_given, Arrival &time_given,
PathVertex &enable_path) PathVertex &enable_path) const
{ {
latchEnablePath(q_path, d_q_edge, enable_path); latchEnablePath(q_path, d_q_edge, enable_path);
if (!enable_path.isNull() if (!enable_path.isNull()
@ -470,7 +470,7 @@ Latches::latchTimeGivenToStartpoint(Path *d_path,
} }
void void
Latches::latchDtoQEnable(Edge *d_q_edge, Latches::latchDtoQEnable(const Edge *d_q_edge,
const Instance *inst, const Instance *inst,
// Return values. // Return values.
Vertex *&enable_vertex, Vertex *&enable_vertex,

View File

@ -38,24 +38,24 @@ class Latches : public StaState
{ {
public: public:
Latches(StaState *sta); Latches(StaState *sta);
void latchTimeGivenToStartpoint(Path *d_path, void latchTimeGivenToStartpoint(const Path *d_path,
Path *q_path, const Path *q_path,
Edge *d_q_edge, const Edge *d_q_edge,
// Return values. // Return values.
Arrival &time_given, Arrival &time_given,
PathVertex &enable_path); PathVertex &enable_path) const;
void latchRequired(const Path *data_path, void latchRequired(const Path *data_path,
const PathVertex *enable_path, const PathVertex *enable_path,
const PathVertex *disable_path, const PathVertex *disable_path,
MultiCyclePath *mcp, const MultiCyclePath *mcp,
PathDelay *path_delay, const PathDelay *path_delay,
Arrival src_clk_latency, Arrival src_clk_latency,
const ArcDelay &margin, const ArcDelay &margin,
// Return values. // Return values.
Required &required, Required &required,
Delay &borrow, Delay &borrow,
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint); Delay &time_given_to_startpoint) const;
void latchRequired(const Path *data_path, void latchRequired(const Path *data_path,
const PathVertex *enable_path, const PathVertex *enable_path,
const PathVertex *disable_path, const PathVertex *disable_path,
@ -64,7 +64,7 @@ public:
Required &required, Required &required,
Delay &borrow, Delay &borrow,
Arrival &adjusted_data_arrival, Arrival &adjusted_data_arrival,
Delay &time_given_to_startpoint); Delay &time_given_to_startpoint) const;
void latchBorrowInfo(const Path *data_path, void latchBorrowInfo(const Path *data_path,
const PathVertex *enable_path, const PathVertex *enable_path,
const PathVertex *disable_path, const PathVertex *disable_path,
@ -78,26 +78,27 @@ public:
Crpr &open_crpr, Crpr &open_crpr,
Crpr &crpr_diff, Crpr &crpr_diff,
Delay &max_borrow, Delay &max_borrow,
bool &borrow_limit_exists); bool &borrow_limit_exists) const;
bool isLatchDtoQ(Edge *edge) const; bool isLatchDtoQ(Edge *edge) const;
// Find the latch EN->Q edge for a D->Q edge. // Find the latch EN->Q edge for a D->Q edge.
void latchDtoQEnable(Edge *d_q_edge, void latchDtoQEnable(const Edge *d_q_edge,
const Instance *inst, const Instance *inst,
// Return values. // Return values.
Vertex *&enable_vertex, Vertex *&enable_vertex,
const RiseFall *&enable_rf, const RiseFall *&enable_rf,
LatchEnableState &state) const; LatchEnableState &state) const;
LatchEnableState latchDtoQState(Edge *d_q_edge) const; LatchEnableState latchDtoQState(Edge *d_q_edge) const;
void latchEnableOtherPath(Path *path, void latchEnableOtherPath(const Path *path,
const PathAnalysisPt *tgt_clk_path_ap, const PathAnalysisPt *tgt_clk_path_ap,
// Return value. // Return value.
PathVertex &other_path); PathVertex &other_path) const;
void latchEnablePath(Path *q_path, Edge *d_q_edge, void latchEnablePath(const Path *q_path,
const Edge *d_q_edge,
// Return value. // Return value.
PathVertex &enable_path) const; PathVertex &enable_path) const;
void latchOutArrival(Path *data_path, void latchOutArrival(const Path *data_path,
TimingArc *d_q_arc, const TimingArc *d_q_arc,
Edge *d_q_edge, const Edge *d_q_edge,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
Tag *&q_tag, Tag *&q_tag,
ArcDelay &arc_delay, ArcDelay &arc_delay,
@ -107,8 +108,8 @@ protected:
ArcDelay latchSetupMargin(Vertex *data_vertex, ArcDelay latchSetupMargin(Vertex *data_vertex,
const RiseFall *data_rf, const RiseFall *data_rf,
const Path *disable_path, const Path *disable_path,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap) const;
ExceptionPath *exceptionTo(Path *data_path, ExceptionPath *exceptionTo(const Path *data_path,
const ClockEdge *en_clk_edge); const ClockEdge *en_clk_edge);
}; };

View File

@ -428,7 +428,7 @@ PathEnd::checkInterClkUncertainty(const ClockEdge *src_clk_edge,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
PathEndUnconstrained::reportFull(ReportPath *report) const PathEndUnconstrained::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
@ -440,7 +440,7 @@ PathEndUnconstrained::slackNoCrpr(const StaState *) const
} }
void void
PathEndUnconstrained::reportShort(ReportPath *report) const PathEndUnconstrained::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -979,13 +979,13 @@ PathEndCheck::typeName() const
} }
void void
PathEndCheck::reportFull(ReportPath *report) const PathEndCheck::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndCheck::reportShort(ReportPath *report) const PathEndCheck::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -1170,13 +1170,13 @@ PathEndLatchCheck::latchDisable() const
} }
void void
PathEndLatchCheck::reportFull(ReportPath *report) const PathEndLatchCheck::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndLatchCheck::reportShort(ReportPath *report) const PathEndLatchCheck::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -1359,13 +1359,13 @@ PathEndOutputDelay::typeName() const
} }
void void
PathEndOutputDelay::reportFull(ReportPath *report) const PathEndOutputDelay::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndOutputDelay::reportShort(ReportPath *report) const PathEndOutputDelay::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -1571,13 +1571,13 @@ PathEndGatedClock::checkRole(const StaState *) const
} }
void void
PathEndGatedClock::reportFull(ReportPath *report) const PathEndGatedClock::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndGatedClock::reportShort(ReportPath *report) const PathEndGatedClock::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -1734,13 +1734,13 @@ PathEndDataCheck::checkRole(const StaState *sta) const
} }
void void
PathEndDataCheck::reportFull(ReportPath *report) const PathEndDataCheck::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndDataCheck::reportShort(ReportPath *report) const PathEndDataCheck::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }
@ -1858,13 +1858,13 @@ PathEndPathDelay::findSrcClkArrival(const StaState *sta)
} }
void void
PathEndPathDelay::reportFull(ReportPath *report) const PathEndPathDelay::reportFull(const ReportPath *report) const
{ {
report->reportFull(this); report->reportFull(this);
} }
void void
PathEndPathDelay::reportShort(ReportPath *report) const PathEndPathDelay::reportShort(const ReportPath *report) const
{ {
report->reportShort(this); report->reportShort(this);
} }

View File

@ -164,31 +164,31 @@ PathExpanded::path(size_t index) const
} }
TimingArc * TimingArc *
PathExpanded::prevArc(size_t index) PathExpanded::prevArc(size_t index) const
{ {
return prev_arcs_[pathsIndex(index)]; return prev_arcs_[pathsIndex(index)];
} }
PathRef * const PathRef *
PathExpanded::startPath() PathExpanded::startPath() const
{ {
return &paths_[start_index_]; return &paths_[start_index_];
} }
PathRef * const PathRef *
PathExpanded::endPath() PathExpanded::endPath() const
{ {
return &paths_[0]; return &paths_[0];
} }
TimingArc * TimingArc *
PathExpanded::startPrevArc() PathExpanded::startPrevArc() const
{ {
return prev_arcs_[start_index_]; return prev_arcs_[start_index_];
} }
PathRef * const PathRef *
PathExpanded::startPrevPath() PathExpanded::startPrevPath() const
{ {
size_t start1 = start_index_ + 1; size_t start1 = start_index_ + 1;
if (start1 < paths_.size()) if (start1 < paths_.size())
@ -198,11 +198,11 @@ PathExpanded::startPrevPath()
} }
void void
PathExpanded::clkPath(PathRef &clk_path) PathExpanded::clkPath(PathRef &clk_path) const
{ {
const Latches *latches = sta_->latches(); const Latches *latches = sta_->latches();
PathRef *start = startPath(); const PathRef *start = startPath();
TimingArc *prev_arc = startPrevArc(); const TimingArc *prev_arc = startPrevArc();
if (start && prev_arc) { if (start && prev_arc) {
TimingRole *role = prev_arc->role(); TimingRole *role = prev_arc->role();
if (role == TimingRole::latchDtoQ()) { if (role == TimingRole::latchDtoQ()) {
@ -215,7 +215,7 @@ PathExpanded::clkPath(PathRef &clk_path)
} }
else if (role == TimingRole::regClkToQ() else if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ()) { || role == TimingRole::latchEnToQ()) {
PathRef *start_prev = startPrevPath(); const PathRef *start_prev = startPrevPath();
if (start_prev) if (start_prev)
clk_path.init(start_prev); clk_path.init(start_prev);
} }
@ -226,15 +226,15 @@ PathExpanded::clkPath(PathRef &clk_path)
void void
PathExpanded::latchPaths(// Return values. PathExpanded::latchPaths(// Return values.
PathRef *&d_path, const PathRef *&d_path,
PathRef *&q_path, const PathRef *&q_path,
Edge *&d_q_edge) Edge *&d_q_edge) const
{ {
d_path = nullptr; d_path = nullptr;
q_path = nullptr; q_path = nullptr;
d_q_edge = nullptr; d_q_edge = nullptr;
PathRef *start = startPath(); const PathRef *start = startPath();
TimingArc *prev_arc = startPrevArc(); const TimingArc *prev_arc = startPrevArc();
if (start if (start
&& prev_arc && prev_arc
&& prev_arc->role() == TimingRole::latchDtoQ()) { && prev_arc->role() == TimingRole::latchDtoQ()) {

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ typedef Vector<ReportField*> ReportFieldSeq;
class ReportPath : public StaState class ReportPath : public StaState
{ {
public: public:
explicit ReportPath(StaState *sta); ReportPath(StaState *sta);
virtual ~ReportPath(); virtual ~ReportPath();
ReportPathFormat pathFormat() const { return format_; } ReportPathFormat pathFormat() const { return format_; }
void setPathFormat(ReportPathFormat format); void setPathFormat(ReportPathFormat format);
@ -61,93 +61,93 @@ public:
void setNoSplit(bool no_split); void setNoSplit(bool no_split);
bool reportSigmas() const { return report_sigmas_; } bool reportSigmas() const { return report_sigmas_; }
void setReportSigmas(bool report); void setReportSigmas(bool report);
ReportField *findField(const char *name); ReportField *findField(const char *name) const;
// Header above reportPathEnd results. // Header above reportPathEnd results.
void reportPathEndHeader(); void reportPathEndHeader() const;
// Footer below reportPathEnd results. // Footer below reportPathEnd results.
void reportPathEndFooter(); void reportPathEndFooter() const;
void reportPathEnd(PathEnd *end); void reportPathEnd(const PathEnd *end) const;
// Format report_path_endpoint only: // Format report_path_endpoint only:
// Previous path end is used to detect path group changes // Previous path end is used to detect path group changes
// so headers are reported by group. // so headers are reported by group.
void reportPathEnd(PathEnd *end, void reportPathEnd(const PathEnd *end,
PathEnd *prev_end, const PathEnd *prev_end,
bool last); bool last) const;
void reportPathEnds(PathEndSeq *ends); void reportPathEnds(const PathEndSeq *ends) const;
void reportPath(const Path *path); void reportPath(const Path *path) const;
void reportShort(const PathEndUnconstrained *end); void reportShort(const PathEndUnconstrained *end) const;
void reportShort(const PathEndCheck *end); void reportShort(const PathEndCheck *end) const;
void reportShort(const PathEndLatchCheck *end); void reportShort(const PathEndLatchCheck *end) const;
void reportShort(const PathEndPathDelay *end); void reportShort(const PathEndPathDelay *end) const;
void reportShort(const PathEndOutputDelay *end); void reportShort(const PathEndOutputDelay *end) const;
void reportShort(const PathEndGatedClock *end); void reportShort(const PathEndGatedClock *end) const;
void reportShort(const PathEndDataCheck *end); void reportShort(const PathEndDataCheck *end) const;
void reportFull(const PathEndUnconstrained *end); void reportFull(const PathEndUnconstrained *end) const;
void reportFull(const PathEndCheck *end); void reportFull(const PathEndCheck *end) const;
void reportFull(const PathEndLatchCheck *end); void reportFull(const PathEndLatchCheck *end) const;
void reportFull(const PathEndPathDelay *end); void reportFull(const PathEndPathDelay *end) const;
void reportFull(const PathEndOutputDelay *end); void reportFull(const PathEndOutputDelay *end) const;
void reportFull(const PathEndGatedClock *end); void reportFull(const PathEndGatedClock *end) const;
void reportFull(const PathEndDataCheck *end); void reportFull(const PathEndDataCheck *end) const;
void reportJsonHeader(); void reportJsonHeader() const;
void reportJsonFooter(); void reportJsonFooter() const;
void reportJson(const PathEnd *end, void reportJson(const PathEnd *end,
bool last); bool last) const;
void reportJson(const Path *path); void reportJson(const Path *path) const;
void reportJson(const Path *path, void reportJson(const Path *path,
const char *path_name, const char *path_name,
int indent, int indent,
bool trailing_comma, bool trailing_comma,
string &result); string &result) const;
void reportJson(const PathExpanded &expanded, void reportJson(const PathExpanded &expanded,
const char *path_name, const char *path_name,
int indent, int indent,
bool trailing_comma, bool trailing_comma,
string &result); string &result) const;
void reportEndHeader(); void reportEndHeader() const;
void reportEndLine(PathEnd *end); void reportEndLine(const PathEnd *end) const;
void reportSummaryHeader(); void reportSummaryHeader() const;
void reportSummaryLine(PathEnd *end); void reportSummaryLine(const PathEnd *end) const;
void reportSlackOnlyHeader(); void reportSlackOnlyHeader() const;
void reportSlackOnly(PathEnd *end); void reportSlackOnly(const PathEnd *end) const;
void reportMpwCheck(MinPulseWidthCheck *check, void reportMpwCheck(const MinPulseWidthCheck *check,
bool verbose); bool verbose) const;
void reportMpwChecks(MinPulseWidthCheckSeq *checks, void reportMpwChecks(const MinPulseWidthCheckSeq *checks,
bool verbose); bool verbose) const;
void reportMpwHeaderShort(); void reportMpwHeaderShort() const;
void reportShort(MinPulseWidthCheck *check); void reportShort(const MinPulseWidthCheck *check) const;
void reportVerbose(MinPulseWidthCheck *check); void reportVerbose(const MinPulseWidthCheck *check) const;
void reportCheck(MinPeriodCheck *check, void reportCheck(const MinPeriodCheck *check,
bool verbose); bool verbose) const;
void reportChecks(MinPeriodCheckSeq *checks, void reportChecks(const MinPeriodCheckSeq *checks,
bool verbose); bool verbose) const;
void reportPeriodHeaderShort(); void reportPeriodHeaderShort() const;
void reportShort(MinPeriodCheck *check); void reportShort(const MinPeriodCheck *check) const;
void reportVerbose(MinPeriodCheck *check); void reportVerbose(const MinPeriodCheck *check) const;
void reportCheck(MaxSkewCheck *check, void reportCheck(const MaxSkewCheck *check,
bool verbose); bool verbose) const;
void reportChecks(MaxSkewCheckSeq *checks, void reportChecks(const MaxSkewCheckSeq *checks,
bool verbose); bool verbose) const;
void reportMaxSkewHeaderShort(); void reportMaxSkewHeaderShort() const;
void reportShort(MaxSkewCheck *check); void reportShort(const MaxSkewCheck *check) const;
void reportVerbose(MaxSkewCheck *check); void reportVerbose(const MaxSkewCheck *check) const;
void reportLimitShortHeader(const ReportField *field); void reportLimitShortHeader(const ReportField *field) const;
void reportLimitShort(const ReportField *field, void reportLimitShort(const ReportField *field,
Pin *pin, Pin *pin,
float value, float value,
float limit, float limit,
float slack); float slack) const;
void reportLimitVerbose(const ReportField *field, void reportLimitVerbose(const ReportField *field,
Pin *pin, Pin *pin,
const RiseFall *rf, const RiseFall *rf,
@ -155,7 +155,7 @@ public:
float limit, float limit,
float slack, float slack,
const Corner *corner, const Corner *corner,
const MinMax *min_max); const MinMax *min_max) const;
ReportField *fieldSlew() const { return field_slew_; } ReportField *fieldSlew() const { return field_slew_; }
ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldFanout() const { return field_fanout_; }
ReportField *fieldCapacitance() const { return field_capacitance_; } ReportField *fieldCapacitance() const { return field_capacitance_; }
@ -169,83 +169,83 @@ protected:
bool left_justify, bool left_justify,
Unit *unit, Unit *unit,
bool enabled); bool enabled);
void reportEndpointHeader(PathEnd *end, void reportEndpointHeader(const PathEnd *end,
PathEnd *prev_end); const PathEnd *prev_end) const;
void reportShort(const PathEndUnconstrained *end, void reportShort(const PathEndUnconstrained *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndCheck *end, void reportShort(const PathEndCheck *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndLatchCheck *end, void reportShort(const PathEndLatchCheck *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndPathDelay *end, void reportShort(const PathEndPathDelay *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndOutputDelay *end, void reportShort(const PathEndOutputDelay *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndGatedClock *end, void reportShort(const PathEndGatedClock *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportShort(const PathEndDataCheck *end, void reportShort(const PathEndDataCheck *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportEndpoint(const PathEndOutputDelay *end); void reportEndpoint(const PathEndOutputDelay *end) const;
void reportEndpointOutputDelay(const PathEndClkConstrained *end); void reportEndpointOutputDelay(const PathEndClkConstrained *end) const;
void reportEndpoint(const PathEndPathDelay *end); void reportEndpoint(const PathEndPathDelay *end) const;
void reportEndpoint(const PathEndGatedClock *end); void reportEndpoint(const PathEndGatedClock *end) const;
string pathEndpoint(PathEnd *end); string pathEndpoint(const PathEnd *end) const;
string pathStartpoint(PathEnd *end, string pathStartpoint(const PathEnd *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportBorrowing(const PathEndLatchCheck *end, void reportBorrowing(const PathEndLatchCheck *end,
Arrival &borrow, Arrival &borrow,
Arrival &time_given_to_startpoint); Arrival &time_given_to_startpoint) const;
void reportEndpoint(const PathEndDataCheck *end); void reportEndpoint(const PathEndDataCheck *end) const;
const char *clkNetworkDelayIdealProp(bool is_ideal); const char *clkNetworkDelayIdealProp(bool is_ideal) const;
string checkRoleReason(const PathEnd *end); string checkRoleReason(const PathEnd *end) const;
string checkRoleString(const PathEnd *end); string checkRoleString(const PathEnd *end) const;
virtual void reportGroup(const PathEnd *end); virtual void reportGroup(const PathEnd *end) const;
void reportStartpoint(const PathEnd *end, void reportStartpoint(const PathEnd *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportUnclockedEndpoint(const PathEnd *end, void reportUnclockedEndpoint(const PathEnd *end,
const char *default_reason); const char *default_reason) const;
void reportEndpoint(const PathEndCheck *end); void reportEndpoint(const PathEndCheck *end) const;
void reportEndpoint(const PathEndLatchCheck *end); void reportEndpoint(const PathEndLatchCheck *end) const;
const char *latchDesc(const PathEndLatchCheck *end); const char *latchDesc(const PathEndLatchCheck *end) const;
void reportStartpoint(const char *start, void reportStartpoint(const char *start,
string reason); const string reason) const;
void reportEndpoint(const char *end, void reportEndpoint(const char *end,
string reason); const string reason) const;
void reportStartEndPoint(const char *pt, void reportStartEndPoint(const char *pt,
string reason, const string reason,
const char *key); const char *key) const;
string tgtClkName(const PathEnd *end); string tgtClkName(const PathEnd *end) const;
const char *clkRegLatchDesc(const PathEnd *end); const char *clkRegLatchDesc(const PathEnd *end) const;
void reportSrcPath(const PathEnd *end, void reportSrcPath(const PathEnd *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportTgtClk(const PathEnd *end); void reportTgtClk(const PathEnd *end) const;
void reportTgtClk(const PathEnd *end, void reportTgtClk(const PathEnd *end,
float prev_time); float prev_time) const;
void reportTgtClk(const PathEnd *end, void reportTgtClk(const PathEnd *end,
float prev_time, float prev_time,
bool is_prop); bool is_prop) const;
void reportTgtClk(const PathEnd *end, void reportTgtClk(const PathEnd *end,
float prev_time, float prev_time,
float src_offset, float src_offset,
bool is_prop); bool is_prop) const;
bool pathFromGenPropClk(const Path *clk_path, bool pathFromGenPropClk(const Path *clk_path,
const EarlyLate *early_late); const EarlyLate *early_late) const;
bool isGenPropClk(const Clock *clk, bool isGenPropClk(const Clock *clk,
const RiseFall *clk_rf, const RiseFall *clk_rf,
const MinMax *min_max, const MinMax *min_max,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportSrcClkAndPath(const Path *path, void reportSrcClkAndPath(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
float time_offset, float time_offset,
Arrival clk_insertion, Arrival clk_insertion,
Arrival clk_latency, Arrival clk_latency,
bool is_path_delay); bool is_path_delay) const;
bool reportGenClkSrcPath(const Path *clk_path, bool reportGenClkSrcPath(const Path *clk_path,
const Clock *clk, const Clock *clk,
const RiseFall *clk_rf, const RiseFall *clk_rf,
const MinMax *min_max, const MinMax *min_max,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportGenClkSrcAndPath(const Path *path, void reportGenClkSrcAndPath(const Path *path,
const Clock *clk, const Clock *clk,
const RiseFall *clk_rf, const RiseFall *clk_rf,
@ -253,7 +253,7 @@ protected:
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
float time_offset, float time_offset,
float path_time_offset, float path_time_offset,
bool clk_used_as_data); bool clk_used_as_data) const;
bool reportGenClkSrcPath1(const Clock *clk, bool reportGenClkSrcPath1(const Clock *clk,
const Pin *clk_pin, const Pin *clk_pin,
const RiseFall *clk_rf, const RiseFall *clk_rf,
@ -261,99 +261,99 @@ protected:
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
float gclk_time, float gclk_time,
float time_offset, float time_offset,
bool clk_used_as_data); bool clk_used_as_data) const;
void reportClkSrcLatency(Arrival insertion, void reportClkSrcLatency(Arrival insertion,
float clk_time, float clk_time,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportPathLine(const Path *path, void reportPathLine(const Path *path,
Delay incr, Delay incr,
Arrival time, Arrival time,
const char *line_case); const char *line_case) const;
void reportCommonClkPessimism(const PathEnd *end, void reportCommonClkPessimism(const PathEnd *end,
Arrival &clk_arrival); Arrival &clk_arrival) const ;
void reportClkUncertainty(const PathEnd *end, void reportClkUncertainty(const PathEnd *end,
Arrival &clk_arrival); Arrival &clk_arrival) const ;
void reportClkLine(const Clock *clk, void reportClkLine(const Clock *clk,
const char *clk_name, const char *clk_name,
const RiseFall *clk_rf, const RiseFall *clk_rf,
Arrival clk_time, Arrival clk_time,
const MinMax *min_max); const MinMax *min_max) const ;
void reportClkLine(const Clock *clk, void reportClkLine(const Clock *clk,
const char *clk_name, const char *clk_name,
const RiseFall *clk_rf, const RiseFall *clk_rf,
Arrival prev_time, Arrival prev_time,
Arrival clk_time, Arrival clk_time,
const MinMax *min_max); const MinMax *min_max) const ;
void reportRequired(const PathEnd *end, void reportRequired(const PathEnd *end,
string margin_msg); string margin_msg) const ;
void reportSlack(const PathEnd *end); void reportSlack(const PathEnd *end) const ;
void reportSlack(Slack slack); void reportSlack(Slack slack) const ;
void reportSpaceSlack(PathEnd *end, void reportSpaceSlack(const PathEnd *end,
string &line); string &line) const ;
void reportSpaceSlack(Slack slack, void reportSpaceSlack(Slack slack,
string &line); string &line) const ;
void reportSrcPathArrival(const PathEnd *end, void reportSrcPathArrival(const PathEnd *end,
PathExpanded &expanded); const PathExpanded &expanded) const ;
void reportPath(const PathEnd *end, void reportPath(const PathEnd *end,
PathExpanded &expanded); const PathExpanded &expanded) const;
void reportPathFull(const Path *path); void reportPathFull(const Path *path) const;
void reportPathHeader(); void reportPathHeader() const;
void reportPath1(const Path *path, void reportPath1(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data, bool clk_used_as_data,
float time_offset); float time_offset) const;
void reportPath2(const Path *path, void reportPath2(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data, bool clk_used_as_data,
float time_offset); float time_offset) const;
void reportPath3(const Path *path, void reportPath3(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data, bool clk_used_as_data,
bool report_clk_path, bool report_clk_path,
Arrival prev_time, Arrival prev_time,
float time_offset); float time_offset) const;
void reportPath4(const Path *path, void reportPath4(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
bool clk_used_as_data, bool clk_used_as_data,
bool skip_first_path, bool skip_first_path,
bool skip_last_path, bool skip_last_path,
float time_offset); float time_offset) const;
void reportPath5(const Path *path, void reportPath5(const Path *path,
PathExpanded &expanded, const PathExpanded &expanded,
size_t path_first_index, size_t path_first_index,
size_t path_last_index, size_t path_last_index,
bool propagated_clk, bool propagated_clk,
bool report_clk_path, bool report_clk_path,
Arrival prev_time, Arrival prev_time,
float time_offset); float time_offset) const;
void reportHierPinsThru(const Path *path, void reportHierPinsThru(const Path *path,
const TimingArc *prev_arc); const TimingArc *prev_arc) const;
void reportInputExternalDelay(const Path *path, void reportInputExternalDelay(const Path *path,
float time_offset); float time_offset) const;
void reportLine(const char *what, void reportLine(const char *what,
Delay total, Delay total,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLineNegative(const char *what, void reportLineNegative(const char *what,
Delay total, Delay total,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLine(const char *what, void reportLine(const char *what,
Delay total, Delay total,
const EarlyLate *early_late, const EarlyLate *early_late,
const RiseFall *rf); const RiseFall *rf) const;
void reportLine(const char *what, void reportLine(const char *what,
Delay incr, Delay incr,
Delay total, Delay total,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLine(const char *what, void reportLine(const char *what,
Delay incr, Delay incr,
Delay total, Delay total,
const EarlyLate *early_late, const EarlyLate *early_late,
const RiseFall *rf); const RiseFall *rf) const;
void reportLine(const char *what, void reportLine(const char *what,
Slew slew, Slew slew,
Delay incr, Delay incr,
Delay total, Delay total,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLine(const char *what, void reportLine(const char *what,
float cap, float cap,
Slew slew, Slew slew,
@ -364,106 +364,106 @@ protected:
const EarlyLate *early_late, const EarlyLate *early_late,
const RiseFall *rf, const RiseFall *rf,
string src_attr, string src_attr,
const char *line_case); const char *line_case) const;
void reportLineTotal(const char *what, void reportLineTotal(const char *what,
Delay incr, Delay incr,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLineTotalMinus(const char *what, void reportLineTotalMinus(const char *what,
Delay decr, Delay decr,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportLineTotal1(const char *what, void reportLineTotal1(const char *what,
Delay incr, Delay incr,
bool incr_with_minus, bool incr_with_minus,
const EarlyLate *early_late); const EarlyLate *early_late) const;
void reportDashLineTotal(); void reportDashLineTotal() const;
void reportDescription(const char *what, void reportDescription(const char *what,
string &result); string &result) const;
void reportDescription(const char *what, void reportDescription(const char *what,
bool first_field, bool first_field,
bool last_field, bool last_field,
string &result); string &result) const;
void reportFieldTime(float value, void reportFieldTime(float value,
ReportField *field, ReportField *field,
string &result); string &result) const;
void reportSpaceFieldTime(float value, void reportSpaceFieldTime(float value,
string &result); string &result) const;
void reportSpaceFieldDelay(Delay value, void reportSpaceFieldDelay(Delay value,
const EarlyLate *early_late, const EarlyLate *early_late,
string &result); string &result) const;
void reportFieldDelayMinus(Delay value, void reportFieldDelayMinus(Delay value,
const EarlyLate *early_late, const EarlyLate *early_late,
ReportField *field, const ReportField *field,
string &result); string &result) const;
void reportTotalDelay(Delay value, void reportTotalDelay(Delay value,
const EarlyLate *early_late, const EarlyLate *early_late,
string &result); string &result) const;
void reportFieldDelay(Delay value, void reportFieldDelay(Delay value,
const EarlyLate *early_late, const EarlyLate *early_late,
ReportField *field, const ReportField *field,
string &result); string &result) const;
void reportField(float value, void reportField(float value,
const ReportField *field, const ReportField *field,
string &result); string &result) const;
void reportField(const char *value, void reportField(const char *value,
const ReportField *field, const ReportField *field,
string &result); string &result) const;
void reportFieldBlank(const ReportField *field, void reportFieldBlank(const ReportField *field,
string &result); string &result) const;
void reportDashLine(); void reportDashLine() const;
void reportDashLine(int line_width); void reportDashLine(int line_width) const;
void reportBlankLine(); void reportBlankLine() const;
string descriptionField(Vertex *vertex); string descriptionField(const Vertex *vertex) const;
string descriptionField(const Pin *pin); string descriptionField(const Pin *pin) const;
string descriptionNet(const Pin *pin); string descriptionNet(const Pin *pin) const;
bool reportClkPath() const; bool reportClkPath() const;
string clkName(const Clock *clk, string clkName(const Clock *clk,
bool inverted); bool inverted) const;
bool hasExtInputDriver(const Pin *pin, bool hasExtInputDriver(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max) const;
float drvrFanout(Vertex *drvr, float drvrFanout(Vertex *drvr,
const Corner *corner, const Corner *corner,
const MinMax *min_max); const MinMax *min_max) const;
const char *mpwCheckHiLow(MinPulseWidthCheck *check); const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const;
void reportSkewClkPath(const char *arrival_msg, void reportSkewClkPath(const char *arrival_msg,
const PathVertex *clk_path); const PathVertex *clk_path) const;
const char *edgeRegLatchDesc(Edge *edge, const char *edgeRegLatchDesc(const Edge *edge,
TimingArc *arc); const TimingArc *arc) const;
const char *checkRegLatchDesc(const TimingRole *role, const char *checkRegLatchDesc(const TimingRole *role,
const RiseFall *clk_rf) const; const RiseFall *clk_rf) const;
const char *regDesc(const RiseFall *clk_rf) const; const char *regDesc(const RiseFall *clk_rf) const;
const char *latchDesc(const RiseFall *clk_rf) const; const char *latchDesc(const RiseFall *clk_rf) const;
void pathClkPath(const Path *path, void pathClkPath(const Path *path,
PathRef &clk_path) const; const PathRef &clk_path) const;
bool isPropagated(const Path *clk_path); bool isPropagated(const Path *clk_path) const;
bool isPropagated(const Path *clk_path, bool isPropagated(const Path *clk_path,
const Clock *clk); const Clock *clk) const;
bool pathFromClkPin(PathExpanded &expanded); bool pathFromClkPin(const PathExpanded &expanded) const;
bool pathFromClkPin(const Path *path, bool pathFromClkPin(const Path *path,
const Pin *start_pin); const Pin *start_pin) const;
void latchPaths(const Path *path, void latchPaths(const Path *path,
// Return values. // Return values.
PathRef &d_path, PathRef &d_path,
PathRef &q_path, PathRef &q_path,
Edge *&d_q_edge) const; Edge *&d_q_edge) const;
bool nextArcAnnotated(const PathRef *next_path, bool nextArcAnnotated(const PathRef *next_path,
size_t next_index, size_t next_index,
PathExpanded &expanded, const PathExpanded &expanded,
DcalcAPIndex ap_index); DcalcAPIndex ap_index) const;
float tgtClkInsertionOffet(const Path *clk_path, float tgtClkInsertionOffet(const Path *clk_path,
const EarlyLate *early_late, const EarlyLate *early_late,
PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap) const;
// InputDelay used to seed path root. // InputDelay used to seed path root.
InputDelay *pathInputDelay(const Path *path) const; InputDelay *pathInputDelay(const Path *path) const;
void pathInputDelayRefPath(const Path *path, void pathInputDelayRefPath(const Path *path,
InputDelay *input_delay, const InputDelay *input_delay,
// Return value. // Return value.
PathRef &ref_path); PathRef &ref_path) const;
const char *asRisingFalling(const RiseFall *rf); const char *asRisingFalling(const RiseFall *rf) const;
const char *asRiseFall(const RiseFall *rf); const char *asRiseFall(const RiseFall *rf) const;
Delay delayIncr(Delay time, Delay delayIncr(Delay time,
Delay prev, Delay prev,
const MinMax *min_max); const MinMax *min_max) const;
// Path options. // Path options.
ReportPathFormat format_; ReportPathFormat format_;

View File

@ -2997,9 +2997,9 @@ Search::clkInfoCount() const
} }
ArcDelay ArcDelay
Search::deratedDelay(Vertex *from_vertex, Search::deratedDelay(const Vertex *from_vertex,
TimingArc *arc, const TimingArc *arc,
Edge *edge, const Edge *edge,
bool is_clk, bool is_clk,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {
@ -3011,9 +3011,9 @@ Search::deratedDelay(Vertex *from_vertex,
} }
float float
Search::timingDerate(Vertex *from_vertex, Search::timingDerate(const Vertex *from_vertex,
TimingArc *arc, const TimingArc *arc,
Edge *edge, const Edge *edge,
bool is_clk, bool is_clk,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap)
{ {

View File

@ -321,18 +321,6 @@ required_count()
return Sta::sta()->requiredCount(); return Sta::sta()->requiredCount();
} }
int
graph_arrival_count()
{
return Sta::sta()->graph()->arrivalCount();
}
int
graph_required_count()
{
return Sta::sta()->graph()->requiredCount();
}
int int
endpoint_violation_count(const MinMax *min_max) endpoint_violation_count(const MinMax *min_max)
{ {

View File

@ -2574,7 +2574,7 @@ Sta::reportPathEnds(PathEndSeq *ends)
} }
void void
Sta::reportPath(Path *path) Sta::reportPath(const Path *path)
{ {
report_path_->reportPath(path); report_path_->reportPath(path);
} }
@ -3177,7 +3177,7 @@ bool
MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end) MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end)
{ {
PathExpanded expanded(path_end->path(), sta_); PathExpanded expanded(path_end->path(), sta_);
PathRef *start = expanded.startPath(); const PathRef *start = expanded.startPath();
Graph *graph = sta_->graph(); Graph *graph = sta_->graph();
const Pin *first_pin = start->pin(graph); const Pin *first_pin = start->pin(graph);
Network *network = sta_->network(); Network *network = sta_->network();

View File

@ -220,7 +220,7 @@ WritePathSpice::writeSpice()
void void
WritePathSpice::writeHeader() WritePathSpice::writeHeader()
{ {
Path *start_path = path_expanded_.startPath(); const Path *start_path = path_expanded_.startPath();
string title = stdstrPrint("Path from %s %s to %s %s", string title = stdstrPrint("Path from %s %s to %s %s",
network_->pathName(start_path->pin(this)), network_->pathName(start_path->pin(this)),
start_path->transition(this)->asString(), start_path->transition(this)->asString(),

View File

@ -44,7 +44,8 @@ void
sta::VerilogParse::error(const location_type &loc, sta::VerilogParse::error(const location_type &loc,
const string &msg) const string &msg)
{ {
reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str()); reader->report()->fileError(164,reader->filename(),loc.begin.line,
"%s",msg.c_str());
} }
%} %}
@ -57,11 +58,7 @@ sta::VerilogParse::error(const location_type &loc,
%define parse.assert %define parse.assert
%parse-param { VerilogScanner *scanner } %parse-param { VerilogScanner *scanner }
%parse-param { VerilogReader *reader } %parse-param { VerilogReader *reader }
%define api.parser.class {VerilogParse}
// bison 3.0.4 for centos7
%define parser_class_name {VerilogParse}
// bison 3.3.2
//%define api.parser.class {VerilogParse}
%union { %union {
int ival; int ival;

299
verilog/VerilogReader.hh Normal file
View File

@ -0,0 +1,299 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include <string>
#include "StringSet.hh"
#include "Vector.hh"
#include "Map.hh"
#include "NetworkClass.hh"
namespace sta {
class VerilogScanner;
class VerilogParse;
class Debug;
class Report;
class VerilogAttrEntry;
class VerilogAttrStmt;
class VerilogReader;
class VerilogStmt;
class VerilogNet;
class VerilogNetScalar;
class VerilogModule;
class VerilogInst;
class VerilogModuleInst;
class VerilogLibertyInst;
class VerilogDcl;
class VerilogDclBus;
class VerilogDclArg;
class VerilogAssign;
class VerilogNetConcat;
class VerilogNetConstant;
class VerilogNetBitSelect;
class VerilogNetPartSelect;
class StringRegistry;
class VerilogBindingTbl;
class VerilogNetNameIterator;
class VerilogNetPortRef;
class VerilogError;
class LibertyCell;
typedef Map<Cell*, VerilogModule*> VerilogModuleMap;
typedef Vector<VerilogStmt*> VerilogStmtSeq;
typedef Vector<VerilogNet*> VerilogNetSeq;
typedef Vector<VerilogDclArg*> VerilogDclArgSeq;
typedef Vector<VerilogAttrStmt*> VerilogAttrStmtSeq;
typedef Vector<VerilogAttrEntry*> VerilogAttrEntrySeq;
typedef Vector<VerilogError*> VerilogErrorSeq;
using std::string;
using std::vector;
using std::set;
class VerilogReader
{
public:
VerilogReader(NetworkReader *network);
~VerilogReader();
bool read(const char *filename);
void makeModule(const string *module_name,
VerilogNetSeq *ports,
VerilogStmtSeq *stmts,
VerilogAttrStmtSeq *attr_stmts,
int line);
void makeModule(const string *module_name,
VerilogStmtSeq *port_dcls,
VerilogStmtSeq *stmts,
VerilogAttrStmtSeq *attr_stmts,
int line);
VerilogDcl *makeDcl(PortDirection *dir,
VerilogDclArgSeq *args,
VerilogAttrStmtSeq *attr_stmts,
int line);
VerilogDcl *makeDcl(PortDirection *dir,
VerilogDclArg *arg,
VerilogAttrStmtSeq *attr_stmts,
int line);
VerilogDclArg *makeDclArg(const string *net_name);
VerilogDclArg*makeDclArg(VerilogAssign *assign);
VerilogDclBus *makeDclBus(PortDirection *dir,
int from_index,
int to_index,
VerilogDclArg *arg,
VerilogAttrStmtSeq *attr_stmts,
int line);
VerilogDclBus *makeDclBus(PortDirection *dir,
int from_index,
int to_index,
VerilogDclArgSeq *args,
VerilogAttrStmtSeq *attr_stmts,
int line);
VerilogInst *makeModuleInst(const string *module_name,
const string *inst_name,
VerilogNetSeq *pins,
VerilogAttrStmtSeq *attr_stmts,
const int line);
VerilogAssign *makeAssign(VerilogNet *lhs,
VerilogNet *rhs,
int line);
VerilogNetScalar *makeNetScalar(const string *name);
VerilogNetPortRef *makeNetNamedPortRefScalarNet(const string *port_vname);
VerilogNetPortRef *makeNetNamedPortRefScalarNet(const string *port_name,
const string *net_name);
VerilogNetPortRef *makeNetNamedPortRefBitSelect(const string *port_name,
const string *bus_name,
int index);
VerilogNetPortRef *makeNetNamedPortRefScalar(const string *port_name,
VerilogNet *net);
VerilogNetPortRef *makeNetNamedPortRefBit(const string *port_name,
int index,
VerilogNet *net);
VerilogNetPortRef *makeNetNamedPortRefPart(const string *port_name,
int from_index,
int to_index,
VerilogNet *net);
VerilogNetConcat *makeNetConcat(VerilogNetSeq *nets);
VerilogNetConstant *makeNetConstant(const string *constant,
int line);
VerilogNetBitSelect *makeNetBitSelect(const string *name,
int index);
VerilogNetPartSelect *makeNetPartSelect(const string *name,
int from_index,
int to_index);
VerilogModule *module(Cell *cell);
Instance *linkNetwork(const char *top_cell_name,
bool make_black_boxes);
const char *filename() const { return filename_.c_str(); }
void incrLine();
Report *report() const { return report_; }
void error(int id,
const char *filename,
int line,
const char *fmt, ...);
void warn(int id,
const char *filename,
int line,
const char *fmt, ...);
const string &zeroNetName() const { return zero_net_name_; }
const string &oneNetName() const { return one_net_name_; }
void deleteModules();
void reportStmtCounts();
const string &constant10Max() const { return constant10_max_; }
protected:
void init(const char *filename);
void makeCellPorts(Cell *cell,
VerilogModule *module,
VerilogNetSeq *ports);
Port *makeCellPort(Cell *cell,
VerilogModule *module,
const string &port_name);
void makeNamedPortRefCellPorts(Cell *cell,
VerilogModule *module,
VerilogNet *mod_port,
StdStringSet &port_names);
void checkModuleDcls(VerilogModule *module,
set<string> &port_names);
void makeModuleInstBody(VerilogModule *module,
Instance *inst,
VerilogBindingTbl *bindings,
bool make_black_boxes);
void makeModuleInstNetwork(VerilogModuleInst *mod_inst,
Instance *parent,
VerilogModule *parent_module,
VerilogBindingTbl *parent_bindings,
bool make_black_boxes);
void makeLibertyInst(VerilogLibertyInst *lib_inst,
Instance *parent,
VerilogModule *parent_module,
VerilogBindingTbl *parent_bindings);
void bindGlobalNets(VerilogBindingTbl *bindings);
void makeNamedInstPins1(Cell *cell,
Instance *inst,
VerilogModuleInst *mod_inst,
VerilogBindingTbl *bindings,
Instance *parent,
VerilogBindingTbl *parent_bindings,
bool is_leaf);
void makeNamedInstPins(Cell *cell,
Instance *inst,
VerilogModuleInst *mod_inst,
VerilogBindingTbl *bindings,
Instance *parent,
VerilogModule *parent_module,
VerilogBindingTbl *parent_bindings,
bool is_leaf);
void makeOrderedInstPins(Cell *cell,
Instance *inst,
VerilogModuleInst *mod_inst,
VerilogBindingTbl *bindings,
Instance *parent,
VerilogModule *parent_module,
VerilogBindingTbl *parent_bindings,
bool is_leaf);
void mergeAssignNet(VerilogAssign *assign,
VerilogModule *module,
Instance *inst,
VerilogBindingTbl *bindings);
void makeInstPin(Instance *inst,
Port *port,
VerilogNetNameIterator *net_name_iter,
VerilogBindingTbl *bindings,
Instance *parent,
VerilogBindingTbl *parent_bindings,
bool is_leaf);
void makeInstPin(Instance *inst,
Port *port,
const string &net_name,
VerilogBindingTbl *bindings,
Instance *parent,
VerilogBindingTbl *parent_bindings,
bool is_leaf);
void linkWarn(int id,
const char *filename,
int line,
const char *msg, ...)
__attribute__((format (printf, 5, 6)));
void linkError(int id,
const char *filename,
int line,
const char *msg, ...)
__attribute__((format (printf, 5, 6)));
bool reportLinkErrors();
bool haveLinkErrors();
Cell *makeBlackBox(VerilogModuleInst *mod_inst,
VerilogModule *parent_module);
void makeBlackBoxNamedPorts(Cell *cell,
VerilogModuleInst *mod_inst,
VerilogModule *parent_module);
void makeBlackBoxOrderedPorts(Cell *cell,
VerilogModuleInst *mod_inst,
VerilogModule *parent_module);
bool isBlackBox(Cell *cell);
bool hasScalarNamedPortRefs(LibertyCell *liberty_cell,
VerilogNetSeq *pins);
string filename_;
Report *report_;
Debug *debug_;
NetworkReader *network_;
Library *library_;
int black_box_index_;
VerilogModuleMap module_map_;
VerilogErrorSeq link_errors_;
const string zero_net_name_;
const string one_net_name_;
string constant10_max_;
ViewType *view_type_;
bool report_stmt_stats_;
int module_count_;
int inst_mod_count_;
int inst_lib_count_;
int inst_lib_net_arrays_;
int port_names_;
int inst_module_names_;
int inst_names_;
int dcl_count_;
int dcl_bus_count_;
int dcl_arg_count_;
int net_scalar_count_;
int net_scalar_names_;
int net_bus_names_;
int net_part_select_count_;
int net_bit_select_count_;
int net_port_ref_scalar_count_;
int net_port_ref_scalar_net_count_;
int net_port_ref_bit_count_;
int net_port_ref_part_count_;
int net_constant_count_;
int assign_count_;
int concat_count_;
};
} // namespace sta

View File

@ -24,15 +24,15 @@
#pragma once #pragma once
#include "VerilogLocation.hh"
#include "VerilogParse.hh"
#ifndef __FLEX_LEXER_H #ifndef __FLEX_LEXER_H
#undef yyFlexLexer #undef yyFlexLexer
#define yyFlexLexer VerilogFlexLexer #define yyFlexLexer VerilogFlexLexer
#include <FlexLexer.h> #include <FlexLexer.h>
#endif #endif
#include "VerilogLocation.hh"
#include "VerilogParse.hh"
namespace sta { namespace sta {
class Report; class Report;