Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
2c5df8ccbc
|
|
@ -101,8 +101,7 @@ set(STA_SOURCE
|
|||
liberty/LeakagePower.cc
|
||||
liberty/Liberty.cc
|
||||
liberty/LibertyBuilder.cc
|
||||
liberty/LibertyExpr.cc
|
||||
liberty/LibertyExprPvt.hh
|
||||
liberty/LibExprReader.cc
|
||||
liberty/LibertyParser.cc
|
||||
liberty/LibertyReader.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.
|
||||
#find_package(FLEX 2.6.4)
|
||||
find_package(FLEX)
|
||||
find_package(BISON)
|
||||
|
||||
# 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)
|
||||
find_package(BISON REQUIRED 3.2)
|
||||
|
||||
# Verilog scan/parse.
|
||||
flex_target(VerilogLex ${STA_HOME}/verilog/VerilogLex.ll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/VerilogLex.cc)
|
||||
bison_target(VerilogParse ${STA_HOME}/verilog/VerilogParse.yy
|
||||
${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")
|
||||
${CMAKE_CURRENT_BINARY_DIR}/VerilogParse.cc)
|
||||
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.
|
||||
flex_target(SdfLex ${STA_HOME}/sdf/SdfLex.ll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SdfLex.cc)
|
||||
bison_target(SdfParse ${STA_HOME}/sdf/SdfParse.yy
|
||||
${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")
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc)
|
||||
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.
|
||||
flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc
|
||||
COMPILE_FLAGS --prefix=SaifLex_
|
||||
)
|
||||
bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc
|
||||
COMPILE_FLAGS --name-prefix=SaifParse_
|
||||
)
|
||||
flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc)
|
||||
bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc)
|
||||
add_flex_bison_dependency(SaifLex SaifParse)
|
||||
|
||||
################################################################
|
||||
|
|
@ -497,8 +483,8 @@ target_sources(OpenSTA
|
|||
|
||||
${STA_TCL_INIT}
|
||||
|
||||
${FLEX_LibertyExprLex_OUTPUTS}
|
||||
${BISON_LibertyExprParse_OUTPUTS}
|
||||
${FLEX_LibExprLex_OUTPUTS}
|
||||
${BISON_LibExprParse_OUTPUTS}
|
||||
${FLEX_LibertyLex_OUTPUTS}
|
||||
${BISON_LibertyParse_OUTPUTS}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ FROM centos:centos7 AS base-dependencies
|
|||
LABEL author="James Cherry"
|
||||
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 \
|
||||
&& 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 \
|
||||
|
|
@ -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 \
|
||||
&& 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 \
|
||||
&& 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
|
||||
|
||||
# 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
|
||||
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 && \
|
||||
rm cudd-3.0.0.tar.gz
|
||||
|
||||
# Build CUDD
|
||||
RUN source /opt/rh/devtoolset-8/enable && \
|
||||
RUN source /opt/rh/devtoolset-11/enable && \
|
||||
cd cudd-3.0.0 && \
|
||||
mkdir ../cudd && \
|
||||
./configure && \
|
||||
make -j`nproc`
|
||||
make -j`nproc` && \
|
||||
make install
|
||||
|
||||
FROM base-dependencies AS builder
|
||||
|
||||
|
|
@ -33,9 +46,9 @@ WORKDIR /OpenSTA
|
|||
|
||||
# Build
|
||||
RUN rm -rf build && mkdir build
|
||||
RUN source /opt/rh/devtoolset-8/enable && \
|
||||
RUN source /opt/rh/devtoolset-11/enable && \
|
||||
cd build && \
|
||||
cmake3 -DCUDD_DIR=../cudd-3.0.0 .. && \
|
||||
cmake3 .. && \
|
||||
make -j`nproc`
|
||||
|
||||
# Run sta on entry
|
||||
|
|
|
|||
|
|
@ -321,8 +321,8 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex,
|
|||
Port *port = network_->port(drvr_pin);
|
||||
drive = sdc_->findInputDrive(port);
|
||||
}
|
||||
for (auto rf : RiseFall::range()) {
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
if (drive) {
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
const LibertyCell *drvr_cell;
|
||||
|
|
@ -350,8 +350,8 @@ void
|
|||
GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
InputDrive *drive,
|
||||
DcalcAnalysisPt *dcalc_ap,
|
||||
const InputDrive *drive,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc)
|
||||
{
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
|
|
@ -397,7 +397,7 @@ void
|
|||
GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
DcalcAnalysisPt *dcalc_ap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc)
|
||||
{
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
|
|
@ -429,8 +429,8 @@ GraphDelayCalc::seedLoadSlew(Vertex *vertex)
|
|||
vertex->name(sdc_network_));
|
||||
ClockSet *clks = sdc_->findLeafPinClocks(pin);
|
||||
initSlew(vertex);
|
||||
for (auto rf : RiseFall::range()) {
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
if (!vertex->slewAnnotated(rf, slew_min_max)) {
|
||||
float slew = 0.0;
|
||||
|
|
@ -807,11 +807,11 @@ GraphDelayCalc::initLoadSlews(Vertex *drvr_vertex)
|
|||
Edge *wire_edge = edge_iter.next();
|
||||
if (wire_edge->isWire()) {
|
||||
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();
|
||||
Slew slew_init_value(slew_min_max->initValue());
|
||||
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))
|
||||
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,
|
||||
delay_exists);
|
||||
}
|
||||
for (auto rf : RiseFall::range()) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
if (!delay_exists[rf->index()])
|
||||
zeroSlewAndWireDelays(drvr_vertex, rf);
|
||||
}
|
||||
|
|
@ -856,10 +856,10 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
|
|||
void
|
||||
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();
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
for (auto rf : RiseFall::range()) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
if (!vertex->slewAnnotated(rf, slew_min_max))
|
||||
graph_->setSlew(vertex, rf, ap_index, default_slew);
|
||||
}
|
||||
|
|
@ -895,7 +895,7 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
|
|||
Vertex *from_vertex = edge->from(graph_);
|
||||
const TimingArcSet *arc_set = edge->timingArcSet();
|
||||
bool delay_changed = false;
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const TimingArc *arc : arc_set->arcs()) {
|
||||
delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc,
|
||||
dcalc_ap, arc_delay_calc,
|
||||
|
|
@ -982,7 +982,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
|
|||
ArcDelayCalc *arc_delay_calc)
|
||||
{
|
||||
ArcDcalcArgSeq dcalc_args;
|
||||
for (auto drvr_vertex1 : multi_drvr->drvrs()) {
|
||||
for (Vertex *drvr_vertex1 : multi_drvr->drvrs()) {
|
||||
Edge *edge1 = nullptr;
|
||||
const TimingArc *arc1 = nullptr;
|
||||
if (drvr_vertex1 == drvr_vertex) {
|
||||
|
|
@ -1212,7 +1212,7 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
|||
{
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
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);
|
||||
load_cap = min_max->minMax(cap, load_cap);
|
||||
}
|
||||
|
|
@ -1359,8 +1359,8 @@ GraphDelayCalc::netCaps(const Pin *drvr_pin,
|
|||
void
|
||||
GraphDelayCalc::initSlew(Vertex *vertex)
|
||||
{
|
||||
for (auto rf : RiseFall::range()) {
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const RiseFall *rf : RiseFall::range()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
if (!vertex->slewAnnotated(rf, slew_min_max)) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
|
|
@ -1374,7 +1374,7 @@ void
|
|||
GraphDelayCalc::zeroSlewAndWireDelays(Vertex *drvr_vertex,
|
||||
const RiseFall *rf)
|
||||
{
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
|
||||
// Init drvr slew.
|
||||
|
|
@ -1406,11 +1406,11 @@ GraphDelayCalc::initWireDelays(Vertex *drvr_vertex)
|
|||
while (edge_iter.hasNext()) {
|
||||
Edge *wire_edge = edge_iter.next();
|
||||
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();
|
||||
Delay delay_init_value(delay_min_max->initValue());
|
||||
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))
|
||||
graph_->setWireArcDelay(wire_edge, rf, ap_index, delay_init_value);
|
||||
}
|
||||
|
|
@ -1466,7 +1466,7 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
|
|||
const Pin *related_out_pin = 0;
|
||||
if (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();
|
||||
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
|
||||
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf,
|
||||
|
|
@ -1583,7 +1583,7 @@ GraphDelayCalc::minPeriod(const Pin *pin,
|
|||
{
|
||||
exists = false;
|
||||
const MinMax *min_max = MinMax::max();
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const DcalcAnalysisPt *dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
// Sdf annotation.
|
||||
float min_period1 = 0.0;
|
||||
bool exists1 = false;
|
||||
|
|
@ -1639,11 +1639,11 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
|
|||
int count = RiseFall::index_count * corners->dcalcAnalysisPtCount();
|
||||
net_caps_.resize(count);
|
||||
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();
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
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 index = ap_index * RiseFall::index_count + drvr_rf_index;
|
||||
NetCaps &net_caps = net_caps_[index];
|
||||
|
|
|
|||
|
|
@ -83,18 +83,6 @@ private:
|
|||
|
||||
%inline %{
|
||||
|
||||
int
|
||||
graph_vertex_count()
|
||||
{
|
||||
return Sta::sta()->ensureGraph()->vertexCount();
|
||||
}
|
||||
|
||||
int
|
||||
graph_edge_count()
|
||||
{
|
||||
return Sta::sta()->ensureGraph()->edgeCount();
|
||||
}
|
||||
|
||||
int
|
||||
graph_arc_count()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ public:
|
|||
virtual float delay() const { return 0.0; }
|
||||
virtual const char *name() const { return nullptr; }
|
||||
virtual bool isDefault() const { return false; }
|
||||
virtual bool ignoreClkLatency() { return false; }
|
||||
virtual bool ignoreClkLatency() const { return false; }
|
||||
|
||||
protected:
|
||||
virtual const char *typeString() const = 0;
|
||||
|
|
@ -210,7 +210,7 @@ public:
|
|||
virtual float delay() const { return delay_; }
|
||||
virtual int typePriority() const;
|
||||
virtual bool tighterThan(ExceptionPath *exception) const;
|
||||
virtual bool ignoreClkLatency() { return ignore_clk_latency_; }
|
||||
virtual bool ignoreClkLatency() const { return ignore_clk_latency_; }
|
||||
|
||||
protected:
|
||||
bool ignore_clk_latency_;
|
||||
|
|
|
|||
|
|
@ -116,8 +116,6 @@ public:
|
|||
Required *requireds(Vertex *vertex);
|
||||
void deleteRequireds(Vertex *vertex,
|
||||
uint32_t count);
|
||||
size_t arrivalCount() const { return arrivals_.size(); }
|
||||
size_t requiredCount() const { return requireds_.size(); }
|
||||
PathVertexRep *makePrevPaths(Vertex *vertex,
|
||||
uint32_t count);
|
||||
PathVertexRep *prevPaths(Vertex *vertex) const;
|
||||
|
|
@ -217,8 +215,8 @@ public:
|
|||
void removeDelaySlewAnnotations();
|
||||
VertexSet *regClkVertices() { return reg_clk_vertices_; }
|
||||
|
||||
static const int vertex_level_bits = 24;
|
||||
static const int vertex_level_max = (1<<vertex_level_bits)-1;
|
||||
static constexpr int vertex_level_bits = 24;
|
||||
static constexpr int vertex_level_max = (1<<vertex_level_bits)-1;
|
||||
|
||||
protected:
|
||||
void makeVerticesAndEdges();
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ typedef vector<Slew> SlewSeq;
|
|||
static constexpr int level_max = std::numeric_limits<Level>::max();
|
||||
|
||||
// 16,777,215 tags
|
||||
static const int tag_group_index_bits = 24;
|
||||
static const 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 tag_group_index_bits = 24;
|
||||
static constexpr TagGroupIndex tag_group_index_max = (1<<tag_group_index_bits)-1;
|
||||
static constexpr int slew_annotated_bits = MinMax::index_count * RiseFall::index_count;
|
||||
|
||||
// Bit shifts used to mark vertices in a Bfs queue.
|
||||
enum class BfsIndex { dcalc, arrival, required, other, bits };
|
||||
|
|
|
|||
|
|
@ -144,13 +144,13 @@ protected:
|
|||
void seedNoDrvrSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
DcalcAnalysisPt *dcalc_ap,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
InputDrive *drive,
|
||||
DcalcAnalysisPt *dcalc_ap,
|
||||
const InputDrive *drive,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc);
|
||||
void seedLoadSlew(Vertex *vertex);
|
||||
void setInputPortWireDelays(Vertex *vertex);
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ public:
|
|||
void driveResistance(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
float &res,
|
||||
bool &exists);
|
||||
bool &exists) const;
|
||||
bool hasDriveResistance(const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
bool driveResistanceMinMaxEqual(const RiseFall *rf);
|
||||
const MinMax *min_max) const;
|
||||
bool driveResistanceMinMaxEqual(const RiseFall *rf) const;
|
||||
void setDriveCell(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const LibertyPort *from_port,
|
||||
|
|
@ -68,18 +68,18 @@ public:
|
|||
const LibertyCell *&cell,
|
||||
const LibertyPort *&from_port,
|
||||
float *&from_slews,
|
||||
const LibertyPort *&to_port);
|
||||
const LibertyPort *&to_port) const;
|
||||
InputDriveCell *driveCell(const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
bool hasDriveCell(const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
// True if rise/fall/min/max drive cells are equal.
|
||||
bool driveCellsEqual();
|
||||
bool driveCellsEqual() const;
|
||||
void slew(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
float &slew,
|
||||
bool &exists);
|
||||
RiseFallMinMax *slews() { return &slews_; }
|
||||
bool &exists) const;
|
||||
const RiseFallMinMax *slews() const { return &slews_; }
|
||||
|
||||
private:
|
||||
RiseFallMinMax slews_;
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ public:
|
|||
const RiseFall *transition(const StaState *sta) const;
|
||||
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
|
||||
PathAPIndex pathIndex(const StaState *sta) const;
|
||||
virtual void reportShort(ReportPath *report) const = 0;
|
||||
virtual void reportFull(ReportPath *report) const = 0;
|
||||
virtual void reportShort(const ReportPath *report) const = 0;
|
||||
virtual void reportFull(const ReportPath *report) const = 0;
|
||||
|
||||
// Predicates for PathEnd type.
|
||||
// Default methods overridden by respective types.
|
||||
|
|
@ -228,8 +228,8 @@ public:
|
|||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual PathEnd *copy();
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isUnconstrained() const;
|
||||
virtual Required requiredTime(const StaState *sta) const;
|
||||
virtual Required requiredTimeOffset(const StaState *sta) const;
|
||||
|
|
@ -327,8 +327,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isCheck() const { return true; }
|
||||
virtual ArcDelay margin(const StaState *sta) const;
|
||||
virtual float macroClkTreeDelay(const StaState *sta) const;
|
||||
|
|
@ -373,8 +373,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
PathVertex *latchDisable();
|
||||
const PathVertex *latchDisable() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual TimingRole *checkRole(const StaState *sta) const;
|
||||
virtual Required requiredTime(const StaState *sta) const;
|
||||
virtual Arrival borrow(const StaState *sta) const;
|
||||
|
|
@ -432,8 +432,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isOutputDelay() const { return true; }
|
||||
virtual ArcDelay margin(const StaState *sta) const;
|
||||
virtual TimingRole *checkRole(const StaState *sta) const;
|
||||
|
|
@ -478,8 +478,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isGatedClock() const { return true; }
|
||||
virtual ArcDelay margin(const StaState *) const { return margin_; }
|
||||
virtual TimingRole *checkRole(const StaState *sta) const;
|
||||
|
|
@ -510,8 +510,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isDataCheck() const { return true; }
|
||||
virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
|
||||
virtual TimingRole *checkRole(const StaState *sta) const;
|
||||
|
|
@ -566,8 +566,8 @@ public:
|
|||
virtual PathEnd *copy();
|
||||
virtual Type type() const;
|
||||
virtual const char *typeName() const;
|
||||
virtual void reportShort(ReportPath *report) const;
|
||||
virtual void reportFull(ReportPath *report) const;
|
||||
virtual void reportShort(const ReportPath *report) const;
|
||||
virtual void reportFull(const ReportPath *report) const;
|
||||
virtual bool isPathDelay() const { return true; }
|
||||
virtual TimingRole *checkRole(const StaState *sta) const;
|
||||
virtual bool pathDelayMarginIsExternal() const;
|
||||
|
|
|
|||
|
|
@ -49,20 +49,20 @@ public:
|
|||
// path(0) is the startpoint.
|
||||
// path(size()-1) is the endpoint.
|
||||
const PathRef *path(size_t index) const;
|
||||
TimingArc *prevArc(size_t index);
|
||||
TimingArc *prevArc(size_t index) const;
|
||||
// Returns the path start point.
|
||||
// Register/Latch Q pin
|
||||
// Input pin
|
||||
PathRef *startPath();
|
||||
PathRef *startPrevPath();
|
||||
PathRef *endPath();
|
||||
TimingArc *startPrevArc();
|
||||
const PathRef *startPath() const;
|
||||
const PathRef *startPrevPath() const;
|
||||
const PathRef *endPath() const;
|
||||
TimingArc *startPrevArc() const;
|
||||
size_t startIndex() const;
|
||||
void clkPath(PathRef &clk_path);
|
||||
void clkPath(PathRef &clk_path) const;
|
||||
void latchPaths(// Return values.
|
||||
PathRef *&d_path,
|
||||
PathRef *&q_path,
|
||||
Edge *&d_q_edge);
|
||||
const PathRef *&d_path,
|
||||
const PathRef *&q_path,
|
||||
Edge *&d_q_edge) const;
|
||||
|
||||
protected:
|
||||
void expandGenclk(PathRef *clk_path);
|
||||
|
|
|
|||
|
|
@ -341,9 +341,9 @@ public:
|
|||
Arrival insertion,
|
||||
const PathAnalysisPt *path_ap);
|
||||
// Timing derated arc delay for a path analysis point.
|
||||
ArcDelay deratedDelay(Vertex *from_vertex,
|
||||
TimingArc *arc,
|
||||
Edge *edge,
|
||||
ArcDelay deratedDelay(const Vertex *from_vertex,
|
||||
const TimingArc *arc,
|
||||
const Edge *edge,
|
||||
bool is_clk,
|
||||
const PathAnalysisPt *path_ap);
|
||||
|
||||
|
|
@ -501,9 +501,9 @@ protected:
|
|||
void findArrivalsSeed();
|
||||
void seedFilterStarts();
|
||||
bool hasEnabledChecks(Vertex *vertex) const;
|
||||
virtual float timingDerate(Vertex *from_vertex,
|
||||
TimingArc *arc,
|
||||
Edge *edge,
|
||||
virtual float timingDerate(const Vertex *from_vertex,
|
||||
const TimingArc *arc,
|
||||
const Edge *edge,
|
||||
bool is_clk,
|
||||
const PathAnalysisPt *path_ap);
|
||||
void deletePaths();
|
||||
|
|
|
|||
|
|
@ -922,7 +922,7 @@ public:
|
|||
void reportPathEnd(PathEnd *end);
|
||||
void reportPathEnds(PathEndSeq *ends);
|
||||
ReportPath *reportPath() { return report_path_; }
|
||||
void reportPath(Path *path);
|
||||
void reportPath(const Path *path);
|
||||
|
||||
// Report clk skews for clks.
|
||||
void reportClkSkew(ConstClockSeq &clks,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -29,31 +28,31 @@
|
|||
#include "util/FlexDisableRegister.hh"
|
||||
#include "Debug.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::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) \
|
||||
result = libexpr_parser->copyInput(buf, max_size)
|
||||
|
||||
void
|
||||
libertyExprFlushBuffer()
|
||||
{
|
||||
YY_FLUSH_BUFFER;
|
||||
}
|
||||
typedef sta::LibExprParse::token token;
|
||||
|
||||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option c++
|
||||
%option yyclass="sta::LibExprScanner"
|
||||
%option prefix="LibExpr"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
%option stack
|
||||
/* %option debug */
|
||||
|
||||
%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}{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} {
|
||||
BEGIN(INITIAL);
|
||||
LibertyExprParse_lval.string = libexpr_parser->tokenCopy();
|
||||
return PORT;
|
||||
yylval->string = stringCopy(token_.c_str());
|
||||
return token::PORT;
|
||||
}
|
||||
|
||||
{PORT} {
|
||||
LibertyExprParse_lval.string = stringCopy(LibertyExprLex_text);
|
||||
return PORT;
|
||||
yylval->string = stringCopy(yytext);
|
||||
return token::PORT;
|
||||
}
|
||||
|
||||
{BLANK} {}
|
||||
|
||||
/* Send out of bound characters to parser. */
|
||||
. { return (int) LibertyExprLex_text[0]; }
|
||||
. { return (int) yytext[0]; }
|
||||
|
||||
%%
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -26,15 +24,35 @@
|
|||
|
||||
// Liberty function expression parser.
|
||||
|
||||
%{
|
||||
#include "FuncExpr.hh"
|
||||
#include "liberty/LibertyExpr.hh"
|
||||
#include "liberty/LibertyExprPvt.hh"
|
||||
#include "liberty/LibExprReader.hh"
|
||||
#include "liberty/LibExprReaderPvt.hh"
|
||||
#include "liberty/LibExprScanner.hh"
|
||||
|
||||
int LibertyExprLex_lex();
|
||||
#define LibertyExprParse_lex LibertyExprLex_lex
|
||||
#undef yylex
|
||||
#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 {
|
||||
int int_val;
|
||||
const char *string;
|
||||
|
|
@ -50,18 +68,15 @@ int LibertyExprLex_lex();
|
|||
%type <string> PORT
|
||||
%type <expr> expr terminal terminal_expr implicit_and
|
||||
|
||||
%{
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
result_expr:
|
||||
expr { sta::libexpr_parser->setResult($1); }
|
||||
| expr ';'{ sta::libexpr_parser->setResult($1); }
|
||||
expr { reader->setResult($1); }
|
||||
| expr ';'{ reader->setResult($1); }
|
||||
;
|
||||
|
||||
terminal:
|
||||
PORT { $$ = sta::libexpr_parser->makeFuncExprPort($1); }
|
||||
PORT { $$ = reader->makeFuncExprPort($1); }
|
||||
| '0' { $$ = sta::FuncExpr::makeZero(); }
|
||||
| '1' { $$ = sta::FuncExpr::makeOne(); }
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
|
|
@ -69,25 +84,25 @@ terminal:
|
|||
|
||||
terminal_expr:
|
||||
terminal
|
||||
| '!' terminal { $$ = sta::libexpr_parser->makeFuncExprNot($2); }
|
||||
| terminal '\'' { $$ = sta::libexpr_parser->makeFuncExprNot($1); }
|
||||
| '!' terminal { $$ = reader->makeFuncExprNot($2); }
|
||||
| terminal '\'' { $$ = reader->makeFuncExprNot($1); }
|
||||
;
|
||||
|
||||
implicit_and:
|
||||
terminal_expr terminal_expr
|
||||
{ $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); }
|
||||
{ $$ = reader->makeFuncExprAnd($1, $2); }
|
||||
| implicit_and terminal_expr
|
||||
{ $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); }
|
||||
{ $$ = reader->makeFuncExprAnd($1, $2); }
|
||||
;
|
||||
|
||||
expr:
|
||||
terminal_expr
|
||||
| implicit_and
|
||||
| expr '+' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); }
|
||||
| expr '|' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); }
|
||||
| expr '*' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); }
|
||||
| expr '&' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); }
|
||||
| expr '^' expr { $$ = sta::libexpr_parser->makeFuncExprXor($1, $3); }
|
||||
| expr '+' expr { $$ = reader->makeFuncExprOr($1, $3); }
|
||||
| expr '|' expr { $$ = reader->makeFuncExprOr($1, $3); }
|
||||
| expr '*' expr { $$ = reader->makeFuncExprAnd($1, $3); }
|
||||
| expr '&' expr { $$ = reader->makeFuncExprAnd($1, $3); }
|
||||
| expr '^' expr { $$ = reader->makeFuncExprXor($1, $3); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
@ -24,19 +24,17 @@
|
|||
|
||||
#include "FuncExpr.hh"
|
||||
|
||||
#include <algorithm> // min
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "Report.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "LibertyExprPvt.hh"
|
||||
|
||||
extern int
|
||||
LibertyExprParse_parse();
|
||||
#include "LibExprReaderPvt.hh"
|
||||
#include "LibExprScanner.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
LibExprParser *libexpr_parser;
|
||||
|
||||
FuncExpr *
|
||||
parseFuncExpr(const char *func,
|
||||
LibertyCell *cell,
|
||||
|
|
@ -44,18 +42,20 @@ parseFuncExpr(const char *func,
|
|||
Report *report)
|
||||
{
|
||||
if (func != nullptr && func[0] != '\0') {
|
||||
LibExprParser parser(func, cell, error_msg, report);
|
||||
libexpr_parser = &parser;
|
||||
LibertyExprParse_parse();
|
||||
FuncExpr *expr = parser.result();
|
||||
libexpr_parser = nullptr;
|
||||
string func1(func);
|
||||
std::istringstream stream(func);
|
||||
LibExprReader reader(func, cell, error_msg, report);
|
||||
LibExprScanner scanner(stream);
|
||||
LibExprParse parser(&scanner, &reader);
|
||||
parser.parse();
|
||||
FuncExpr *expr = reader.result();
|
||||
return expr;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LibExprParser::LibExprParser(const char *func,
|
||||
LibExprReader::LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report) :
|
||||
|
|
@ -63,24 +63,17 @@ LibExprParser::LibExprParser(const char *func,
|
|||
cell_(cell),
|
||||
error_msg_(error_msg),
|
||||
report_(report),
|
||||
result_(nullptr),
|
||||
token_length_(100),
|
||||
token_(new char[token_length_]),
|
||||
token_next_(token_)
|
||||
result_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
LibExprParser::~LibExprParser()
|
||||
{
|
||||
stringDelete(token_);
|
||||
}
|
||||
|
||||
// defined in LibertyReader.cc
|
||||
LibertyPort *
|
||||
libertyReaderFindPort(LibertyCell *cell,
|
||||
const char *port_name);
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprPort(const char *port_name)
|
||||
LibExprReader::makeFuncExprPort(const char *port_name)
|
||||
{
|
||||
FuncExpr *expr = nullptr;
|
||||
LibertyPort *port = libertyReaderFindPort(cell_, port_name);
|
||||
|
|
@ -94,7 +87,7 @@ LibExprParser::makeFuncExprPort(const char *port_name)
|
|||
}
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprNot(FuncExpr *arg)
|
||||
LibExprReader::makeFuncExprNot(FuncExpr *arg)
|
||||
{
|
||||
if (arg)
|
||||
return FuncExpr::makeNot(arg);
|
||||
|
|
@ -103,7 +96,7 @@ LibExprParser::makeFuncExprNot(FuncExpr *arg)
|
|||
}
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprXor(FuncExpr *arg1,
|
||||
LibExprReader::makeFuncExprXor(FuncExpr *arg1,
|
||||
FuncExpr *arg2)
|
||||
{
|
||||
if (arg1 && arg2)
|
||||
|
|
@ -113,7 +106,7 @@ LibExprParser::makeFuncExprXor(FuncExpr *arg1,
|
|||
}
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprAnd(FuncExpr *arg1,
|
||||
LibExprReader::makeFuncExprAnd(FuncExpr *arg1,
|
||||
FuncExpr *arg2)
|
||||
{
|
||||
if (arg1 && arg2)
|
||||
|
|
@ -123,7 +116,7 @@ LibExprParser::makeFuncExprAnd(FuncExpr *arg1,
|
|||
}
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprOr(FuncExpr *arg1,
|
||||
LibExprReader::makeFuncExprOr(FuncExpr *arg1,
|
||||
FuncExpr *arg2)
|
||||
{
|
||||
if (arg1 && arg2)
|
||||
|
|
@ -133,65 +126,22 @@ LibExprParser::makeFuncExprOr(FuncExpr *arg1,
|
|||
}
|
||||
|
||||
void
|
||||
LibExprParser::setResult(FuncExpr *result)
|
||||
LibExprReader::setResult(FuncExpr *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
|
||||
LibExprParser::tokenErase()
|
||||
{
|
||||
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)
|
||||
LibExprReader::parseError(const char *msg)
|
||||
{
|
||||
report_->error(1131, "%s %s.", error_msg_, msg);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Global namespace
|
||||
|
||||
int
|
||||
LibertyExprParse_error(const char *msg)
|
||||
LibExprScanner::LibExprScanner(std::istringstream &stream) :
|
||||
yyFlexLexer(&stream)
|
||||
{
|
||||
libertyExprFlushBuffer();
|
||||
sta::libexpr_parser->parseError(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -29,15 +29,15 @@ namespace sta {
|
|||
class Report;
|
||||
class LibertyCell;
|
||||
class FuncExpr;
|
||||
class LibExprScanner;
|
||||
|
||||
class LibExprParser
|
||||
class LibExprReader
|
||||
{
|
||||
public:
|
||||
LibExprParser(const char *func,
|
||||
LibExprReader(const char *func,
|
||||
LibertyCell *cell,
|
||||
const char *error_msg,
|
||||
Report *report);
|
||||
~LibExprParser();
|
||||
FuncExpr *makeFuncExprPort(const char *port_name);
|
||||
FuncExpr *makeFuncExprOr(FuncExpr *arg1,
|
||||
FuncExpr *arg2);
|
||||
|
|
@ -51,11 +51,7 @@ public:
|
|||
void parseError(const char *msg);
|
||||
size_t copyInput(char *buf,
|
||||
size_t max_size);
|
||||
void tokenStart();
|
||||
const char *token();
|
||||
char *tokenCopy();
|
||||
void tokenErase();
|
||||
void tokenAppend(char ch);
|
||||
Report *report() const { return report_; }
|
||||
|
||||
private:
|
||||
const char *func_;
|
||||
|
|
@ -63,18 +59,6 @@ private:
|
|||
const char *error_msg_;
|
||||
Report *report_;
|
||||
FuncExpr *result_;
|
||||
size_t token_length_;
|
||||
char *token_;
|
||||
char *token_next_;
|
||||
};
|
||||
|
||||
extern LibExprParser *libexpr_parser;
|
||||
|
||||
} // namespace
|
||||
|
||||
// Global namespace
|
||||
|
||||
void
|
||||
libertyExprFlushBuffer();
|
||||
int
|
||||
LibertyExprParse_error(const char *msg);
|
||||
|
|
@ -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
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
%{
|
||||
#include <cstdlib>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
#include "Report.hh"
|
||||
#include "liberty/LibertyParser.hh"
|
||||
#include "liberty/LibertyScanner.hh"
|
||||
|
||||
|
|
@ -36,6 +36,15 @@
|
|||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
|
||||
#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"
|
||||
|
|
@ -47,11 +56,7 @@
|
|||
%define parse.assert
|
||||
%parse-param { LibertyScanner *scanner }
|
||||
%parse-param { LibertyParser *reader }
|
||||
|
||||
// bison 3.0.4 for centos7
|
||||
%define parser_class_name {LibertyParse}
|
||||
// bison 3.3.2
|
||||
//%define api.parser.class {LibertyParse}
|
||||
%define api.parser.class {LibertyParse}
|
||||
|
||||
%expect 2
|
||||
|
||||
|
|
|
|||
|
|
@ -41,18 +41,15 @@ parseLibertyFile(const char *filename,
|
|||
LibertyGroupVisitor *library_visitor,
|
||||
Report *report)
|
||||
{
|
||||
std::istream *stream = new gzstream::igzstream(filename);
|
||||
if (stream->good()) {
|
||||
gzstream::igzstream stream(filename);
|
||||
if (stream.is_open()) {
|
||||
LibertyParser reader(filename, library_visitor, report);
|
||||
LibertyScanner scanner(stream, filename, &reader, report);
|
||||
LibertyScanner scanner(&stream, filename, &reader, report);
|
||||
LibertyParse parser(&scanner, &reader);
|
||||
parser.parse();
|
||||
delete stream;
|
||||
}
|
||||
else {
|
||||
delete stream;
|
||||
else
|
||||
throw FileNotReadable(filename);
|
||||
}
|
||||
}
|
||||
|
||||
LibertyParser::LibertyParser(const char *filename,
|
||||
|
|
@ -567,12 +564,4 @@ LibertyScanner::error(const char *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
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include "LinearModel.hh"
|
||||
#include "Wireload.hh"
|
||||
#include "EquivCells.hh"
|
||||
#include "LibertyExpr.hh"
|
||||
#include "LibExprReader.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "LibertyBuilder.hh"
|
||||
#include "LibertyReaderPvt.hh"
|
||||
|
|
|
|||
|
|
@ -31,15 +31,17 @@
|
|||
#include "Map.hh"
|
||||
#include "StringSeq.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "Transition.hh"
|
||||
#include "TimingArc.hh"
|
||||
#include "InternalPower.hh"
|
||||
#include "LeakagePower.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "Sequential.hh"
|
||||
#include "TableModel.hh"
|
||||
#include "LibertyParser.hh"
|
||||
#include "LibertyReader.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "LibertyBuilder.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -494,6 +496,8 @@ public:
|
|||
void endCcsn(LibertyGroup *group);
|
||||
void beginEcsmWaveform(LibertyGroup *group);
|
||||
void endEcsmWaveform(LibertyGroup *group);
|
||||
LibertyPort *findPort(LibertyCell *cell,
|
||||
const char *port_name);
|
||||
|
||||
protected:
|
||||
TimingModel *makeScalarCheckModel(float value,
|
||||
|
|
@ -519,8 +523,6 @@ protected:
|
|||
StdStringSeq parseTokenList(const char *token_str,
|
||||
const char separator);
|
||||
LibertyPort *findPort(const char *port_name);
|
||||
LibertyPort *findPort(LibertyCell *cell,
|
||||
const char *port_name);
|
||||
float defaultCap(LibertyPort *port);
|
||||
virtual void visitVariable(LibertyVariable *var);
|
||||
void visitPorts(std::function<void (LibertyPort *port)> func);
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "LibertyLocation.hh"
|
||||
#include "LibertyParse.hh"
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
#undef yyFlexLexer
|
||||
#define yyFlexLexer LibertyFlexLexer
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
#include "LibertyLocation.hh"
|
||||
#include "LibertyParse.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class Report;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -31,30 +30,28 @@
|
|||
#include "StringUtil.hh"
|
||||
#include "parasitics/SpefReaderPvt.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;
|
||||
|
||||
void
|
||||
spefFlushBuffer()
|
||||
{
|
||||
YY_FLUSH_BUFFER;
|
||||
}
|
||||
|
||||
// Reset the start condition to INITIAL.
|
||||
void
|
||||
spefResetScanner()
|
||||
{
|
||||
BEGIN(0);
|
||||
}
|
||||
// update location on matching
|
||||
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
|
||||
|
||||
typedef sta::SpefParse::token token;
|
||||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option c++
|
||||
%option yyclass="sta::SpefScanner"
|
||||
%option prefix="Spef"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
%option stack
|
||||
%option yylineno
|
||||
/* %option debug */
|
||||
|
||||
%x COMMENT
|
||||
%x QUOTE
|
||||
|
|
@ -93,123 +90,117 @@ INDEX "*"{POS_INTEGER}
|
|||
|
||||
%%
|
||||
|
||||
"*BUS_DELIMITER" { return BUS_DELIMITER; }
|
||||
"*C2_R1_C1" { return C2_R1_C1; }
|
||||
"*C" { return KW_C; }
|
||||
"*CAP" { return CAP; }
|
||||
"*CELL" { return CELL; }
|
||||
"*CONN" { return CONN; }
|
||||
"*C_UNIT" { return C_UNIT; }
|
||||
"*SPEF" { return SPEF; }
|
||||
"*DATE" { return DATE; }
|
||||
"*DEFINE" { return DEFINE; }
|
||||
"*DELIMITER" { return DELIMITER; }
|
||||
"*DESIGN" { return DESIGN; }
|
||||
"*DESIGN_FLOW" { return DESIGN_FLOW; }
|
||||
"*DIVIDER" { return DIVIDER; }
|
||||
"*DRIVER" { return DRIVER; }
|
||||
"*D_NET" { return D_NET; }
|
||||
"*D_PNET" { return D_PNET; }
|
||||
"*D" { return KW_D; }
|
||||
"*END" { return END; }
|
||||
"*GROUND_NETS" { return GROUND_NETS; }
|
||||
"*INDUC" { return INDUC; }
|
||||
"*I" { return KW_I; }
|
||||
"*K" { return KW_K; }
|
||||
"*L" { return KW_L; }
|
||||
"*LOADS" { return LOADS; }
|
||||
"*L_UNIT" { return L_UNIT; }
|
||||
"*NAME_MAP" { return NAME_MAP; }
|
||||
"*N" { return KW_N; }
|
||||
"*PDEFINE" { return PDEFINE; }
|
||||
"*PHYSICAL_PORTS" { return PHYSICAL_PORTS; }
|
||||
"*PORTS" { return PORTS; }
|
||||
"*POWER_NETS" { return POWER_NETS; }
|
||||
"*PROGRAM" { return PROGRAM; }
|
||||
"*P" { return KW_P; }
|
||||
"*Q" { return KW_Q; }
|
||||
"*RC" { return RC; }
|
||||
"*RES" { return RES; }
|
||||
"*R_NET" { return R_NET; }
|
||||
"*R_PNET" { return R_PNET; }
|
||||
"*R_UNIT" { return R_UNIT; }
|
||||
"*S" { return KW_S; }
|
||||
"*T_UNIT" { return T_UNIT; }
|
||||
"*VENDOR" { return VENDOR; }
|
||||
"*VERSION" { return PVERSION; }
|
||||
"*V" { return KW_V; }
|
||||
"*BUS_DELIMITER" { return token::BUS_DELIMITER; }
|
||||
"*C2_R1_C1" { return token::C2_R1_C1; }
|
||||
"*C" { return token::KW_C; }
|
||||
"*CAP" { return token::CAP; }
|
||||
"*CELL" { return token::CELL; }
|
||||
"*CONN" { return token::CONN; }
|
||||
"*C_UNIT" { return token::C_UNIT; }
|
||||
"*SPEF" { return token::SPEF; }
|
||||
"*DATE" { return token::DATE; }
|
||||
"*DEFINE" { return token::DEFINE; }
|
||||
"*DELIMITER" { return token::DELIMITER; }
|
||||
"*DESIGN" { return token::DESIGN; }
|
||||
"*DESIGN_FLOW" { return token::DESIGN_FLOW; }
|
||||
"*DIVIDER" { return token::DIVIDER; }
|
||||
"*DRIVER" { return token::DRIVER; }
|
||||
"*D_NET" { return token::D_NET; }
|
||||
"*D_PNET" { return token::D_PNET; }
|
||||
"*D" { return token::KW_D; }
|
||||
"*END" { return token::END; }
|
||||
"*GROUND_NETS" { return token::GROUND_NETS; }
|
||||
"*INDUC" { return token::INDUC; }
|
||||
"*I" { return token::KW_I; }
|
||||
"*K" { return token::KW_K; }
|
||||
"*L" { return token::KW_L; }
|
||||
"*LOADS" { return token::LOADS; }
|
||||
"*L_UNIT" { return token::L_UNIT; }
|
||||
"*NAME_MAP" { return token::NAME_MAP; }
|
||||
"*N" { return token::KW_N; }
|
||||
"*PDEFINE" { return token::PDEFINE; }
|
||||
"*PHYSICAL_PORTS" { return token::PHYSICAL_PORTS; }
|
||||
"*PORTS" { return token::PORTS; }
|
||||
"*POWER_NETS" { return token::POWER_NETS; }
|
||||
"*PROGRAM" { return token::PROGRAM; }
|
||||
"*P" { return token::KW_P; }
|
||||
"*Q" { return token::KW_Q; }
|
||||
"*RC" { return token::RC; }
|
||||
"*RES" { return token::RES; }
|
||||
"*R_NET" { return token::R_NET; }
|
||||
"*R_PNET" { return token::R_PNET; }
|
||||
"*R_UNIT" { return token::R_UNIT; }
|
||||
"*S" { return token::KW_S; }
|
||||
"*T_UNIT" { return token::T_UNIT; }
|
||||
"*VENDOR" { return token::VENDOR; }
|
||||
"*VERSION" { return token::PVERSION; }
|
||||
"*V" { return token::KW_V; }
|
||||
|
||||
"//".*\n { /* Single line comment */
|
||||
sta::spef_reader->incrLine();
|
||||
}
|
||||
"//".*\n { loc->lines(); loc->step(); } /* Single line comment */
|
||||
|
||||
"/*" { BEGIN COMMENT; }
|
||||
<COMMENT>{
|
||||
|
||||
.
|
||||
|
||||
\n { sta::spef_reader->incrLine(); }
|
||||
\n { loc->lines(); loc->step(); }
|
||||
|
||||
"*/" { BEGIN INITIAL; }
|
||||
|
||||
<<EOF>> {
|
||||
SpefParse_error("unterminated comment");
|
||||
error("unterminated comment");
|
||||
BEGIN(INITIAL);
|
||||
yyterminate();
|
||||
}
|
||||
}
|
||||
|
||||
"\"" { BEGIN QUOTE; spef_token.erase(); }
|
||||
"\"" { BEGIN QUOTE; token_.erase(); }
|
||||
<QUOTE>{
|
||||
|
||||
\r?\n {
|
||||
sta::spef_reader->incrLine();
|
||||
}
|
||||
\r?\n { loc->lines(); loc->step(); }
|
||||
|
||||
"\\". { spef_token += yytext[1]; }
|
||||
"\\". { token_ += yytext[1]; }
|
||||
|
||||
"\"" {
|
||||
BEGIN INITIAL;
|
||||
SpefParse_lval.string = sta::stringCopy(spef_token.c_str());
|
||||
return QSTRING;
|
||||
yylval->string = sta::stringCopy(token_.c_str());
|
||||
return token::QSTRING;
|
||||
}
|
||||
|
||||
. { spef_token += yytext[0]; }
|
||||
. { token_ += yytext[0]; }
|
||||
|
||||
<<EOF>> {
|
||||
SpefParse_error("unterminated quoted string");
|
||||
error("unterminated quoted string");
|
||||
BEGIN(INITIAL);
|
||||
yyterminate();
|
||||
}
|
||||
}
|
||||
|
||||
{BLANK}*\n {
|
||||
sta::spef_reader->incrLine();
|
||||
}
|
||||
{BLANK}*\n { loc->lines(); loc->step(); }
|
||||
|
||||
{INTEGER} {
|
||||
SpefParse_lval.integer = atoi(yytext);
|
||||
return INTEGER;
|
||||
yylval->integer = atoi(yytext);
|
||||
return token::INTEGER;
|
||||
}
|
||||
|
||||
{FLOAT} {
|
||||
SpefParse_lval.number = static_cast<float>(atof(yytext));
|
||||
return FLOAT;
|
||||
yylval->number = static_cast<float>(atof(yytext));
|
||||
return token::FLOAT;
|
||||
}
|
||||
|
||||
{IDENT} {
|
||||
SpefParse_lval.string = sta::spef_reader->translated(yytext);
|
||||
return IDENT;
|
||||
yylval->string = reader_->translated(yytext);
|
||||
return token::IDENT;
|
||||
}
|
||||
|
||||
{PATH}|{NAME_PAIR} {
|
||||
SpefParse_lval.string = sta::spef_reader->translated(yytext);
|
||||
return NAME;
|
||||
yylval->string = reader_->translated(yytext);
|
||||
return token::NAME;
|
||||
}
|
||||
|
||||
{INDEX} {
|
||||
SpefParse_lval.string = sta::stringCopy(yytext);
|
||||
return INDEX;
|
||||
yylval->string = sta::stringCopy(yytext);
|
||||
return token::INDEX;
|
||||
}
|
||||
|
||||
{HCHAR} {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -24,19 +22,41 @@
|
|||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
%{
|
||||
#include <cstring>
|
||||
|
||||
#include "Report.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "StringSeq.hh"
|
||||
#include "parasitics/SpefReaderPvt.hh"
|
||||
#include "parasitics/SpefScanner.hh"
|
||||
|
||||
int SpefLex_lex();
|
||||
#define SpefParse_lex SpefLex_lex
|
||||
// use yacc generated parser errors
|
||||
#define YYERROR_VERBOSE
|
||||
#undef yylex
|
||||
#define yylex scanner->lex
|
||||
|
||||
// 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 {
|
||||
char ch;
|
||||
char *string;
|
||||
|
|
@ -195,7 +215,7 @@ vendor:
|
|||
|
||||
design_flow:
|
||||
DESIGN_FLOW qstrings
|
||||
{ sta::spef_reader->setDesignFlow($2); }
|
||||
{ reader->setDesignFlow($2); }
|
||||
;
|
||||
|
||||
qstrings:
|
||||
|
|
@ -209,19 +229,19 @@ qstrings:
|
|||
|
||||
hierarchy_div_def:
|
||||
DIVIDER hchar
|
||||
{ sta::spef_reader->setDivider($2); }
|
||||
{ reader->setDivider($2); }
|
||||
;
|
||||
|
||||
pin_delim_def:
|
||||
DELIMITER hchar
|
||||
{ sta::spef_reader->setDelimiter($2); }
|
||||
{ reader->setDelimiter($2); }
|
||||
;
|
||||
|
||||
bus_delim_def:
|
||||
BUS_DELIMITER prefix_bus_delim
|
||||
{ sta::spef_reader->setBusBrackets($2, '\0'); }
|
||||
{ reader->setBusBrackets($2, '\0'); }
|
||||
| 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:
|
||||
T_UNIT pos_number IDENT
|
||||
{ sta::spef_reader->setTimeScale($2, $3); }
|
||||
{ reader->setTimeScale($2, $3); }
|
||||
;
|
||||
|
||||
cap_scale:
|
||||
C_UNIT pos_number IDENT
|
||||
{ sta::spef_reader->setCapScale($2, $3); }
|
||||
{ reader->setCapScale($2, $3); }
|
||||
;
|
||||
|
||||
res_scale:
|
||||
R_UNIT pos_number IDENT
|
||||
{ sta::spef_reader->setResScale($2, $3); }
|
||||
{ reader->setResScale($2, $3); }
|
||||
;
|
||||
|
||||
induc_scale:
|
||||
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:
|
||||
INDEX mapped_item
|
||||
{ sta::spef_reader->makeNameMapEntry($1, $2);
|
||||
{ reader->makeNameMapEntry($1, $2);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -330,7 +350,7 @@ port_entry:
|
|||
|
||||
direction:
|
||||
IDENT
|
||||
{ $$ = sta::spef_reader->portDirection($1);
|
||||
{ $$ = reader->portDirection($1);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -474,14 +494,14 @@ nets:
|
|||
|
||||
d_net:
|
||||
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
|
||||
{ sta::spef_reader->dspfFinish(); }
|
||||
{ reader->dspfFinish(); }
|
||||
;
|
||||
|
||||
net:
|
||||
name_or_index
|
||||
{ $$ = sta::spef_reader->findNet($1);
|
||||
{ $$ = reader->findNet($1);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -531,7 +551,7 @@ internal_connection:
|
|||
|
||||
pin_name:
|
||||
name_or_index
|
||||
{ $$ = sta::spef_reader->findPin($1);
|
||||
{ $$ = reader->findPin($1);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
;
|
||||
|
|
@ -565,9 +585,9 @@ cap_elems:
|
|||
|
||||
cap_elem:
|
||||
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
|
||||
{ sta::spef_reader->makeCapacitor($1, $2, $3, $4); }
|
||||
{ reader->makeCapacitor($1, $2, $3, $4); }
|
||||
;
|
||||
|
||||
cap_id:
|
||||
|
|
@ -593,7 +613,7 @@ res_elems:
|
|||
|
||||
res_elem:
|
||||
res_id parasitic_node parasitic_node par_value
|
||||
{ sta::spef_reader->makeResistor($1, $2, $3, $4); }
|
||||
{ reader->makeResistor($1, $2, $3, $4); }
|
||||
;
|
||||
|
||||
res_id:
|
||||
|
|
@ -626,9 +646,9 @@ induc_id:
|
|||
|
||||
r_net:
|
||||
R_NET net total_cap
|
||||
{ sta::spef_reader->rspfBegin($2, $3); }
|
||||
{ reader->rspfBegin($2, $3); }
|
||||
routing_conf driver_reducs END
|
||||
{ sta::spef_reader->rspfFinish(); }
|
||||
{ reader->rspfFinish(); }
|
||||
;
|
||||
|
||||
driver_reducs:
|
||||
|
|
@ -638,11 +658,11 @@ driver_reducs:
|
|||
|
||||
driver_reduc:
|
||||
driver_pair driver_cell pi_model
|
||||
{ sta::spef_reader->rspfDrvrBegin($1, $3);
|
||||
{ reader->rspfDrvrBegin($1, $3);
|
||||
sta::stringDelete($2);
|
||||
}
|
||||
load_desc
|
||||
{ sta::spef_reader->rspfDrvrFinish(); }
|
||||
{ reader->rspfDrvrFinish(); }
|
||||
;
|
||||
|
||||
driver_pair:
|
||||
|
|
@ -673,9 +693,9 @@ rc_descs:
|
|||
|
||||
rc_desc:
|
||||
RC pin_name par_value
|
||||
{ sta::spef_reader->rspfLoad($2, $3); }
|
||||
{ reader->rspfLoad($2, $3); }
|
||||
| RC pin_name par_value pole_residue_desc
|
||||
{ sta::spef_reader->rspfLoad($2, $3); }
|
||||
{ reader->rspfLoad($2, $3); }
|
||||
;
|
||||
|
||||
pole_residue_desc:
|
||||
|
|
@ -810,7 +830,7 @@ pos_integer:
|
|||
INTEGER
|
||||
{ int value = $1;
|
||||
if (value < 0)
|
||||
sta::spef_reader->warn(1525, "%d is not positive.", value);
|
||||
reader->warn(1525, "%d is not positive.", value);
|
||||
$$ = value;
|
||||
}
|
||||
;
|
||||
|
|
@ -819,13 +839,13 @@ pos_number:
|
|||
INTEGER
|
||||
{ float value = static_cast<float>($1);
|
||||
if (value < 0)
|
||||
sta::spef_reader->warn(1526, "%.4f is not positive.", value);
|
||||
reader->warn(1526, "%.4f is not positive.", value);
|
||||
$$ = value;
|
||||
}
|
||||
| FLOAT
|
||||
{ float value = static_cast<float>($1);
|
||||
if (value < 0)
|
||||
sta::spef_reader->warn(1527, "%.4f is not positive.", value);
|
||||
reader->warn(1527, "%.4f is not positive.", value);
|
||||
$$ = value;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
|
|
@ -40,17 +40,10 @@
|
|||
#include "ArcDelayCalc.hh"
|
||||
#include "SpefReaderPvt.hh"
|
||||
#include "SpefNamespace.hh"
|
||||
|
||||
int
|
||||
SpefParse_parse();
|
||||
void
|
||||
spefResetScanner();
|
||||
#include "parasitics/SpefScanner.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
// Referenced by parser.
|
||||
SpefReader *spef_reader;
|
||||
|
||||
bool
|
||||
readSpefFile(const char *filename,
|
||||
Instance *instance,
|
||||
|
|
@ -63,35 +56,14 @@ readSpefFile(const char *filename,
|
|||
const MinMaxAll *min_max,
|
||||
StaState *sta)
|
||||
{
|
||||
bool success = false;
|
||||
const ArcDelayCalc *arc_delay_calc = sta->arcDelayCalc();
|
||||
if (reduce && !arc_delay_calc->reduceSupported()) {
|
||||
sta->report()->warn(1658, "Delay calculator %s does not support reduction.",
|
||||
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,
|
||||
SpefReader reader(filename, 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);
|
||||
bool success = reader.read();
|
||||
return success;
|
||||
}
|
||||
|
||||
SpefReader::SpefReader(const char *filename,
|
||||
gzFile stream,
|
||||
Instance *instance,
|
||||
ParasiticAnalysisPt *ap,
|
||||
bool pin_cap_included,
|
||||
|
|
@ -110,8 +82,6 @@ SpefReader::SpefReader(const char *filename,
|
|||
reduce_(reduce),
|
||||
corner_(corner),
|
||||
min_max_(min_max),
|
||||
stream_(stream),
|
||||
line_(1),
|
||||
// defaults
|
||||
divider_('\0'),
|
||||
delimiter_('\0'),
|
||||
|
|
@ -141,6 +111,25 @@ SpefReader::~SpefReader()
|
|||
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
|
||||
SpefReader::setDivider(char divider)
|
||||
{
|
||||
|
|
@ -154,7 +143,8 @@ SpefReader::setDelimiter(char delimiter)
|
|||
}
|
||||
|
||||
void
|
||||
SpefReader::setBusBrackets(char left, char right)
|
||||
SpefReader::setBusBrackets(char left,
|
||||
char right)
|
||||
{
|
||||
if (!((left == '[' && right == ']')
|
||||
|| (left == '{' && right == '}')
|
||||
|
|
@ -196,30 +186,6 @@ SpefReader::findPortPinRelative(const char *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 *
|
||||
SpefReader::translated(const char *token)
|
||||
{
|
||||
|
|
@ -227,18 +193,12 @@ SpefReader::translated(const char *token)
|
|||
network_->pathEscape());
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::incrLine()
|
||||
{
|
||||
line_++;
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::warn(int id, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
report_->vfileWarn(id, filename_, line_, fmt, args);
|
||||
report_->vfileWarn(id, filename_, scanner_->line(), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
@ -644,17 +604,23 @@ SpefTriple::value(int index) const
|
|||
return values_[0];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Global namespace
|
||||
|
||||
void spefFlushBuffer();
|
||||
|
||||
int
|
||||
SpefParse_error(const char *msg)
|
||||
SpefScanner::SpefScanner(std::istream *stream,
|
||||
const string &filename,
|
||||
SpefReader *reader,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -32,15 +32,6 @@
|
|||
#include "ParasiticsClass.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 {
|
||||
|
||||
class Report;
|
||||
|
|
@ -48,6 +39,7 @@ class MinMaxAll;
|
|||
class SpefRspfPi;
|
||||
class SpefTriple;
|
||||
class Corner;
|
||||
class SpefScanner;
|
||||
|
||||
typedef std::map<int, char*, std::less<int>> SpefNameMap;
|
||||
|
||||
|
|
@ -55,7 +47,6 @@ class SpefReader : public StaState
|
|||
{
|
||||
public:
|
||||
SpefReader(const char *filename,
|
||||
gzFile stream,
|
||||
Instance *instance,
|
||||
ParasiticAnalysisPt *ap,
|
||||
bool pin_cap_included,
|
||||
|
|
@ -66,21 +57,12 @@ public:
|
|||
const MinMaxAll *min_max,
|
||||
StaState *sta);
|
||||
virtual ~SpefReader();
|
||||
bool read();
|
||||
char divider() const { return divider_; }
|
||||
void setDivider(char divider);
|
||||
char delimiter() const { return delimiter_; }
|
||||
void setDelimiter(char delimiter);
|
||||
void incrLine();
|
||||
int line() const { return line_; }
|
||||
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.
|
||||
char *translated(const char *token);
|
||||
void warn(int id,
|
||||
|
|
@ -136,6 +118,7 @@ private:
|
|||
bool local_only);
|
||||
|
||||
const char *filename_;
|
||||
SpefScanner *scanner_;
|
||||
Instance *instance_;
|
||||
const ParasiticAnalysisPt *ap_;
|
||||
bool pin_cap_included_;
|
||||
|
|
@ -144,8 +127,6 @@ private:
|
|||
const Corner *corner_;
|
||||
const MinMaxAll *min_max_;
|
||||
// Normally no need to keep device names.
|
||||
gzFile stream_;
|
||||
int line_;
|
||||
char divider_;
|
||||
char delimiter_;
|
||||
char bus_brkt_left_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -30,23 +29,28 @@
|
|||
#include "StringUtil.hh"
|
||||
#include "power/SaifReaderPvt.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;
|
||||
|
||||
void
|
||||
saifFlushBuffer()
|
||||
{
|
||||
YY_FLUSH_BUFFER;
|
||||
}
|
||||
// update location on matching
|
||||
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
|
||||
|
||||
typedef sta::SaifParse::token token;
|
||||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option c++
|
||||
%option yyclass="sta::SaifScanner"
|
||||
%option prefix="Saif"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
%option stack
|
||||
%option yylineno
|
||||
/* %option debug */
|
||||
|
||||
%x COMMENT
|
||||
%x QUOTE
|
||||
|
|
@ -65,74 +69,74 @@ EOL \r?\n
|
|||
"*/" { BEGIN INITIAL; }
|
||||
|
||||
.
|
||||
{EOL} { sta::saif_reader->incrLine(); }
|
||||
{EOL} { loc->lines(); loc->step(); }
|
||||
|
||||
<<EOF>> {
|
||||
SaifParse_error("unterminated comment");
|
||||
error("unterminated comment");
|
||||
BEGIN(INITIAL);
|
||||
yyterminate();
|
||||
}
|
||||
}
|
||||
|
||||
"\"" { BEGIN QUOTE; saif_token.erase(); }
|
||||
"\"" { BEGIN QUOTE; token_.clear(); }
|
||||
<QUOTE>{
|
||||
|
||||
"\\". { saif_token += yytext[1]; }
|
||||
"\\". { token_ += yytext[1]; }
|
||||
|
||||
"\"" {
|
||||
BEGIN INITIAL;
|
||||
SaifParse_lval.string = sta::stringCopy(saif_token.c_str());
|
||||
return QSTRING;
|
||||
yylval->string = sta::stringCopy(token_.c_str());
|
||||
return token::QSTRING;
|
||||
}
|
||||
|
||||
. { saif_token += yytext[0]; }
|
||||
. { token_ += yytext[0]; }
|
||||
|
||||
<<EOF>> {
|
||||
SaifParse_error("unterminated quoted string");
|
||||
error("unterminated quoted string");
|
||||
BEGIN(INITIAL);
|
||||
yyterminate();
|
||||
}
|
||||
}
|
||||
|
||||
"//"[^\n]*{EOL} { sta::saif_reader->incrLine(); }
|
||||
"//"[^\n]*{EOL} { loc->lines(); loc->step(); }
|
||||
|
||||
[0-9]+ {
|
||||
SaifParse_lval.uint = atoll(yytext);
|
||||
return UINT;
|
||||
yylval->uint = atoll(yytext);
|
||||
return token::UINT;
|
||||
}
|
||||
|
||||
":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} {
|
||||
return ((int) yytext[0]);
|
||||
}
|
||||
|
||||
SAIFILE { return SAIFILE; }
|
||||
SAIFVERSION { return SAIFVERSION; }
|
||||
DIRECTION { return DIRECTION; }
|
||||
DESIGN { return DESIGN; }
|
||||
DATE { return DATE; }
|
||||
VENDOR { return VENDOR; }
|
||||
PROGRAM_NAME { return PROGRAM_NAME; }
|
||||
VERSION { return VERSION; }
|
||||
DIVIDER { return DIVIDER; }
|
||||
TIMESCALE { return TIMESCALE; }
|
||||
DURATION { return DURATION; }
|
||||
INSTANCE { return INSTANCE; }
|
||||
NET { return NET; }
|
||||
PORT { return PORT; }
|
||||
T0 { return T0; }
|
||||
T1 { return T1; }
|
||||
TX { return TX; }
|
||||
TZ { return TZ; }
|
||||
TB { return TB; }
|
||||
TC { return TC; }
|
||||
IG { return IG; }
|
||||
SAIFILE { return token::SAIFILE; }
|
||||
SAIFVERSION { return token::SAIFVERSION; }
|
||||
DIRECTION { return token::DIRECTION; }
|
||||
DESIGN { return token::DESIGN; }
|
||||
DATE { return token::DATE; }
|
||||
VENDOR { return token::VENDOR; }
|
||||
PROGRAM_NAME { return token::PROGRAM_NAME; }
|
||||
VERSION { return token::VERSION; }
|
||||
DIVIDER { return token::DIVIDER; }
|
||||
TIMESCALE { return token::TIMESCALE; }
|
||||
DURATION { return token::DURATION; }
|
||||
INSTANCE { return token::INSTANCE; }
|
||||
NET { return token::NET; }
|
||||
PORT { return token::PORT; }
|
||||
T0 { return token::T0; }
|
||||
T1 { return token::T1; }
|
||||
TX { return token::TX; }
|
||||
TZ { return token::TZ; }
|
||||
TB { return token::TB; }
|
||||
TC { return token::TC; }
|
||||
IG { return token::IG; }
|
||||
|
||||
{ID} {
|
||||
SaifParse_lval.string = sta::stringCopy(yytext);
|
||||
return ID;
|
||||
yylval->string = sta::stringCopy(yytext);
|
||||
return token::ID;
|
||||
}
|
||||
|
||||
{EOL} { sta::saif_reader->incrLine(); }
|
||||
{EOL} { loc->lines(); loc->step(); }
|
||||
|
||||
{BLANK} { /* Ignore blanks. */ }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
%{
|
||||
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -24,20 +22,41 @@
|
|||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
%{
|
||||
#include <cctype>
|
||||
|
||||
#include "Report.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "power/SaifReaderPvt.hh"
|
||||
#include "power/SaifScanner.hh"
|
||||
|
||||
int SaifLex_lex();
|
||||
#define SaifParse_lex SaifLex_lex
|
||||
// use yacc generated parser errors
|
||||
#define YYERROR_VERBOSE
|
||||
#undef yylex
|
||||
#define yylex scanner->lex
|
||||
|
||||
#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
|
||||
%expect 2
|
||||
|
||||
|
|
@ -86,9 +105,9 @@ header_stmt:
|
|||
| '(' VENDOR QSTRING ')' { sta::stringDelete($3); }
|
||||
| '(' PROGRAM_NAME QSTRING ')' { sta::stringDelete($3); }
|
||||
| '(' VERSION QSTRING ')' { sta::stringDelete($3); }
|
||||
| '(' DIVIDER hchar ')' { sta::saif_reader->setDivider($3); }
|
||||
| '(' TIMESCALE UINT ID ')' { sta::saif_reader->setTimescale($3, $4); }
|
||||
| '(' DURATION UINT ')' { sta::saif_reader->setDuration($3); }
|
||||
| '(' DIVIDER hchar ')' { reader->setDivider($3); }
|
||||
| '(' TIMESCALE UINT ID ')' { reader->setTimescale($3, $4); }
|
||||
| '(' DURATION UINT ')' { reader->setDuration($3); }
|
||||
;
|
||||
|
||||
hchar:
|
||||
|
|
@ -100,13 +119,13 @@ hchar:
|
|||
|
||||
instance:
|
||||
'(' INSTANCE ID
|
||||
{ sta::saif_reader->instancePush($3); }
|
||||
{ reader->instancePush($3); }
|
||||
instance_contents ')'
|
||||
{ sta::saif_reader->instancePop(); }
|
||||
{ reader->instancePop(); }
|
||||
| '(' INSTANCE QSTRING ID
|
||||
{ sta::saif_reader->instancePush($3); }
|
||||
{ reader->instancePush($3); }
|
||||
instance_contents ')'
|
||||
{ sta::saif_reader->instancePop(); }
|
||||
{ reader->instancePop(); }
|
||||
;
|
||||
|
||||
instance_contents:
|
||||
|
|
@ -128,7 +147,7 @@ nets:
|
|||
|
||||
net:
|
||||
'(' ID state_durations ')'
|
||||
{ sta::saif_reader->setNetDurations($2, $3); }
|
||||
{ reader->setNetDurations($2, $3); }
|
||||
;
|
||||
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -29,33 +29,27 @@
|
|||
|
||||
#include "Error.hh"
|
||||
#include "Debug.hh"
|
||||
#include "Stats.hh"
|
||||
#include "Report.hh"
|
||||
#include "Network.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Power.hh"
|
||||
#include "power/SaifReaderPvt.hh"
|
||||
#include "power/SaifScanner.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
extern int
|
||||
SaifParse_parse();
|
||||
extern int SaifParse_debug;
|
||||
|
||||
namespace sta {
|
||||
|
||||
using std::min;
|
||||
|
||||
SaifReader *saif_reader = nullptr;
|
||||
|
||||
bool
|
||||
readSaif(const char *filename,
|
||||
const char *scope,
|
||||
Sta *sta)
|
||||
{
|
||||
SaifReader reader(filename, scope, sta);
|
||||
saif_reader = &reader;
|
||||
bool success = reader.read();
|
||||
saif_reader = nullptr;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -65,8 +59,6 @@ SaifReader::SaifReader(const char *filename,
|
|||
StaState(sta),
|
||||
filename_(filename),
|
||||
scope_(scope),
|
||||
stream_(nullptr),
|
||||
line_(1),
|
||||
divider_('/'),
|
||||
escape_('\\'),
|
||||
timescale_(1.0E-9F), // default units of ns
|
||||
|
|
@ -76,23 +68,16 @@ SaifReader::SaifReader(const char *filename,
|
|||
{
|
||||
}
|
||||
|
||||
SaifReader::~SaifReader()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SaifReader::read()
|
||||
{
|
||||
// Use zlib to uncompress gzip'd files automagically.
|
||||
stream_ = gzopen(filename_, "rb");
|
||||
if (stream_) {
|
||||
saif_scope_.clear();
|
||||
in_scope_level_ = 0;
|
||||
annotated_pins_.clear();
|
||||
//::SaifParse_debug = 1;
|
||||
gzstream::igzstream stream(filename_);
|
||||
if (stream.is_open()) {
|
||||
Stats stats(debug_, report_);
|
||||
SaifScanner scanner(&stream, filename_, this, report_);
|
||||
SaifParse parser(&scanner, this);
|
||||
// yyparse returns 0 on success.
|
||||
bool success = (::SaifParse_parse() == 0);
|
||||
gzclose(stream_);
|
||||
bool success = (parser.parse() == 0);
|
||||
report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size());
|
||||
return success;
|
||||
}
|
||||
|
|
@ -122,10 +107,10 @@ SaifReader::setTimescale(uint64_t multiplier,
|
|||
else if (stringEq(units, "fs"))
|
||||
timescale_ = multiplier * 1E-15;
|
||||
else
|
||||
saifError(180, "TIMESCALE units not us, ns, or ps.");
|
||||
report_->error(180, "SAIF TIMESCALE units not us, ns, or ps.");
|
||||
}
|
||||
else
|
||||
saifError(181, "TIMESCALE multiplier not 1, 10, or 100.");
|
||||
report_->error(181, "SAIF TIMESCALE multiplier not 1, 10, or 100.");
|
||||
stringDelete(units);
|
||||
}
|
||||
|
||||
|
|
@ -221,72 +206,23 @@ SaifReader::unescaped(const char *token)
|
|||
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
|
||||
SaifReader::getChars(char *buf,
|
||||
size_t &result,
|
||||
size_t max_size)
|
||||
SaifScanner::error(const char *msg)
|
||||
{
|
||||
char *status = gzgets(stream_, buf, max_size);
|
||||
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);
|
||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Global namespace
|
||||
|
||||
void saifFlushBuffer();
|
||||
|
||||
int
|
||||
SaifParse_error(const char *msg)
|
||||
{
|
||||
saifFlushBuffer();
|
||||
sta::saif_reader->saifError(196, "%s.\n", msg);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,15 +39,11 @@
|
|||
|
||||
// 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 {
|
||||
|
||||
class Sta;
|
||||
class Power;
|
||||
class SaifScanner;
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
|
@ -62,7 +58,6 @@ public:
|
|||
SaifReader(const char *filename,
|
||||
const char *scope,
|
||||
Sta *sta);
|
||||
~SaifReader();
|
||||
bool read();
|
||||
|
||||
void setDivider(char divider);
|
||||
|
|
@ -73,24 +68,7 @@ public:
|
|||
void instancePop();
|
||||
void setNetDurations(const char *net_name,
|
||||
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_; }
|
||||
int line() { return line_; }
|
||||
void saifWarn(int id,
|
||||
const char *fmt, ...);
|
||||
void saifError(int id,
|
||||
const char *fmt,
|
||||
...);
|
||||
void notSupported(const char *feature);
|
||||
|
||||
private:
|
||||
string unescaped(const char *token);
|
||||
|
|
@ -98,8 +76,6 @@ private:
|
|||
const char *filename_;
|
||||
const char *scope_; // Divider delimited scope to begin annotation.
|
||||
|
||||
gzFile stream_;
|
||||
int line_;
|
||||
char divider_;
|
||||
char escape_;
|
||||
double timescale_;
|
||||
|
|
@ -112,6 +88,4 @@ private:
|
|||
Power *power_;
|
||||
};
|
||||
|
||||
extern SaifReader *saif_reader;
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -64,19 +64,20 @@ void
|
|||
InputDrive::driveResistance(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
float &res,
|
||||
bool &exists)
|
||||
bool &exists) const
|
||||
{
|
||||
drive_resistances_.value(rf, min_max, res, exists);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool
|
||||
InputDrive::driveResistanceMinMaxEqual(const RiseFall *rf)
|
||||
InputDrive::driveResistanceMinMaxEqual(const RiseFall *rf) const
|
||||
{
|
||||
float min_res, max_res;
|
||||
bool min_exists, max_exists;
|
||||
|
|
@ -120,7 +121,7 @@ InputDrive::driveCell(const RiseFall *rf,
|
|||
const LibertyCell *&cell,
|
||||
const LibertyPort *&from_port,
|
||||
float *&from_slews,
|
||||
const LibertyPort *&to_port)
|
||||
const LibertyPort *&to_port) const
|
||||
{
|
||||
InputDriveCell *drive = drive_cells_[rf->index()][min_max->index()];
|
||||
if (drive) {
|
||||
|
|
@ -139,20 +140,20 @@ InputDrive::driveCell(const RiseFall *rf,
|
|||
|
||||
InputDriveCell *
|
||||
InputDrive::driveCell(const RiseFall *rf,
|
||||
const MinMax *min_max)
|
||||
const MinMax *min_max) const
|
||||
{
|
||||
return drive_cells_[rf->index()][min_max->index()];
|
||||
}
|
||||
|
||||
bool
|
||||
InputDrive::hasDriveCell(const RiseFall *rf,
|
||||
const MinMax *min_max)
|
||||
const MinMax *min_max) const
|
||||
{
|
||||
return drive_cells_[rf->index()][min_max->index()] != nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
InputDrive::driveCellsEqual()
|
||||
InputDrive::driveCellsEqual() const
|
||||
{
|
||||
int rise_index = RiseFall::riseIndex();
|
||||
int fall_index = RiseFall::fallIndex();
|
||||
|
|
@ -171,7 +172,7 @@ void
|
|||
InputDrive::slew(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
float &slew,
|
||||
bool &exists)
|
||||
bool &exists) const
|
||||
{
|
||||
slews_.value(rf, min_max, slew, exists);
|
||||
}
|
||||
|
|
|
|||
12
sdc/Sdc.tcl
12
sdc/Sdc.tcl
|
|
@ -42,7 +42,13 @@ proc_redirect read_sdc {
|
|||
check_argc_eq1 "read_sdc" $args
|
||||
set echo [info exists flags(-echo)]
|
||||
set filename [file nativename [lindex $args 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 verbose [info exists flags(-verbose)]
|
||||
set filename [file nativename [lindex $args 0]]
|
||||
set prev_filename [info script]
|
||||
try {
|
||||
info script $filename
|
||||
source_ $filename $echo $verbose
|
||||
} finally {
|
||||
info script $prev_filename
|
||||
}
|
||||
}
|
||||
|
||||
proc source_ { filename echo verbose } {
|
||||
|
|
|
|||
|
|
@ -1716,7 +1716,7 @@ WriteSdc::writeInputTransitions() const
|
|||
Port *port = port_iter->next();
|
||||
InputDrive *drive = sdc_->findInputDrive(port);
|
||||
if (drive) {
|
||||
RiseFallMinMax *slews = drive->slews();
|
||||
const RiseFallMinMax *slews = drive->slews();
|
||||
WriteGetPort write_port(port, this);
|
||||
writeRiseFallMinMaxTimeCmd("set_input_transition", slews, write_port);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,14 @@
|
|||
|
||||
// warning: variable 'yynerrs_' set but not used
|
||||
#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"
|
||||
|
|
@ -44,11 +52,7 @@
|
|||
%define parse.assert
|
||||
%parse-param { SdfScanner *scanner }
|
||||
%parse-param { SdfReader *reader }
|
||||
|
||||
// bison 3.0.4 for centos7
|
||||
%define parser_class_name {SdfParse}
|
||||
// bison 3.3.2
|
||||
//%define api.parser.class {SdfParse}
|
||||
%define api.parser.class {SdfParse}
|
||||
|
||||
// expected shift/reduce conflicts
|
||||
%expect 4
|
||||
|
|
|
|||
|
|
@ -1103,14 +1103,4 @@ SdfScanner::error(const char *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
|
||||
|
|
|
|||
|
|
@ -24,15 +24,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "SdfLocation.hh"
|
||||
#include "SdfParse.hh"
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
#undef yyFlexLexer
|
||||
#define yyFlexLexer SdfFlexLexer
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
#include "SdfLocation.hh"
|
||||
#include "SdfParse.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class Report;
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ public:
|
|||
PathVertex *ref_path,
|
||||
TimingArc *check_arc,
|
||||
Edge *check_edge);
|
||||
PathVertex *clkPath() { return &clk_path_; }
|
||||
const PathVertex *clkPath() const { return &clk_path_; }
|
||||
Pin *clkPin(const StaState *sta) const;
|
||||
PathVertex *refPath() { return &ref_path_; }
|
||||
const PathVertex *refPath() const { return &ref_path_; }
|
||||
Pin *refPin(const StaState *sta) const;
|
||||
Delay skew(const StaState *sta) const;
|
||||
ArcDelay maxSkew(const StaState *sta) const;
|
||||
|
|
|
|||
|
|
@ -51,15 +51,15 @@ void
|
|||
Latches::latchRequired(const Path *data_path,
|
||||
const PathVertex *enable_path,
|
||||
const PathVertex *disable_path,
|
||||
MultiCyclePath *mcp,
|
||||
PathDelay *path_delay,
|
||||
const MultiCyclePath *mcp,
|
||||
const PathDelay *path_delay,
|
||||
Arrival src_clk_latency,
|
||||
const ArcDelay &margin,
|
||||
// Return values.
|
||||
Required &required,
|
||||
Arrival &borrow,
|
||||
Arrival &adjusted_data_arrival,
|
||||
Delay &time_given_to_startpoint)
|
||||
Delay &time_given_to_startpoint) const
|
||||
{
|
||||
const Arrival data_arrival = data_path->arrival(this);
|
||||
float max_delay = 0.0;
|
||||
|
|
@ -161,7 +161,7 @@ Latches::latchBorrowInfo(const Path *data_path,
|
|||
Crpr &open_crpr,
|
||||
Crpr &crpr_diff,
|
||||
Delay &max_borrow,
|
||||
bool &borrow_limit_exists)
|
||||
bool &borrow_limit_exists) const
|
||||
{
|
||||
if (data_path && enable_path && disable_path) {
|
||||
const ClockEdge *data_clk_edge = data_path->clkEdge(this);
|
||||
|
|
@ -220,7 +220,7 @@ Latches::latchRequired(const Path *data_path,
|
|||
Required &required,
|
||||
Arrival &borrow,
|
||||
Arrival &adjusted_data_arrival,
|
||||
Delay &time_given_to_startpoint)
|
||||
Delay &time_given_to_startpoint) const
|
||||
{
|
||||
Vertex *data_vertex = data_path->vertex(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.
|
||||
void
|
||||
Latches::latchEnableOtherPath(Path *path,
|
||||
Latches::latchEnableOtherPath(const Path *path,
|
||||
const PathAnalysisPt *tgt_clk_path_ap,
|
||||
// Return value.
|
||||
PathVertex &other_path)
|
||||
PathVertex &other_path) const
|
||||
{
|
||||
Vertex *vertex = path->vertex(this);
|
||||
const ClockEdge *clk_edge = path->clkEdge(this);
|
||||
|
|
@ -266,8 +266,8 @@ Latches::latchEnableOtherPath(Path *path,
|
|||
}
|
||||
|
||||
void
|
||||
Latches::latchEnablePath(Path *q_path,
|
||||
Edge *d_q_edge,
|
||||
Latches::latchEnablePath(const Path *q_path,
|
||||
const Edge *d_q_edge,
|
||||
// Return value.
|
||||
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
|
||||
// the enable open edge.
|
||||
void
|
||||
Latches::latchOutArrival(Path *data_path,
|
||||
TimingArc *d_q_arc,
|
||||
Edge *d_q_edge,
|
||||
Latches::latchOutArrival(const Path *data_path,
|
||||
const TimingArc *d_q_arc,
|
||||
const Edge *d_q_edge,
|
||||
const PathAnalysisPt *path_ap,
|
||||
// Return values.
|
||||
Tag *&q_tag,
|
||||
|
|
@ -398,7 +398,7 @@ Latches::latchOutArrival(Path *data_path,
|
|||
}
|
||||
|
||||
ExceptionPath *
|
||||
Latches::exceptionTo(Path *data_path,
|
||||
Latches::exceptionTo(const Path *data_path,
|
||||
const ClockEdge *en_clk_edge)
|
||||
{
|
||||
// Look for exceptions -to data or -to enable clk.
|
||||
|
|
@ -415,7 +415,7 @@ ArcDelay
|
|||
Latches::latchSetupMargin(Vertex *data_vertex,
|
||||
const RiseFall *data_rf,
|
||||
const Path *disable_path,
|
||||
const PathAnalysisPt *path_ap)
|
||||
const PathAnalysisPt *path_ap) const
|
||||
{
|
||||
if (disable_path) {
|
||||
Vertex *enable_vertex = disable_path->vertex(this);
|
||||
|
|
@ -443,12 +443,12 @@ Latches::latchSetupMargin(Vertex *data_vertex,
|
|||
}
|
||||
|
||||
void
|
||||
Latches::latchTimeGivenToStartpoint(Path *d_path,
|
||||
Path *q_path,
|
||||
Edge *d_q_edge,
|
||||
Latches::latchTimeGivenToStartpoint(const Path *d_path,
|
||||
const Path *q_path,
|
||||
const Edge *d_q_edge,
|
||||
// Return values.
|
||||
Arrival &time_given,
|
||||
PathVertex &enable_path)
|
||||
PathVertex &enable_path) const
|
||||
{
|
||||
latchEnablePath(q_path, d_q_edge, enable_path);
|
||||
if (!enable_path.isNull()
|
||||
|
|
@ -470,7 +470,7 @@ Latches::latchTimeGivenToStartpoint(Path *d_path,
|
|||
}
|
||||
|
||||
void
|
||||
Latches::latchDtoQEnable(Edge *d_q_edge,
|
||||
Latches::latchDtoQEnable(const Edge *d_q_edge,
|
||||
const Instance *inst,
|
||||
// Return values.
|
||||
Vertex *&enable_vertex,
|
||||
|
|
|
|||
|
|
@ -38,24 +38,24 @@ class Latches : public StaState
|
|||
{
|
||||
public:
|
||||
Latches(StaState *sta);
|
||||
void latchTimeGivenToStartpoint(Path *d_path,
|
||||
Path *q_path,
|
||||
Edge *d_q_edge,
|
||||
void latchTimeGivenToStartpoint(const Path *d_path,
|
||||
const Path *q_path,
|
||||
const Edge *d_q_edge,
|
||||
// Return values.
|
||||
Arrival &time_given,
|
||||
PathVertex &enable_path);
|
||||
PathVertex &enable_path) const;
|
||||
void latchRequired(const Path *data_path,
|
||||
const PathVertex *enable_path,
|
||||
const PathVertex *disable_path,
|
||||
MultiCyclePath *mcp,
|
||||
PathDelay *path_delay,
|
||||
const MultiCyclePath *mcp,
|
||||
const PathDelay *path_delay,
|
||||
Arrival src_clk_latency,
|
||||
const ArcDelay &margin,
|
||||
// Return values.
|
||||
Required &required,
|
||||
Delay &borrow,
|
||||
Arrival &adjusted_data_arrival,
|
||||
Delay &time_given_to_startpoint);
|
||||
Delay &time_given_to_startpoint) const;
|
||||
void latchRequired(const Path *data_path,
|
||||
const PathVertex *enable_path,
|
||||
const PathVertex *disable_path,
|
||||
|
|
@ -64,7 +64,7 @@ public:
|
|||
Required &required,
|
||||
Delay &borrow,
|
||||
Arrival &adjusted_data_arrival,
|
||||
Delay &time_given_to_startpoint);
|
||||
Delay &time_given_to_startpoint) const;
|
||||
void latchBorrowInfo(const Path *data_path,
|
||||
const PathVertex *enable_path,
|
||||
const PathVertex *disable_path,
|
||||
|
|
@ -78,26 +78,27 @@ public:
|
|||
Crpr &open_crpr,
|
||||
Crpr &crpr_diff,
|
||||
Delay &max_borrow,
|
||||
bool &borrow_limit_exists);
|
||||
bool &borrow_limit_exists) const;
|
||||
bool isLatchDtoQ(Edge *edge) const;
|
||||
// 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,
|
||||
// Return values.
|
||||
Vertex *&enable_vertex,
|
||||
const RiseFall *&enable_rf,
|
||||
LatchEnableState &state) const;
|
||||
LatchEnableState latchDtoQState(Edge *d_q_edge) const;
|
||||
void latchEnableOtherPath(Path *path,
|
||||
void latchEnableOtherPath(const Path *path,
|
||||
const PathAnalysisPt *tgt_clk_path_ap,
|
||||
// Return value.
|
||||
PathVertex &other_path);
|
||||
void latchEnablePath(Path *q_path, Edge *d_q_edge,
|
||||
PathVertex &other_path) const;
|
||||
void latchEnablePath(const Path *q_path,
|
||||
const Edge *d_q_edge,
|
||||
// Return value.
|
||||
PathVertex &enable_path) const;
|
||||
void latchOutArrival(Path *data_path,
|
||||
TimingArc *d_q_arc,
|
||||
Edge *d_q_edge,
|
||||
void latchOutArrival(const Path *data_path,
|
||||
const TimingArc *d_q_arc,
|
||||
const Edge *d_q_edge,
|
||||
const PathAnalysisPt *path_ap,
|
||||
Tag *&q_tag,
|
||||
ArcDelay &arc_delay,
|
||||
|
|
@ -107,8 +108,8 @@ protected:
|
|||
ArcDelay latchSetupMargin(Vertex *data_vertex,
|
||||
const RiseFall *data_rf,
|
||||
const Path *disable_path,
|
||||
const PathAnalysisPt *path_ap);
|
||||
ExceptionPath *exceptionTo(Path *data_path,
|
||||
const PathAnalysisPt *path_ap) const;
|
||||
ExceptionPath *exceptionTo(const Path *data_path,
|
||||
const ClockEdge *en_clk_edge);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ PathEnd::checkInterClkUncertainty(const ClockEdge *src_clk_edge,
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
PathEndUnconstrained::reportFull(ReportPath *report) const
|
||||
PathEndUnconstrained::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
|
@ -440,7 +440,7 @@ PathEndUnconstrained::slackNoCrpr(const StaState *) const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndUnconstrained::reportShort(ReportPath *report) const
|
||||
PathEndUnconstrained::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -979,13 +979,13 @@ PathEndCheck::typeName() const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndCheck::reportFull(ReportPath *report) const
|
||||
PathEndCheck::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndCheck::reportShort(ReportPath *report) const
|
||||
PathEndCheck::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -1170,13 +1170,13 @@ PathEndLatchCheck::latchDisable() const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndLatchCheck::reportFull(ReportPath *report) const
|
||||
PathEndLatchCheck::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndLatchCheck::reportShort(ReportPath *report) const
|
||||
PathEndLatchCheck::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -1359,13 +1359,13 @@ PathEndOutputDelay::typeName() const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndOutputDelay::reportFull(ReportPath *report) const
|
||||
PathEndOutputDelay::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndOutputDelay::reportShort(ReportPath *report) const
|
||||
PathEndOutputDelay::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -1571,13 +1571,13 @@ PathEndGatedClock::checkRole(const StaState *) const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndGatedClock::reportFull(ReportPath *report) const
|
||||
PathEndGatedClock::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndGatedClock::reportShort(ReportPath *report) const
|
||||
PathEndGatedClock::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -1734,13 +1734,13 @@ PathEndDataCheck::checkRole(const StaState *sta) const
|
|||
}
|
||||
|
||||
void
|
||||
PathEndDataCheck::reportFull(ReportPath *report) const
|
||||
PathEndDataCheck::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndDataCheck::reportShort(ReportPath *report) const
|
||||
PathEndDataCheck::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
@ -1858,13 +1858,13 @@ PathEndPathDelay::findSrcClkArrival(const StaState *sta)
|
|||
}
|
||||
|
||||
void
|
||||
PathEndPathDelay::reportFull(ReportPath *report) const
|
||||
PathEndPathDelay::reportFull(const ReportPath *report) const
|
||||
{
|
||||
report->reportFull(this);
|
||||
}
|
||||
|
||||
void
|
||||
PathEndPathDelay::reportShort(ReportPath *report) const
|
||||
PathEndPathDelay::reportShort(const ReportPath *report) const
|
||||
{
|
||||
report->reportShort(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,31 +164,31 @@ PathExpanded::path(size_t index) const
|
|||
}
|
||||
|
||||
TimingArc *
|
||||
PathExpanded::prevArc(size_t index)
|
||||
PathExpanded::prevArc(size_t index) const
|
||||
{
|
||||
return prev_arcs_[pathsIndex(index)];
|
||||
}
|
||||
|
||||
PathRef *
|
||||
PathExpanded::startPath()
|
||||
const PathRef *
|
||||
PathExpanded::startPath() const
|
||||
{
|
||||
return &paths_[start_index_];
|
||||
}
|
||||
|
||||
PathRef *
|
||||
PathExpanded::endPath()
|
||||
const PathRef *
|
||||
PathExpanded::endPath() const
|
||||
{
|
||||
return &paths_[0];
|
||||
}
|
||||
|
||||
TimingArc *
|
||||
PathExpanded::startPrevArc()
|
||||
PathExpanded::startPrevArc() const
|
||||
{
|
||||
return prev_arcs_[start_index_];
|
||||
}
|
||||
|
||||
PathRef *
|
||||
PathExpanded::startPrevPath()
|
||||
const PathRef *
|
||||
PathExpanded::startPrevPath() const
|
||||
{
|
||||
size_t start1 = start_index_ + 1;
|
||||
if (start1 < paths_.size())
|
||||
|
|
@ -198,11 +198,11 @@ PathExpanded::startPrevPath()
|
|||
}
|
||||
|
||||
void
|
||||
PathExpanded::clkPath(PathRef &clk_path)
|
||||
PathExpanded::clkPath(PathRef &clk_path) const
|
||||
{
|
||||
const Latches *latches = sta_->latches();
|
||||
PathRef *start = startPath();
|
||||
TimingArc *prev_arc = startPrevArc();
|
||||
const PathRef *start = startPath();
|
||||
const TimingArc *prev_arc = startPrevArc();
|
||||
if (start && prev_arc) {
|
||||
TimingRole *role = prev_arc->role();
|
||||
if (role == TimingRole::latchDtoQ()) {
|
||||
|
|
@ -215,7 +215,7 @@ PathExpanded::clkPath(PathRef &clk_path)
|
|||
}
|
||||
else if (role == TimingRole::regClkToQ()
|
||||
|| role == TimingRole::latchEnToQ()) {
|
||||
PathRef *start_prev = startPrevPath();
|
||||
const PathRef *start_prev = startPrevPath();
|
||||
if (start_prev)
|
||||
clk_path.init(start_prev);
|
||||
}
|
||||
|
|
@ -226,15 +226,15 @@ PathExpanded::clkPath(PathRef &clk_path)
|
|||
|
||||
void
|
||||
PathExpanded::latchPaths(// Return values.
|
||||
PathRef *&d_path,
|
||||
PathRef *&q_path,
|
||||
Edge *&d_q_edge)
|
||||
const PathRef *&d_path,
|
||||
const PathRef *&q_path,
|
||||
Edge *&d_q_edge) const
|
||||
{
|
||||
d_path = nullptr;
|
||||
q_path = nullptr;
|
||||
d_q_edge = nullptr;
|
||||
PathRef *start = startPath();
|
||||
TimingArc *prev_arc = startPrevArc();
|
||||
const PathRef *start = startPath();
|
||||
const TimingArc *prev_arc = startPrevArc();
|
||||
if (start
|
||||
&& prev_arc
|
||||
&& prev_arc->role() == TimingRole::latchDtoQ()) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -44,7 +44,7 @@ typedef Vector<ReportField*> ReportFieldSeq;
|
|||
class ReportPath : public StaState
|
||||
{
|
||||
public:
|
||||
explicit ReportPath(StaState *sta);
|
||||
ReportPath(StaState *sta);
|
||||
virtual ~ReportPath();
|
||||
ReportPathFormat pathFormat() const { return format_; }
|
||||
void setPathFormat(ReportPathFormat format);
|
||||
|
|
@ -61,93 +61,93 @@ public:
|
|||
void setNoSplit(bool no_split);
|
||||
bool reportSigmas() const { return report_sigmas_; }
|
||||
void setReportSigmas(bool report);
|
||||
ReportField *findField(const char *name);
|
||||
ReportField *findField(const char *name) const;
|
||||
|
||||
// Header above reportPathEnd results.
|
||||
void reportPathEndHeader();
|
||||
void reportPathEndHeader() const;
|
||||
// Footer below reportPathEnd results.
|
||||
void reportPathEndFooter();
|
||||
void reportPathEnd(PathEnd *end);
|
||||
void reportPathEndFooter() const;
|
||||
void reportPathEnd(const PathEnd *end) const;
|
||||
// Format report_path_endpoint only:
|
||||
// Previous path end is used to detect path group changes
|
||||
// so headers are reported by group.
|
||||
void reportPathEnd(PathEnd *end,
|
||||
PathEnd *prev_end,
|
||||
bool last);
|
||||
void reportPathEnds(PathEndSeq *ends);
|
||||
void reportPath(const Path *path);
|
||||
void reportPathEnd(const PathEnd *end,
|
||||
const PathEnd *prev_end,
|
||||
bool last) const;
|
||||
void reportPathEnds(const PathEndSeq *ends) const;
|
||||
void reportPath(const Path *path) const;
|
||||
|
||||
void reportShort(const PathEndUnconstrained *end);
|
||||
void reportShort(const PathEndCheck *end);
|
||||
void reportShort(const PathEndLatchCheck *end);
|
||||
void reportShort(const PathEndPathDelay *end);
|
||||
void reportShort(const PathEndOutputDelay *end);
|
||||
void reportShort(const PathEndGatedClock *end);
|
||||
void reportShort(const PathEndDataCheck *end);
|
||||
void reportShort(const PathEndUnconstrained *end) const;
|
||||
void reportShort(const PathEndCheck *end) const;
|
||||
void reportShort(const PathEndLatchCheck *end) const;
|
||||
void reportShort(const PathEndPathDelay *end) const;
|
||||
void reportShort(const PathEndOutputDelay *end) const;
|
||||
void reportShort(const PathEndGatedClock *end) const;
|
||||
void reportShort(const PathEndDataCheck *end) const;
|
||||
|
||||
void reportFull(const PathEndUnconstrained *end);
|
||||
void reportFull(const PathEndCheck *end);
|
||||
void reportFull(const PathEndLatchCheck *end);
|
||||
void reportFull(const PathEndPathDelay *end);
|
||||
void reportFull(const PathEndOutputDelay *end);
|
||||
void reportFull(const PathEndGatedClock *end);
|
||||
void reportFull(const PathEndDataCheck *end);
|
||||
void reportFull(const PathEndUnconstrained *end) const;
|
||||
void reportFull(const PathEndCheck *end) const;
|
||||
void reportFull(const PathEndLatchCheck *end) const;
|
||||
void reportFull(const PathEndPathDelay *end) const;
|
||||
void reportFull(const PathEndOutputDelay *end) const;
|
||||
void reportFull(const PathEndGatedClock *end) const;
|
||||
void reportFull(const PathEndDataCheck *end) const;
|
||||
|
||||
void reportJsonHeader();
|
||||
void reportJsonFooter();
|
||||
void reportJsonHeader() const;
|
||||
void reportJsonFooter() const;
|
||||
void reportJson(const PathEnd *end,
|
||||
bool last);
|
||||
void reportJson(const Path *path);
|
||||
bool last) const;
|
||||
void reportJson(const Path *path) const;
|
||||
void reportJson(const Path *path,
|
||||
const char *path_name,
|
||||
int indent,
|
||||
bool trailing_comma,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportJson(const PathExpanded &expanded,
|
||||
const char *path_name,
|
||||
int indent,
|
||||
bool trailing_comma,
|
||||
string &result);
|
||||
string &result) const;
|
||||
|
||||
void reportEndHeader();
|
||||
void reportEndLine(PathEnd *end);
|
||||
void reportEndHeader() const;
|
||||
void reportEndLine(const PathEnd *end) const;
|
||||
|
||||
void reportSummaryHeader();
|
||||
void reportSummaryLine(PathEnd *end);
|
||||
void reportSummaryHeader() const;
|
||||
void reportSummaryLine(const PathEnd *end) const;
|
||||
|
||||
void reportSlackOnlyHeader();
|
||||
void reportSlackOnly(PathEnd *end);
|
||||
void reportSlackOnlyHeader() const;
|
||||
void reportSlackOnly(const PathEnd *end) const;
|
||||
|
||||
void reportMpwCheck(MinPulseWidthCheck *check,
|
||||
bool verbose);
|
||||
void reportMpwChecks(MinPulseWidthCheckSeq *checks,
|
||||
bool verbose);
|
||||
void reportMpwHeaderShort();
|
||||
void reportShort(MinPulseWidthCheck *check);
|
||||
void reportVerbose(MinPulseWidthCheck *check);
|
||||
void reportMpwCheck(const MinPulseWidthCheck *check,
|
||||
bool verbose) const;
|
||||
void reportMpwChecks(const MinPulseWidthCheckSeq *checks,
|
||||
bool verbose) const;
|
||||
void reportMpwHeaderShort() const;
|
||||
void reportShort(const MinPulseWidthCheck *check) const;
|
||||
void reportVerbose(const MinPulseWidthCheck *check) const;
|
||||
|
||||
void reportCheck(MinPeriodCheck *check,
|
||||
bool verbose);
|
||||
void reportChecks(MinPeriodCheckSeq *checks,
|
||||
bool verbose);
|
||||
void reportPeriodHeaderShort();
|
||||
void reportShort(MinPeriodCheck *check);
|
||||
void reportVerbose(MinPeriodCheck *check);
|
||||
void reportCheck(const MinPeriodCheck *check,
|
||||
bool verbose) const;
|
||||
void reportChecks(const MinPeriodCheckSeq *checks,
|
||||
bool verbose) const;
|
||||
void reportPeriodHeaderShort() const;
|
||||
void reportShort(const MinPeriodCheck *check) const;
|
||||
void reportVerbose(const MinPeriodCheck *check) const;
|
||||
|
||||
void reportCheck(MaxSkewCheck *check,
|
||||
bool verbose);
|
||||
void reportChecks(MaxSkewCheckSeq *checks,
|
||||
bool verbose);
|
||||
void reportMaxSkewHeaderShort();
|
||||
void reportShort(MaxSkewCheck *check);
|
||||
void reportVerbose(MaxSkewCheck *check);
|
||||
void reportCheck(const MaxSkewCheck *check,
|
||||
bool verbose) const;
|
||||
void reportChecks(const MaxSkewCheckSeq *checks,
|
||||
bool verbose) const;
|
||||
void reportMaxSkewHeaderShort() const;
|
||||
void reportShort(const MaxSkewCheck *check) const;
|
||||
void reportVerbose(const MaxSkewCheck *check) const;
|
||||
|
||||
void reportLimitShortHeader(const ReportField *field);
|
||||
void reportLimitShortHeader(const ReportField *field) const;
|
||||
void reportLimitShort(const ReportField *field,
|
||||
Pin *pin,
|
||||
float value,
|
||||
float limit,
|
||||
float slack);
|
||||
float slack) const;
|
||||
void reportLimitVerbose(const ReportField *field,
|
||||
Pin *pin,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -155,7 +155,7 @@ public:
|
|||
float limit,
|
||||
float slack,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
ReportField *fieldSlew() const { return field_slew_; }
|
||||
ReportField *fieldFanout() const { return field_fanout_; }
|
||||
ReportField *fieldCapacitance() const { return field_capacitance_; }
|
||||
|
|
@ -169,83 +169,83 @@ protected:
|
|||
bool left_justify,
|
||||
Unit *unit,
|
||||
bool enabled);
|
||||
void reportEndpointHeader(PathEnd *end,
|
||||
PathEnd *prev_end);
|
||||
void reportEndpointHeader(const PathEnd *end,
|
||||
const PathEnd *prev_end) const;
|
||||
void reportShort(const PathEndUnconstrained *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndCheck *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndLatchCheck *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndPathDelay *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndOutputDelay *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndGatedClock *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportShort(const PathEndDataCheck *end,
|
||||
PathExpanded &expanded);
|
||||
void reportEndpoint(const PathEndOutputDelay *end);
|
||||
void reportEndpointOutputDelay(const PathEndClkConstrained *end);
|
||||
void reportEndpoint(const PathEndPathDelay *end);
|
||||
void reportEndpoint(const PathEndGatedClock *end);
|
||||
string pathEndpoint(PathEnd *end);
|
||||
string pathStartpoint(PathEnd *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportEndpoint(const PathEndOutputDelay *end) const;
|
||||
void reportEndpointOutputDelay(const PathEndClkConstrained *end) const;
|
||||
void reportEndpoint(const PathEndPathDelay *end) const;
|
||||
void reportEndpoint(const PathEndGatedClock *end) const;
|
||||
string pathEndpoint(const PathEnd *end) const;
|
||||
string pathStartpoint(const PathEnd *end,
|
||||
const PathExpanded &expanded) const;
|
||||
void reportBorrowing(const PathEndLatchCheck *end,
|
||||
Arrival &borrow,
|
||||
Arrival &time_given_to_startpoint);
|
||||
void reportEndpoint(const PathEndDataCheck *end);
|
||||
const char *clkNetworkDelayIdealProp(bool is_ideal);
|
||||
Arrival &time_given_to_startpoint) const;
|
||||
void reportEndpoint(const PathEndDataCheck *end) const;
|
||||
const char *clkNetworkDelayIdealProp(bool is_ideal) const;
|
||||
|
||||
string checkRoleReason(const PathEnd *end);
|
||||
string checkRoleString(const PathEnd *end);
|
||||
virtual void reportGroup(const PathEnd *end);
|
||||
string checkRoleReason(const PathEnd *end) const;
|
||||
string checkRoleString(const PathEnd *end) const;
|
||||
virtual void reportGroup(const PathEnd *end) const;
|
||||
void reportStartpoint(const PathEnd *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportUnclockedEndpoint(const PathEnd *end,
|
||||
const char *default_reason);
|
||||
void reportEndpoint(const PathEndCheck *end);
|
||||
void reportEndpoint(const PathEndLatchCheck *end);
|
||||
const char *latchDesc(const PathEndLatchCheck *end);
|
||||
const char *default_reason) const;
|
||||
void reportEndpoint(const PathEndCheck *end) const;
|
||||
void reportEndpoint(const PathEndLatchCheck *end) const;
|
||||
const char *latchDesc(const PathEndLatchCheck *end) const;
|
||||
void reportStartpoint(const char *start,
|
||||
string reason);
|
||||
const string reason) const;
|
||||
void reportEndpoint(const char *end,
|
||||
string reason);
|
||||
const string reason) const;
|
||||
void reportStartEndPoint(const char *pt,
|
||||
string reason,
|
||||
const char *key);
|
||||
string tgtClkName(const PathEnd *end);
|
||||
const char *clkRegLatchDesc(const PathEnd *end);
|
||||
const string reason,
|
||||
const char *key) const;
|
||||
string tgtClkName(const PathEnd *end) const;
|
||||
const char *clkRegLatchDesc(const PathEnd *end) const;
|
||||
void reportSrcPath(const PathEnd *end,
|
||||
PathExpanded &expanded);
|
||||
void reportTgtClk(const PathEnd *end);
|
||||
const PathExpanded &expanded) const;
|
||||
void reportTgtClk(const PathEnd *end) const;
|
||||
void reportTgtClk(const PathEnd *end,
|
||||
float prev_time);
|
||||
float prev_time) const;
|
||||
void reportTgtClk(const PathEnd *end,
|
||||
float prev_time,
|
||||
bool is_prop);
|
||||
bool is_prop) const;
|
||||
void reportTgtClk(const PathEnd *end,
|
||||
float prev_time,
|
||||
float src_offset,
|
||||
bool is_prop);
|
||||
bool is_prop) const;
|
||||
bool pathFromGenPropClk(const Path *clk_path,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
bool isGenPropClk(const Clock *clk,
|
||||
const RiseFall *clk_rf,
|
||||
const MinMax *min_max,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportSrcClkAndPath(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
float time_offset,
|
||||
Arrival clk_insertion,
|
||||
Arrival clk_latency,
|
||||
bool is_path_delay);
|
||||
bool is_path_delay) const;
|
||||
bool reportGenClkSrcPath(const Path *clk_path,
|
||||
const Clock *clk,
|
||||
const RiseFall *clk_rf,
|
||||
const MinMax *min_max,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportGenClkSrcAndPath(const Path *path,
|
||||
const Clock *clk,
|
||||
const RiseFall *clk_rf,
|
||||
|
|
@ -253,7 +253,7 @@ protected:
|
|||
const PathAnalysisPt *path_ap,
|
||||
float time_offset,
|
||||
float path_time_offset,
|
||||
bool clk_used_as_data);
|
||||
bool clk_used_as_data) const;
|
||||
bool reportGenClkSrcPath1(const Clock *clk,
|
||||
const Pin *clk_pin,
|
||||
const RiseFall *clk_rf,
|
||||
|
|
@ -261,99 +261,99 @@ protected:
|
|||
const PathAnalysisPt *path_ap,
|
||||
float gclk_time,
|
||||
float time_offset,
|
||||
bool clk_used_as_data);
|
||||
bool clk_used_as_data) const;
|
||||
void reportClkSrcLatency(Arrival insertion,
|
||||
float clk_time,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportPathLine(const Path *path,
|
||||
Delay incr,
|
||||
Arrival time,
|
||||
const char *line_case);
|
||||
const char *line_case) const;
|
||||
void reportCommonClkPessimism(const PathEnd *end,
|
||||
Arrival &clk_arrival);
|
||||
Arrival &clk_arrival) const ;
|
||||
void reportClkUncertainty(const PathEnd *end,
|
||||
Arrival &clk_arrival);
|
||||
Arrival &clk_arrival) const ;
|
||||
void reportClkLine(const Clock *clk,
|
||||
const char *clk_name,
|
||||
const RiseFall *clk_rf,
|
||||
Arrival clk_time,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const ;
|
||||
void reportClkLine(const Clock *clk,
|
||||
const char *clk_name,
|
||||
const RiseFall *clk_rf,
|
||||
Arrival prev_time,
|
||||
Arrival clk_time,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const ;
|
||||
void reportRequired(const PathEnd *end,
|
||||
string margin_msg);
|
||||
void reportSlack(const PathEnd *end);
|
||||
void reportSlack(Slack slack);
|
||||
void reportSpaceSlack(PathEnd *end,
|
||||
string &line);
|
||||
string margin_msg) const ;
|
||||
void reportSlack(const PathEnd *end) const ;
|
||||
void reportSlack(Slack slack) const ;
|
||||
void reportSpaceSlack(const PathEnd *end,
|
||||
string &line) const ;
|
||||
void reportSpaceSlack(Slack slack,
|
||||
string &line);
|
||||
string &line) const ;
|
||||
void reportSrcPathArrival(const PathEnd *end,
|
||||
PathExpanded &expanded);
|
||||
const PathExpanded &expanded) const ;
|
||||
void reportPath(const PathEnd *end,
|
||||
PathExpanded &expanded);
|
||||
void reportPathFull(const Path *path);
|
||||
void reportPathHeader();
|
||||
const PathExpanded &expanded) const;
|
||||
void reportPathFull(const Path *path) const;
|
||||
void reportPathHeader() const;
|
||||
void reportPath1(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportPath2(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportPath3(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportPath4(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
bool clk_used_as_data,
|
||||
bool skip_first_path,
|
||||
bool skip_last_path,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportPath5(const Path *path,
|
||||
PathExpanded &expanded,
|
||||
const PathExpanded &expanded,
|
||||
size_t path_first_index,
|
||||
size_t path_last_index,
|
||||
bool propagated_clk,
|
||||
bool report_clk_path,
|
||||
Arrival prev_time,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportHierPinsThru(const Path *path,
|
||||
const TimingArc *prev_arc);
|
||||
const TimingArc *prev_arc) const;
|
||||
void reportInputExternalDelay(const Path *path,
|
||||
float time_offset);
|
||||
float time_offset) const;
|
||||
void reportLine(const char *what,
|
||||
Delay total,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLineNegative(const char *what,
|
||||
Delay total,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLine(const char *what,
|
||||
Delay total,
|
||||
const EarlyLate *early_late,
|
||||
const RiseFall *rf);
|
||||
const RiseFall *rf) const;
|
||||
void reportLine(const char *what,
|
||||
Delay incr,
|
||||
Delay total,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLine(const char *what,
|
||||
Delay incr,
|
||||
Delay total,
|
||||
const EarlyLate *early_late,
|
||||
const RiseFall *rf);
|
||||
const RiseFall *rf) const;
|
||||
void reportLine(const char *what,
|
||||
Slew slew,
|
||||
Delay incr,
|
||||
Delay total,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLine(const char *what,
|
||||
float cap,
|
||||
Slew slew,
|
||||
|
|
@ -364,83 +364,83 @@ protected:
|
|||
const EarlyLate *early_late,
|
||||
const RiseFall *rf,
|
||||
string src_attr,
|
||||
const char *line_case);
|
||||
const char *line_case) const;
|
||||
void reportLineTotal(const char *what,
|
||||
Delay incr,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLineTotalMinus(const char *what,
|
||||
Delay decr,
|
||||
const EarlyLate *early_late);
|
||||
const EarlyLate *early_late) const;
|
||||
void reportLineTotal1(const char *what,
|
||||
Delay incr,
|
||||
bool incr_with_minus,
|
||||
const EarlyLate *early_late);
|
||||
void reportDashLineTotal();
|
||||
const EarlyLate *early_late) const;
|
||||
void reportDashLineTotal() const;
|
||||
void reportDescription(const char *what,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportDescription(const char *what,
|
||||
bool first_field,
|
||||
bool last_field,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportFieldTime(float value,
|
||||
ReportField *field,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportSpaceFieldTime(float value,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportSpaceFieldDelay(Delay value,
|
||||
const EarlyLate *early_late,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportFieldDelayMinus(Delay value,
|
||||
const EarlyLate *early_late,
|
||||
ReportField *field,
|
||||
string &result);
|
||||
const ReportField *field,
|
||||
string &result) const;
|
||||
void reportTotalDelay(Delay value,
|
||||
const EarlyLate *early_late,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportFieldDelay(Delay value,
|
||||
const EarlyLate *early_late,
|
||||
ReportField *field,
|
||||
string &result);
|
||||
const ReportField *field,
|
||||
string &result) const;
|
||||
void reportField(float value,
|
||||
const ReportField *field,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportField(const char *value,
|
||||
const ReportField *field,
|
||||
string &result);
|
||||
string &result) const;
|
||||
void reportFieldBlank(const ReportField *field,
|
||||
string &result);
|
||||
void reportDashLine();
|
||||
void reportDashLine(int line_width);
|
||||
void reportBlankLine();
|
||||
string descriptionField(Vertex *vertex);
|
||||
string descriptionField(const Pin *pin);
|
||||
string descriptionNet(const Pin *pin);
|
||||
string &result) const;
|
||||
void reportDashLine() const;
|
||||
void reportDashLine(int line_width) const;
|
||||
void reportBlankLine() const;
|
||||
string descriptionField(const Vertex *vertex) const;
|
||||
string descriptionField(const Pin *pin) const;
|
||||
string descriptionNet(const Pin *pin) const;
|
||||
bool reportClkPath() const;
|
||||
string clkName(const Clock *clk,
|
||||
bool inverted);
|
||||
bool inverted) const;
|
||||
bool hasExtInputDriver(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
float drvrFanout(Vertex *drvr,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
const char *mpwCheckHiLow(MinPulseWidthCheck *check);
|
||||
const MinMax *min_max) const;
|
||||
const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const;
|
||||
void reportSkewClkPath(const char *arrival_msg,
|
||||
const PathVertex *clk_path);
|
||||
const char *edgeRegLatchDesc(Edge *edge,
|
||||
TimingArc *arc);
|
||||
const PathVertex *clk_path) const;
|
||||
const char *edgeRegLatchDesc(const Edge *edge,
|
||||
const TimingArc *arc) const;
|
||||
const char *checkRegLatchDesc(const TimingRole *role,
|
||||
const RiseFall *clk_rf) const;
|
||||
const char *regDesc(const RiseFall *clk_rf) const;
|
||||
const char *latchDesc(const RiseFall *clk_rf) const;
|
||||
void pathClkPath(const Path *path,
|
||||
PathRef &clk_path) const;
|
||||
bool isPropagated(const Path *clk_path);
|
||||
const PathRef &clk_path) const;
|
||||
bool isPropagated(const Path *clk_path) const;
|
||||
bool isPropagated(const Path *clk_path,
|
||||
const Clock *clk);
|
||||
bool pathFromClkPin(PathExpanded &expanded);
|
||||
const Clock *clk) const;
|
||||
bool pathFromClkPin(const PathExpanded &expanded) const;
|
||||
bool pathFromClkPin(const Path *path,
|
||||
const Pin *start_pin);
|
||||
const Pin *start_pin) const;
|
||||
void latchPaths(const Path *path,
|
||||
// Return values.
|
||||
PathRef &d_path,
|
||||
|
|
@ -448,22 +448,22 @@ protected:
|
|||
Edge *&d_q_edge) const;
|
||||
bool nextArcAnnotated(const PathRef *next_path,
|
||||
size_t next_index,
|
||||
PathExpanded &expanded,
|
||||
DcalcAPIndex ap_index);
|
||||
const PathExpanded &expanded,
|
||||
DcalcAPIndex ap_index) const;
|
||||
float tgtClkInsertionOffet(const Path *clk_path,
|
||||
const EarlyLate *early_late,
|
||||
PathAnalysisPt *path_ap);
|
||||
const PathAnalysisPt *path_ap) const;
|
||||
// InputDelay used to seed path root.
|
||||
InputDelay *pathInputDelay(const Path *path) const;
|
||||
void pathInputDelayRefPath(const Path *path,
|
||||
InputDelay *input_delay,
|
||||
const InputDelay *input_delay,
|
||||
// Return value.
|
||||
PathRef &ref_path);
|
||||
const char *asRisingFalling(const RiseFall *rf);
|
||||
const char *asRiseFall(const RiseFall *rf);
|
||||
PathRef &ref_path) const;
|
||||
const char *asRisingFalling(const RiseFall *rf) const;
|
||||
const char *asRiseFall(const RiseFall *rf) const;
|
||||
Delay delayIncr(Delay time,
|
||||
Delay prev,
|
||||
const MinMax *min_max);
|
||||
const MinMax *min_max) const;
|
||||
|
||||
// Path options.
|
||||
ReportPathFormat format_;
|
||||
|
|
|
|||
|
|
@ -2997,9 +2997,9 @@ Search::clkInfoCount() const
|
|||
}
|
||||
|
||||
ArcDelay
|
||||
Search::deratedDelay(Vertex *from_vertex,
|
||||
TimingArc *arc,
|
||||
Edge *edge,
|
||||
Search::deratedDelay(const Vertex *from_vertex,
|
||||
const TimingArc *arc,
|
||||
const Edge *edge,
|
||||
bool is_clk,
|
||||
const PathAnalysisPt *path_ap)
|
||||
{
|
||||
|
|
@ -3011,9 +3011,9 @@ Search::deratedDelay(Vertex *from_vertex,
|
|||
}
|
||||
|
||||
float
|
||||
Search::timingDerate(Vertex *from_vertex,
|
||||
TimingArc *arc,
|
||||
Edge *edge,
|
||||
Search::timingDerate(const Vertex *from_vertex,
|
||||
const TimingArc *arc,
|
||||
const Edge *edge,
|
||||
bool is_clk,
|
||||
const PathAnalysisPt *path_ap)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -321,18 +321,6 @@ required_count()
|
|||
return Sta::sta()->requiredCount();
|
||||
}
|
||||
|
||||
int
|
||||
graph_arrival_count()
|
||||
{
|
||||
return Sta::sta()->graph()->arrivalCount();
|
||||
}
|
||||
|
||||
int
|
||||
graph_required_count()
|
||||
{
|
||||
return Sta::sta()->graph()->requiredCount();
|
||||
}
|
||||
|
||||
int
|
||||
endpoint_violation_count(const MinMax *min_max)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2574,7 +2574,7 @@ Sta::reportPathEnds(PathEndSeq *ends)
|
|||
}
|
||||
|
||||
void
|
||||
Sta::reportPath(Path *path)
|
||||
Sta::reportPath(const Path *path)
|
||||
{
|
||||
report_path_->reportPath(path);
|
||||
}
|
||||
|
|
@ -3177,7 +3177,7 @@ bool
|
|||
MinPeriodEndVisitor::pathIsFromInputPort(PathEnd *path_end)
|
||||
{
|
||||
PathExpanded expanded(path_end->path(), sta_);
|
||||
PathRef *start = expanded.startPath();
|
||||
const PathRef *start = expanded.startPath();
|
||||
Graph *graph = sta_->graph();
|
||||
const Pin *first_pin = start->pin(graph);
|
||||
Network *network = sta_->network();
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ WritePathSpice::writeSpice()
|
|||
void
|
||||
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",
|
||||
network_->pathName(start_path->pin(this)),
|
||||
start_path->transition(this)->asString(),
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ void
|
|||
sta::VerilogParse::error(const location_type &loc,
|
||||
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
|
||||
%parse-param { VerilogScanner *scanner }
|
||||
%parse-param { VerilogReader *reader }
|
||||
|
||||
// bison 3.0.4 for centos7
|
||||
%define parser_class_name {VerilogParse}
|
||||
// bison 3.3.2
|
||||
//%define api.parser.class {VerilogParse}
|
||||
%define api.parser.class {VerilogParse}
|
||||
|
||||
%union {
|
||||
int ival;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -24,15 +24,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "VerilogLocation.hh"
|
||||
#include "VerilogParse.hh"
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
#undef yyFlexLexer
|
||||
#define yyFlexLexer VerilogFlexLexer
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
#include "VerilogLocation.hh"
|
||||
#include "VerilogParse.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class Report;
|
||||
|
|
|
|||
Loading…
Reference in New Issue