Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2024-10-24 06:21:47 +00:00
commit 9afc487f07
49 changed files with 402 additions and 573205 deletions

View File

@ -19,13 +19,12 @@ RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cud
tar -xvf cudd-3.0.0.tar.gz && \ tar -xvf cudd-3.0.0.tar.gz && \
rm cudd-3.0.0.tar.gz rm cudd-3.0.0.tar.gz
# Install CUDD # Build CUDD
RUN source /opt/rh/devtoolset-8/enable && \ RUN source /opt/rh/devtoolset-8/enable && \
cd cudd-3.0.0 && \ cd cudd-3.0.0 && \
mkdir ../cudd && \ mkdir ../cudd && \
./configure && \ ./configure && \
make -j`nproc` && \ make -j`nproc`
make install
FROM base-dependencies AS builder FROM base-dependencies AS builder
@ -34,7 +33,10 @@ WORKDIR /OpenSTA
# Build # Build
RUN rm -rf build && mkdir build RUN rm -rf build && mkdir build
RUN source /opt/rh/devtoolset-8/enable && cd build && cmake3 .. && make -j`nproc` RUN source /opt/rh/devtoolset-8/enable && \
cd build && \
cmake3 -DCUDD_DIR=../cudd-3.0.0 .. && \
make -j`nproc`
# Run sta on entry # Run sta on entry
ENTRYPOINT ["OpenSTA/app/sta"] ENTRYPOINT ["OpenSTA/app/sta"]

View File

@ -1,23 +1,33 @@
FROM ubuntu:18.04 FROM ubuntu:22.04
LABEL author="James Cherry" LABEL author="James Cherry"
LABEL maintainer="James Cherry <cherry@parallaxsw.com>" LABEL maintainer="James Cherry <cherry@parallaxsw.com>"
# Install basics # Install basics
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y wget cmake gcc tcl-dev tcl-tclreadline libeigen3-dev swig bison flex apt-get install -y \
wget \
cmake \
gcc \
tcl-dev \
tcl-tclreadline \
libeigen3-dev \
swig \
bison \
flex \
automake \
autotools-dev
# Download CUDD # Download CUDD
RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \ RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \
tar -xvf cudd-3.0.0.tar.gz && \ tar -xvf cudd-3.0.0.tar.gz && \
rm cudd-3.0.0.tar.gz rm cudd-3.0.0.tar.gz
# Install CUDD # Build CUDD
RUN cd cudd-3.0.0 && \ RUN cd cudd-3.0.0 && \
mkdir ../cudd && \ mkdir ../cudd && \
./configure && \ ./configure && \
make -j`nproc` && \ make -j`nproc`
make install
# Copy files and install OpenSTA # Copy files and install OpenSTA
RUN mkdir OpenSTA RUN mkdir OpenSTA
@ -26,7 +36,7 @@ RUN cd OpenSTA && \
rm -rf build && \ rm -rf build && \
mkdir build && \ mkdir build && \
cd build && \ cd build && \
cmake .. && \ cmake -DCUDD_DIR=../cudd-3.0.0 .. && \
make -j`nproc` make -j`nproc`
# Run sta on entry # Run sta on entry

View File

@ -11,6 +11,8 @@ standard file formats.
* SDC timing constraints * SDC timing constraints
* SDF delay annotation * SDF delay annotation
* SPEF parasitics * SPEF parasitics
* VCD power acitivies
* SAIF power acitivies
OpenSTA uses a TCL command interpreter to read the design, specify OpenSTA uses a TCL command interpreter to read the design, specify
timing constraints and print timing reports. timing constraints and print timing reports.
@ -51,8 +53,8 @@ netlist data structures without duplicating them.
* Simulator to propagate constants from constraints and netlist tie high/low * Simulator to propagate constants from constraints and netlist tie high/low
See doc/OpenSTA.pdf for command documentation. See doc/OpenSTA.pdf for command documentation.
See doc/StaApi.txt for timing engine API documentation.
See doc/ChangeLog.txt for changes to commands. See doc/ChangeLog.txt for changes to commands.
See doc/StaApi.txt for timing engine API documentation.
OpenSTA is dual licensed. It is released under GPL v3 as OpenSTA and OpenSTA is dual licensed. It is released under GPL v3 as OpenSTA and
is also licensed for commerical applications by Parallax Software without is also licensed for commerical applications by Parallax Software without

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
# delay calc example # delay calc example
read_liberty nangate45_slow.lib read_liberty nangate45_slow.lib.gz
read_verilog example1.v read_verilog example1.v
link_design top link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3} create_clock -name clk -period 10 {clk1 clk2 clk3}

View File

@ -1,6 +1,6 @@
# min/max delay calc example # min/max delay calc example
read_liberty -max nangate45_slow.lib read_liberty -max nangate45_slow.lib.gz
read_liberty -min nangate45_fast.lib read_liberty -min nangate45_fast.lib.gz
read_verilog example1.v read_verilog example1.v
link_design top link_design top
create_clock -name clk -period 10 {clk1 clk2 clk3} create_clock -name clk -period 10 {clk1 clk2 clk3}

View File

@ -1,8 +1,8 @@
# 3 corners with +/- 10% derating example # 3 corners with +/- 10% derating example
define_corners ss tt ff define_corners ss tt ff
read_liberty -corner ss nangate45_slow.lib read_liberty -corner ss nangate45_slow.lib.gz
read_liberty -corner tt nangate45_typ.lib read_liberty -corner tt nangate45_typ.lib.gz
read_liberty -corner ff nangate45_fast.lib read_liberty -corner ff nangate45_fast.lib.gz
read_verilog example1.v read_verilog example1.v
link_design top link_design top
set_timing_derate -early 0.9 set_timing_derate -early 0.9

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1,5 +1,5 @@
# report_power gcd # report_power gcd
read_liberty sky130hd_tt.lib read_liberty sky130hd_tt.lib.gz
read_verilog gcd_sky130hd.v read_verilog gcd_sky130hd.v
link_design gcd link_design gcd

View File

@ -1,5 +1,5 @@
# read_vcd_activities gcd # read_vcd_activities gcd
read_liberty sky130hd_tt.lib read_liberty sky130hd_tt.lib.gz
read_verilog gcd_sky130hd.v read_verilog gcd_sky130hd.v
link_design gcd link_design gcd

View File

@ -1,5 +1,5 @@
# sdf example # sdf example
read_liberty nangate45_slow.lib read_liberty nangate45_slow.lib.gz
read_verilog example1.v read_verilog example1.v
link_design top link_design top
read_sdf example1.sdf read_sdf example1.sdf

File diff suppressed because it is too large Load Diff

BIN
examples/sky130hd_tt.lib.gz Normal file

Binary file not shown.

View File

@ -1,5 +1,5 @@
# delay calc with spef parasitics # delay calc with spef parasitics
read_liberty nangate45_slow.lib read_liberty nangate45_slow.lib.gz
read_verilog example1.v read_verilog example1.v
link_design top link_design top
read_spef example1.dspef read_spef example1.dspef

View File

@ -660,12 +660,48 @@ Graph::prevPaths(Vertex *vertex) const
return prev_paths_.pointer(vertex->prevPaths()); return prev_paths_.pointer(vertex->prevPaths());
} }
void
Graph::deletePrevPaths(Vertex *vertex,
uint32_t count)
{
if (vertex->prevPaths() != object_id_null) {
{
LockGuard lock(prev_paths_lock_);
prev_paths_.destroy(vertex->prevPaths(), count);
}
vertex->setPrevPaths(object_id_null);
}
}
void void
Graph::clearPrevPaths() Graph::clearPrevPaths()
{ {
prev_paths_.clear(); prev_paths_.clear();
} }
// No locks.
void
Graph::deletePaths(Vertex *vertex,
uint32_t count)
{
if (vertex->arrivals() != arrival_null) {
arrivals_.destroy(vertex->arrivals(), count);
vertex->setArrivals(arrival_null);
}
if (vertex->requireds() != arrival_null) {
requireds_.destroy(vertex->requireds(), count);
vertex->setRequireds(arrival_null);
}
if (vertex->prevPaths() != object_id_null) {
prev_paths_.destroy(vertex->prevPaths(), count);
vertex->setPrevPaths(object_id_null);
}
vertex->tag_group_index_ = tag_group_index_max;
vertex->crpr_path_pruning_disabled_ = false;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
const Slew & const Slew &
@ -1245,16 +1281,6 @@ Vertex::setPrevPaths(PrevPathId prev_paths)
prev_paths_ = prev_paths; prev_paths_ = prev_paths;
} }
void
Vertex::deletePaths()
{
arrivals_ = arrival_null;
requireds_ = arrival_null;
prev_paths_ = prev_path_null;
tag_group_index_ = tag_group_index_max;
crpr_path_pruning_disabled_ = false;
}
LogicValue LogicValue
Vertex::simValue() const Vertex::simValue() const
{ {

View File

@ -113,7 +113,13 @@ public:
PathVertexRep *makePrevPaths(Vertex *vertex, PathVertexRep *makePrevPaths(Vertex *vertex,
uint32_t count); uint32_t count);
PathVertexRep *prevPaths(Vertex *vertex) const; PathVertexRep *prevPaths(Vertex *vertex) const;
void deletePrevPaths(Vertex *vertex,
uint32_t count);
void clearPrevPaths(); void clearPrevPaths();
// Private to Search::deletePaths1(Vertex).
void deletePaths(Vertex *vertex,
uint32_t count);
// Reported slew are the same as those in the liberty tables. // Reported slew are the same as those in the liberty tables.
// reported_slews = measured_slews / slew_derate_from_library // reported_slews = measured_slews / slew_derate_from_library
// Measured slews are between slew_lower_threshold and slew_upper_threshold. // Measured slews are between slew_lower_threshold and slew_upper_threshold.
@ -333,8 +339,6 @@ public:
// ObjectTable interface. // ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; } ObjectIdx objectIdx() const { return object_idx_; }
void setObjectIdx(ObjectIdx idx); void setObjectIdx(ObjectIdx idx);
// private to Search.cc
void deletePaths();
static int transitionCount() { return 2; } // rise/fall static int transitionCount() { return 2; } // rise/fall

View File

@ -543,6 +543,8 @@ public:
void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps); void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps);
const char *footprint() const; const char *footprint() const;
void setFootprint(const char *footprint); void setFootprint(const char *footprint);
const char *userFunctionClass() const;
void setUserFunctionClass(const char *user_function_class);
protected: protected:
void addPort(ConcretePort *port); void addPort(ConcretePort *port);
@ -634,6 +636,7 @@ protected:
bool have_voltage_waveforms_; bool have_voltage_waveforms_;
std::mutex waveform_lock_; std::mutex waveform_lock_;
const char *footprint_; const char *footprint_;
const char *user_function_class_;
private: private:
friend class LibertyLibrary; friend class LibertyLibrary;

View File

@ -498,6 +498,8 @@ protected:
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap);
void deletePaths(); void deletePaths();
void deletePaths(Vertex *vertex); void deletePaths(Vertex *vertex);
// Delete with incremental tns/wns update.
void deletePathsIncr(Vertex *vertex);
TagGroup *findTagGroup(TagGroupBldr *group_bldr); TagGroup *findTagGroup(TagGroupBldr *group_bldr);
void deleteFilterTags(); void deleteFilterTags();
void deleteFilterTagGroups(); void deleteFilterTagGroups();
@ -686,6 +688,7 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -718,6 +721,7 @@ public:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -787,6 +791,7 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,

View File

@ -892,7 +892,8 @@ public:
bool report_net, bool report_net,
bool report_cap, bool report_cap,
bool report_slew, bool report_slew,
bool report_fanout); bool report_fanout,
bool report_src_attr);
ReportField *findReportPathField(const char *name); ReportField *findReportPathField(const char *name);
void setReportPathDigits(int digits); void setReportPathDigits(int digits);
void setReportPathNoSplit(bool no_split); void setReportPathNoSplit(bool no_split);

View File

@ -941,7 +941,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
leakage_power_exists_(false), leakage_power_exists_(false),
has_internal_ports_(false), has_internal_ports_(false),
have_voltage_waveforms_(false), have_voltage_waveforms_(false),
footprint_(nullptr) footprint_(nullptr),
user_function_class_(nullptr)
{ {
liberty_cell_ = this; liberty_cell_ = this;
} }
@ -971,6 +972,7 @@ LibertyCell::~LibertyCell()
pg_port_map_.deleteContents(); pg_port_map_.deleteContents();
stringDelete(footprint_); stringDelete(footprint_);
stringDelete(user_function_class_);
} }
LibertyPort * LibertyPort *
@ -2004,6 +2006,18 @@ LibertyCell::footprint() const
return footprint_; return footprint_;
} }
void
LibertyCell::setUserFunctionClass(const char *user_function_class)
{
user_function_class_ = stringCopy(user_function_class);
}
const char*
LibertyCell::userFunctionClass() const
{
return user_function_class_;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
LibertyCellPortIterator::LibertyCellPortIterator(const LibertyCell *cell) : LibertyCellPortIterator::LibertyCellPortIterator(const LibertyCell *cell) :

View File

@ -311,6 +311,8 @@ LibertyReader::defineVisitors()
defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming); defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming);
defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors); defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors);
defineAttrVisitor("cell_footprint", &LibertyReader::visitCellFootprint); defineAttrVisitor("cell_footprint", &LibertyReader::visitCellFootprint);
defineAttrVisitor("user_function_class",
&LibertyReader::visitCellUserFunctionClass);
// Pins // Pins
defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin); defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin);
@ -2159,6 +2161,7 @@ LibertyReader::makeStatetable()
internal_ports.push_back(port); internal_ports.push_back(port);
} }
cell_->makeStatetable(input_ports, internal_ports, statetable_->table()); cell_->makeStatetable(input_ports, internal_ports, statetable_->table());
delete statetable_;
statetable_ = nullptr; statetable_ = nullptr;
} }
} }
@ -3076,6 +3079,16 @@ LibertyReader::visitCellFootprint(LibertyAttr *attr)
} }
} }
void
LibertyReader::visitCellUserFunctionClass(LibertyAttr *attr)
{
if (cell_) {
const char *user_function_class = getAttrString(attr);
if (user_function_class)
cell_->setUserFunctionClass(user_function_class);
}
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void

View File

@ -206,6 +206,7 @@ public:
virtual void visitScalingFactors(LibertyAttr *attr); virtual void visitScalingFactors(LibertyAttr *attr);
virtual void visitCellLeakagePower(LibertyAttr *attr); virtual void visitCellLeakagePower(LibertyAttr *attr);
virtual void visitCellFootprint(LibertyAttr *attr); virtual void visitCellFootprint(LibertyAttr *attr);
virtual void visitCellUserFunctionClass(LibertyAttr *attr);
virtual void beginPin(LibertyGroup *group); virtual void beginPin(LibertyGroup *group);
virtual void endPin(LibertyGroup *group); virtual void endPin(LibertyGroup *group);

View File

@ -289,6 +289,13 @@ LibertyWriter::writeCell(const LibertyCell *cell)
fprintf(stream_, " is_macro_cell : true;\n"); fprintf(stream_, " is_macro_cell : true;\n");
if (cell->interfaceTiming()) if (cell->interfaceTiming())
fprintf(stream_, " interface_timing : true;\n"); fprintf(stream_, " interface_timing : true;\n");
const char *footprint = cell->footprint();
if (footprint)
fprintf(stream_, " cell_footprint : \"%s\";\n", footprint);
const char *user_function_class = cell->userFunctionClass();
if (user_function_class)
fprintf(stream_, " user_function_class : \"%s\";\n",
user_function_class);
LibertyCellPortIterator port_iter(cell); LibertyCellPortIterator port_iter(cell);
while (port_iter.hasNext()) { while (port_iter.hasNext()) {

View File

@ -175,15 +175,15 @@ SaifReader::setNetDurations(const char *net_name,
if (in_scope_level_ > 0) { if (in_scope_level_ > 0) {
Instance *parent = path_.empty() ? network_->topInstance() : path_.back(); Instance *parent = path_.empty() ? network_->topInstance() : path_.back();
if (parent) { if (parent) {
const char *net_name1 = unescaped(net_name); string unescaped_name = unescaped(net_name);
const Pin *pin = sdc_network_->findPin(parent, net_name1); const Pin *pin = sdc_network_->findPin(parent, unescaped_name.c_str());
if (pin) { if (pin) {
double t1 = durations[static_cast<int>(SaifState::T1)]; double t1 = durations[static_cast<int>(SaifState::T1)];
float duty = t1 / duration_; float duty = t1 / duration_;
double tc = durations[static_cast<int>(SaifState::TC)]; double tc = durations[static_cast<int>(SaifState::TC)];
float activity = tc / (duration_ * timescale_ / clk_period_); float activity = tc / (duration_ * timescale_ / clk_period_);
debugPrint(debug_, "read_saif", 2, debugPrint(debug_, "read_saif", 2,
"%s duty %.0f / %" PRId64 " = %.2f tc %.0f activity %.2f", "%s duty %.0f / %" PRIu64 " = %.2f tc %.0f activity %.2f",
sdc_network_->pathName(pin), sdc_network_->pathName(pin),
t1, t1,
duration_, duration_,
@ -195,28 +195,22 @@ SaifReader::setNetDurations(const char *net_name,
} }
} }
} }
stringDelete(net_name);
} }
const char * string
SaifReader::unescaped(const char *token) SaifReader::unescaped(const char *token)
{ {
char *unescaped = new char[strlen(token) + 1]; string unescaped;
char *u = unescaped; for (const char *t = token; *t; t++) {
size_t token_length = strlen(token); char ch = *t;
if (ch == escape_)
for (size_t i = 0; i < token_length; i++) { unescaped += *(t+1);
char ch = token[i];
if (ch == escape_) {
char next_ch = token[i + 1];
*u++ = next_ch;
i++;
}
else else
// Just the normal noises. // Just the normal noises.
*u++ = ch; unescaped += ch;
} }
*u = '\0'; debugPrint(debug_, "saif_name", 1, "token %s -> %s", token, unescaped.c_str());
debugPrint(debug_, "saif_name", 1, "token %s -> %s", token, unescaped);
return unescaped; return unescaped;
} }

View File

@ -21,6 +21,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <set> #include <set>
#include <array>
#include "Zlib.hh" #include "Zlib.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -84,7 +85,7 @@ public:
void notSupported(const char *feature); void notSupported(const char *feature);
private: private:
const char *unescaped(const char *token); string unescaped(const char *token);
const char *filename_; const char *filename_;
const char *scope_; // Divider delimited scope to begin annotation. const char *scope_; // Divider delimited scope to begin annotation.

View File

@ -1812,6 +1812,9 @@ PathEndPathDelay::findSrcClkArrival(const StaState *sta)
Search *search = sta->search(); Search *search = sta->search();
src_clk_arrival_ = search->pathClkPathArrival(&path_); src_clk_arrival_ = search->pathClkPathArrival(&path_);
} }
else
src_clk_arrival_ = 0.0;
} }
void void
@ -1941,11 +1944,10 @@ Required
PathEndPathDelay::requiredTime(const StaState *sta) const PathEndPathDelay::requiredTime(const StaState *sta) const
{ {
float delay = path_delay_->delay(); float delay = path_delay_->delay();
if (ignoreClkLatency(sta)) { if (path_delay_->ignoreClkLatency()) {
if (minMax(sta) == MinMax::max()) float src_offset = path_.isClock(sta) ? path_.clkEdge(sta)->time() : src_clk_arrival_;
return src_clk_arrival_ + delay - margin(sta); return src_offset + delay
else + ((minMax(sta) == MinMax::max()) ? -margin(sta) : margin(sta));
return src_clk_arrival_ + delay + margin(sta);
} }
else { else {
Arrival tgt_clk_arrival = targetClkArrival(sta); Arrival tgt_clk_arrival = targetClkArrival(sta);

View File

@ -237,6 +237,7 @@ public:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -315,6 +316,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
const RiseFall *, const RiseFall *,
Tag *, Tag *,
PathVertex *from_path, PathVertex *from_path,
const Arrival &,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay, ArcDelay,

View File

@ -328,6 +328,7 @@ public:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -380,6 +381,7 @@ PrevPathVisitor::visitFromToPath(const Pin *,
const RiseFall *, const RiseFall *,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &,
Edge *, Edge *,
TimingArc *arc, TimingArc *arc,
ArcDelay, ArcDelay,

View File

@ -122,7 +122,7 @@ ReportPath::ReportPath(StaState *sta) :
{ {
setDigits(2); setDigits(2);
makeFields(); makeFields();
setReportFields(false, false, false, false, false); setReportFields(false, false, false, false, false, false);
} }
ReportPath::~ReportPath() ReportPath::~ReportPath()
@ -133,6 +133,7 @@ ReportPath::~ReportPath()
delete field_capacitance_; delete field_capacitance_;
delete field_slew_; delete field_slew_;
delete field_fanout_; delete field_fanout_;
delete field_src_attr_;
delete field_edge_; delete field_edge_;
delete field_case_; delete field_case_;
@ -156,6 +157,8 @@ ReportPath::makeFields()
field_case_ = makeField("case", "case", 11, false, nullptr, false); field_case_ = makeField("case", "case", 11, false, nullptr, false);
field_description_ = makeField("description", "Description", 36, field_description_ = makeField("description", "Description", 36,
true, nullptr, true); true, nullptr, true);
field_src_attr_ = makeField("src_attr", "Src Attr", 40,
true, nullptr, true);
} }
ReportField * ReportField *
@ -225,15 +228,16 @@ ReportPath::setReportFields(bool report_input_pin,
bool report_net, bool report_net,
bool report_cap, bool report_cap,
bool report_slew, bool report_slew,
bool report_fanout) bool report_fanout,
bool report_src_attr)
{ {
report_input_pin_ = report_input_pin; report_input_pin_ = report_input_pin;
report_net_ = report_net; report_net_ = report_net;
field_fanout_->setEnabled(report_net_);
field_capacitance_->setEnabled(report_cap); field_capacitance_->setEnabled(report_cap);
field_slew_->setEnabled(report_slew); field_slew_->setEnabled(report_slew);
field_fanout_->setEnabled(report_fanout); field_fanout_->setEnabled(report_fanout);
field_src_attr_->setEnabled(report_src_attr);
// for debug // for debug
field_case_->setEnabled(false); field_case_->setEnabled(false);
} }
@ -713,7 +717,7 @@ ReportPath::reportFull(const PathEndPathDelay *end)
const Path *tgt_clk_path = end->targetClkPath(); const Path *tgt_clk_path = end->targetClkPath();
if (reportClkPath() if (reportClkPath()
&& isPropagated(tgt_clk_path, tgt_clk)) && isPropagated(tgt_clk_path, tgt_clk))
reportTgtClk(end, delay); reportTgtClk(end, delay, 0.0, true);
else { else {
Arrival tgt_clk_delay = end->targetClkDelay(this); Arrival tgt_clk_delay = end->targetClkDelay(this);
Arrival tgt_clk_arrival = delay + tgt_clk_delay; Arrival tgt_clk_arrival = delay + tgt_clk_delay;
@ -2130,6 +2134,15 @@ ReportPath::reportTgtClk(const PathEnd *end,
bool is_prop) bool is_prop)
{ {
float src_offset = end->sourceClkOffset(this); float src_offset = end->sourceClkOffset(this);
reportTgtClk(end, prev_time, src_offset, is_prop);
}
void
ReportPath::reportTgtClk(const PathEnd *end,
float prev_time,
float src_offset,
bool is_prop)
{
const ClockEdge *clk_edge = end->targetClkEdge(this); const ClockEdge *clk_edge = end->targetClkEdge(this);
Clock *clk = clk_edge->clock(); Clock *clk = clk_edge->clock();
const RiseFall *clk_rf = clk_edge->transition(); const RiseFall *clk_rf = clk_edge->transition();
@ -2395,11 +2408,16 @@ ReportPath::reportPathLine(const Path *path,
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
Slew slew = graph_->slew(vertex, rf, ap_index); Slew slew = graph_->slew(vertex, rf, ap_index);
float cap = field_blank_; float cap = field_blank_;
Instance *inst = network_->instance(pin);
string src_attr = "";
if (inst)
src_attr = network_->getAttribute(inst, "src");
// Don't show capacitance field for input pins. // Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled()) if (is_driver && field_capacitance_->enabled())
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap); cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
reportLine(what.c_str(), cap, slew, field_blank_, reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, early_late, rf, line_case); incr, time, false, early_late, rf, src_attr,
line_case);
} }
void void
@ -2655,6 +2673,10 @@ ReportPath::reportPath5(const Path *path,
const char *line_case = nullptr; const char *line_case = nullptr;
bool is_clk_start = path1->vertex(this) == clk_start; bool is_clk_start = path1->vertex(this) == clk_start;
bool is_clk = path1->isClock(search_); bool is_clk = path1->isClock(search_);
Instance *inst = network_->instance(pin);
string src_attr = "";
if (inst)
src_attr = network_->getAttribute(inst, "src");
// Always show the search start point (register clk pin). // Always show the search start point (register clk pin).
// Skip reporting the clk tree unless it is requested. // Skip reporting the clk tree unless it is requested.
if (is_clk_start if (is_clk_start
@ -2750,7 +2772,8 @@ ReportPath::reportPath5(const Path *path,
auto what = descriptionField(vertex); auto what = descriptionField(vertex);
if (report_net_ && is_driver) { if (report_net_ && is_driver) {
reportLine(what.c_str(), cap, slew, fanout, reportLine(what.c_str(), cap, slew, fanout,
incr, time, false, min_max, rf, line_case); incr, time, false, min_max, rf,
src_attr, line_case);
string what2; string what2;
if (network_->isTopLevelPort(pin)) { if (network_->isTopLevelPort(pin)) {
const char *pin_name = cmd_network_->pathName(pin); const char *pin_name = cmd_network_->pathName(pin);
@ -2768,11 +2791,12 @@ ReportPath::reportPath5(const Path *path,
} }
reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_, reportLine(what2.c_str(), field_blank_, field_blank_, field_blank_,
field_blank_, field_blank_, false, min_max, field_blank_, field_blank_, false, min_max,
nullptr, line_case); nullptr, src_attr, line_case);
} }
else else
reportLine(what.c_str(), cap, slew, fanout, reportLine(what.c_str(), cap, slew, fanout,
incr, time, false, min_max, rf, line_case); incr, time, false, min_max, rf, src_attr,
line_case);
prev_time = time; prev_time = time;
} }
} }
@ -2956,7 +2980,8 @@ ReportPath::reportLine(const char *what,
const EarlyLate *early_late) const EarlyLate *early_late)
{ {
reportLine(what, field_blank_, field_blank_, field_blank_, reportLine(what, field_blank_, field_blank_, field_blank_,
field_blank_, total, false, early_late, nullptr, nullptr); field_blank_, total, false, early_late, nullptr,
"", nullptr);
} }
// Report negative total. // Report negative total.
@ -2966,7 +2991,8 @@ ReportPath::reportLineNegative(const char *what,
const EarlyLate *early_late) const EarlyLate *early_late)
{ {
reportLine(what, field_blank_, field_blank_, field_blank_, reportLine(what, field_blank_, field_blank_, field_blank_,
field_blank_, total, true, early_late, nullptr, nullptr); field_blank_, total, true, early_late, nullptr,
"", nullptr);
} }
// Report total, and transition suffix. // Report total, and transition suffix.
@ -2977,7 +3003,8 @@ ReportPath::reportLine(const char *what,
const RiseFall *rf) const RiseFall *rf)
{ {
reportLine(what, field_blank_, field_blank_, field_blank_, reportLine(what, field_blank_, field_blank_, field_blank_,
field_blank_, total, false, early_late, rf, nullptr); field_blank_, total, false, early_late, rf, "",
nullptr);
} }
// Report increment, and total. // Report increment, and total.
@ -2988,7 +3015,8 @@ ReportPath::reportLine(const char *what,
const EarlyLate *early_late) const EarlyLate *early_late)
{ {
reportLine(what, field_blank_, field_blank_, field_blank_, reportLine(what, field_blank_, field_blank_, field_blank_,
incr, total, false, early_late, nullptr, nullptr); incr, total, false, early_late, nullptr, "",
nullptr);
} }
// Report increment, total, and transition suffix. // Report increment, total, and transition suffix.
@ -3000,7 +3028,8 @@ ReportPath::reportLine(const char *what,
const RiseFall *rf) const RiseFall *rf)
{ {
reportLine(what, field_blank_, field_blank_, field_blank_, reportLine(what, field_blank_, field_blank_, field_blank_,
incr, total, false, early_late, rf, nullptr); incr, total, false, early_late, rf, "",
nullptr);
} }
// Report slew, increment, and total. // Report slew, increment, and total.
@ -3012,7 +3041,8 @@ ReportPath::reportLine(const char *what,
const EarlyLate *early_late) const EarlyLate *early_late)
{ {
reportLine(what, field_blank_, slew, field_blank_, reportLine(what, field_blank_, slew, field_blank_,
incr, total, false, early_late, nullptr, nullptr); incr, total, false, early_late, nullptr,
"", nullptr);
} }
void void
@ -3025,6 +3055,7 @@ ReportPath::reportLine(const char *what,
bool total_with_minus, bool total_with_minus,
const EarlyLate *early_late, const EarlyLate *early_late,
const RiseFall *rf, const RiseFall *rf,
string src_attr,
const char *line_case) const char *line_case)
{ {
ReportFieldSeq::Iterator field_iter(fields_); ReportFieldSeq::Iterator field_iter(fields_);
@ -3064,8 +3095,13 @@ ReportPath::reportLine(const char *what,
else if (field == field_edge_) { else if (field == field_edge_) {
if (rf) if (rf)
reportField(rf->shortName(), field, line); reportField(rf->shortName(), field, line);
// Compatibility kludge; suppress trailing spaces. else
else if (field_iter.hasNext()) reportFieldBlank(field, line);
}
else if (field == field_src_attr_) {
if (src_attr != "")
reportField(src_attr.c_str(), field, line);
else
reportFieldBlank(field, line); reportFieldBlank(field, line);
} }
else if (field == field_case_ && line_case) else if (field == field_case_ && line_case)
@ -3075,7 +3111,10 @@ ReportPath::reportLine(const char *what,
} }
field_index++; field_index++;
} }
report_->reportLineString(line); // Trim trailing spaces and report the line.
string line_stdstr = line;
trimRight(line_stdstr);
report_->reportLineString(line_stdstr.c_str());
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -44,7 +44,8 @@ public:
bool report_net, bool report_net,
bool report_cap, bool report_cap,
bool report_slew, bool report_slew,
bool report_fanout); bool report_fanout,
bool report_src_attr);
int digits() const { return digits_; } int digits() const { return digits_; }
void setDigits(int digits); void setDigits(int digits);
void setNoSplit(bool no_split); void setNoSplit(bool no_split);
@ -148,6 +149,7 @@ public:
ReportField *fieldSlew() const { return field_slew_; } ReportField *fieldSlew() const { return field_slew_; }
ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldFanout() const { return field_fanout_; }
ReportField *fieldCapacitance() const { return field_capacitance_; } ReportField *fieldCapacitance() const { return field_capacitance_; }
ReportField *fieldSrcAttr() const { return field_src_attr_; }
protected: protected:
void makeFields(); void makeFields();
@ -213,6 +215,10 @@ protected:
void reportTgtClk(const PathEnd *end, void reportTgtClk(const PathEnd *end,
float prev_time, float prev_time,
bool is_prop); bool is_prop);
void reportTgtClk(const PathEnd *end,
float prev_time,
float src_offset,
bool is_prop);
bool pathFromGenPropClk(const Path *clk_path, bool pathFromGenPropClk(const Path *clk_path,
const EarlyLate *early_late); const EarlyLate *early_late);
bool isGenPropClk(const Clock *clk, bool isGenPropClk(const Clock *clk,
@ -345,6 +351,7 @@ protected:
bool total_with_minus, bool total_with_minus,
const EarlyLate *early_late, const EarlyLate *early_late,
const RiseFall *rf, const RiseFall *rf,
string src_attr,
const char *line_case); const char *line_case);
void reportLineTotal(const char *what, void reportLineTotal(const char *what,
Delay incr, Delay incr,
@ -461,6 +468,7 @@ protected:
ReportField *field_capacitance_; ReportField *field_capacitance_;
ReportField *field_slew_; ReportField *field_slew_;
ReportField *field_fanout_; ReportField *field_fanout_;
ReportField *field_src_attr_;
ReportField *field_edge_; ReportField *field_edge_;
ReportField *field_case_; ReportField *field_case_;

View File

@ -403,7 +403,7 @@ Search::deletePaths()
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
vertex->deletePaths(); deletePaths(vertex);
} }
filtered_arrivals_->clear(); filtered_arrivals_->clear();
graph_->clearArrivals(); graph_->clearArrivals();
@ -412,13 +412,24 @@ Search::deletePaths()
} }
} }
// Delete with incremental tns/wns update.
void void
Search::deletePaths(Vertex *vertex) Search::deletePathsIncr(Vertex *vertex)
{ {
tnsNotifyBefore(vertex); tnsNotifyBefore(vertex);
if (worst_slacks_) if (worst_slacks_)
worst_slacks_->worstSlackNotifyBefore(vertex); worst_slacks_->worstSlackNotifyBefore(vertex);
vertex->deletePaths(); deletePaths(vertex);
}
void
Search::deletePaths(Vertex *vertex)
{
TagGroup *tag_group = tagGroup(vertex);
if (tag_group) {
int arrival_count = tag_group->arrivalCount();
graph_->deletePaths(vertex, arrival_count);
}
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -510,7 +521,7 @@ Search::deleteFilteredArrivals()
for (Vertex *vertex : *filtered_arrivals_) { for (Vertex *vertex : *filtered_arrivals_) {
if (isClock(vertex)) if (isClock(vertex))
clk_arrivals_valid_ = false; clk_arrivals_valid_ = false;
deletePaths(vertex); deletePathsIncr(vertex);
arrivalInvalid(vertex); arrivalInvalid(vertex);
requiredInvalid(vertex); requiredInvalid(vertex);
} }
@ -677,7 +688,7 @@ void
Search::deleteVertexBefore(Vertex *vertex) Search::deleteVertexBefore(Vertex *vertex)
{ {
if (arrivals_exist_) { if (arrivals_exist_) {
deletePaths(vertex); deletePathsIncr(vertex);
arrival_iter_->deleteVertexBefore(vertex); arrival_iter_->deleteVertexBefore(vertex);
invalid_arrivals_->erase(vertex); invalid_arrivals_->erase(vertex);
filtered_arrivals_->erase(vertex); filtered_arrivals_->erase(vertex);
@ -759,7 +770,7 @@ void
Search::arrivalInvalidDelete(Vertex *vertex) Search::arrivalInvalidDelete(Vertex *vertex)
{ {
arrivalInvalid(vertex); arrivalInvalid(vertex);
vertex->deletePaths(); deletePaths(vertex);
} }
void void
@ -1239,6 +1250,7 @@ ArrivalVisitor::visitFromToPath(const Pin *,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *, Edge *,
TimingArc *, TimingArc *,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -1268,7 +1280,7 @@ ArrivalVisitor::visitFromToPath(const Pin *,
if (tag_match == nullptr if (tag_match == nullptr
|| delayGreater(to_arrival, arrival, min_max, this)) { || delayGreater(to_arrival, arrival, min_max, this)) {
debugPrint(debug_, "search", 3, " %s + %s = %s %s %s", debugPrint(debug_, "search", 3, " %s + %s = %s %s %s",
delayAsString(from_path->arrival(this), this), delayAsString(from_arrival, this),
delayAsString(arc_delay, this), delayAsString(arc_delay, this),
delayAsString(to_arrival, this), delayAsString(to_arrival, this),
min_max == MinMax::max() ? ">" : "<", min_max == MinMax::max() ? ">" : "<",
@ -1456,7 +1468,7 @@ Search::seedArrival(Vertex *vertex)
setVertexArrivals(vertex, &tag_bldr); setVertexArrivals(vertex, &tag_bldr);
} }
else { else {
deletePaths(vertex); deletePathsIncr(vertex);
if (search_adj_->searchFrom(vertex)) if (search_adj_->searchFrom(vertex))
arrival_iter_->enqueueAdjacentVertices(vertex, search_adj_); arrival_iter_->enqueueAdjacentVertices(vertex, search_adj_);
} }
@ -2199,7 +2211,8 @@ PathVisitor::visitFromPath(const Pin *from_pin,
} }
} }
if (to_tag) if (to_tag)
return visitFromToPath(from_pin, from_vertex, from_rf, from_tag, from_path, return visitFromToPath(from_pin, from_vertex, from_rf,
from_tag, from_path, from_arrival,
edge, arc, arc_delay, edge, arc, arc_delay,
to_vertex, to_rf, to_tag, to_arrival, to_vertex, to_rf, to_tag, to_arrival,
min_max, path_ap); min_max, path_ap);
@ -2661,7 +2674,7 @@ Search::setVertexArrivals(Vertex *vertex,
TagGroupBldr *tag_bldr) TagGroupBldr *tag_bldr)
{ {
if (tag_bldr->empty()) if (tag_bldr->empty())
deletePaths(vertex); deletePathsIncr(vertex);
else { else {
TagGroup *prev_tag_group = tagGroup(vertex); TagGroup *prev_tag_group = tagGroup(vertex);
Arrival *prev_arrivals = graph_->arrivals(vertex); Arrival *prev_arrivals = graph_->arrivals(vertex);
@ -2680,7 +2693,7 @@ Search::setVertexArrivals(Vertex *vertex,
else { else {
// Prev paths not required. // Prev paths not required.
prev_paths = nullptr; prev_paths = nullptr;
vertex->setPrevPaths(prev_path_null); graph_->deletePrevPaths(vertex, arrival_count);
} }
tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths); tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths);
vertex->setTagGroupIndex(tag_group->index()); vertex->setTagGroupIndex(tag_group->index());
@ -3477,6 +3490,7 @@ RequiredVisitor::visitFromToPath(const Pin *,
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &,
Edge *edge, Edge *edge,
TimingArc *, TimingArc *,
ArcDelay arc_delay, ArcDelay arc_delay,

View File

@ -504,13 +504,15 @@ set_report_path_fields(bool report_input_pin,
bool report_net, bool report_net,
bool report_cap, bool report_cap,
bool report_slew, bool report_slew,
bool report_fanout) bool report_fanout,
bool report_src_attr)
{ {
Sta::sta()->setReportPathFields(report_input_pin, Sta::sta()->setReportPathFields(report_input_pin,
report_net, report_net,
report_cap, report_cap,
report_slew, report_slew,
report_fanout); report_fanout,
report_src_attr);
} }
void void

View File

@ -401,8 +401,8 @@ define_cmd_args "report_checks" \
[-slack_min slack_min]\ [-slack_min slack_min]\
[-sort_by_slack]\ [-sort_by_slack]\
[-path_group group_name]\ [-path_group group_name]\
[-format full|full_clock|full_clock_expanded|short|end|summary]\ [-format full|full_clock|full_clock_expanded|short|end|slack_only|summary|json]\
[-fields capacitance|slew|input_pin|net]\ [-fields capacitance|slew|input_pin|net|src_attr]\
[-digits digits]\ [-digits digits]\
[-no_line_splits]\ [-no_line_splits]\
[> filename] [>> filename]} [> filename] [>> filename]}
@ -903,15 +903,17 @@ proc parse_report_path_options { cmd args_var default_format
set report_net [expr [lsearch $fields "net*"] != -1] set report_net [expr [lsearch $fields "net*"] != -1]
set report_slew [expr [lsearch $fields "slew*"] != -1] set report_slew [expr [lsearch $fields "slew*"] != -1]
set report_fanout [expr [lsearch $fields "fanout*"] != -1] set report_fanout [expr [lsearch $fields "fanout*"] != -1]
set report_src_attr [expr [lsearch $fields "src_attr*"] != -1]
} else { } else {
set report_input_pin 0 set report_input_pin 0
set report_cap 0 set report_cap 0
set report_net 0 set report_net 0
set report_slew 0 set report_slew 0
set report_fanout 0 set report_fanout 0
set report_src_attr 0
} }
set_report_path_fields $report_input_pin $report_net \ set_report_path_fields $report_input_pin $report_net \
$report_cap $report_slew $report_fanout $report_cap $report_slew $report_fanout $report_src_attr
set_report_path_no_split [info exists path_options(-no_line_splits)] set_report_path_no_split [info exists path_options(-no_line_splits)]
} }

View File

@ -2488,10 +2488,11 @@ Sta::setReportPathFields(bool report_input_pin,
bool report_net, bool report_net,
bool report_cap, bool report_cap,
bool report_slew, bool report_slew,
bool report_fanout) bool report_fanout,
bool report_src_attr)
{ {
report_path_->setReportFields(report_input_pin, report_net, report_cap, report_path_->setReportFields(report_input_pin, report_net, report_cap,
report_slew, report_fanout); report_slew, report_fanout, report_src_attr);
} }
ReportField * ReportField *

View File

@ -80,6 +80,7 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &from_arrival,
Edge *edge, Edge *edge,
TimingArc *arc, TimingArc *arc,
ArcDelay arc_delay, ArcDelay arc_delay,
@ -254,6 +255,7 @@ PathGroupPathVisitor::visitFromToPath(const Pin *,
const RiseFall *, const RiseFall *,
Tag *from_tag, Tag *from_tag,
PathVertex *from_path, PathVertex *from_path,
const Arrival &,
Edge *, Edge *,
TimingArc *, TimingArc *,
ArcDelay , ArcDelay ,

View File

@ -285,6 +285,7 @@ proc run_test_plain { test cmd_file log_file } {
cleanse_logfile $test $log_file cleanse_logfile $test $log_file
return "ERROR $error" return "ERROR $error"
} }
file delete $run_file
cleanse_logfile $test $log_file cleanse_logfile $test $log_file
return "" return ""
} }

View File

@ -129,6 +129,7 @@ record_sta_tests {
get_filter get_filter
get_noargs get_noargs
get_objrefs get_objrefs
report_checks_src_attr
} }
define_test_group fast [group_tests all] define_test_group fast [group_tests all]

View File

@ -0,0 +1,28 @@
Startpoint: in (input port clocked by clk)
Endpoint: _1415_ (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Cap Slew Delay Time Description Src Attr
---------------------------------------------------------------------------------------------------------------
0.00 0.00 0.00 clock clk (rise edge)
0.00 0.00 clock network delay (ideal)
0.00 0.00 v input external delay
0.00 0.00 0.00 0.00 v in (in)
in (net)
0.00 0.00 0.00 v _1415_/D (sky130_fd_sc_hd__dfrtp_1) synthesis/tests/counter.v:22.3-28.6
0.00 data arrival time
0.00 10.00 10.00 clock clk (rise edge)
0.00 10.00 clock network delay (ideal)
0.00 10.00 clock reconvergence pessimism
10.00 ^ _1415_/CLK (sky130_fd_sc_hd__dfrtp_1)
-0.10 9.90 library setup time
9.90 data required time
---------------------------------------------------------------------------------------------------------------
9.90 data required time
-0.00 data arrival time
---------------------------------------------------------------------------------------------------------------
9.90 slack (MET)

View File

@ -0,0 +1,7 @@
# report_checks all fields enabled
read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog verilog_attribute.v
link_design counter
create_clock -name clk -period 10 clk
set_input_delay -clock clk 0 [all_inputs -no_clocks]
report_checks -path_group clk -fields {capacitance slew input_pin net src_attr}

View File

@ -1,5 +1,5 @@
# Tests whether Verilog attributes can be parsed and retrieved correctly # Tests whether Verilog attributes can be parsed and retrieved correctly
read_liberty ../examples/sky130hd_tt.lib read_liberty ../examples/sky130hd_tt.lib.gz
read_verilog verilog_attribute.v read_verilog verilog_attribute.v
link_design counter link_design counter
create_clock -name clk [get_ports clk] -period 50 create_clock -name clk [get_ports clk] -period 50

View File

@ -11,6 +11,7 @@ module counter(clk, reset, in, out);
(* src = "synthesis/tests/counter.v:18.14-18.19" *) (* src = "synthesis/tests/counter.v:18.14-18.19" *)
input reset; input reset;
input in; input in;
(* bottom_bound = 1'sh0 *)
(* src = "synthesis/tests/counter.v:22.3-28.6", attr1 = "test_attr1", attr2 = "test_attr2" *) (* src = "synthesis/tests/counter.v:22.3-28.6", attr1 = "test_attr1", attr2 = "test_attr2" *)
sky130_fd_sc_hd__dfrtp_1 _1415_ ( sky130_fd_sc_hd__dfrtp_1 _1415_ (
.CLK(clk), .CLK(clk),

View File

@ -76,22 +76,22 @@ ID_TOKEN {ID_ESCAPED_TOKEN}|{ID_ALPHA_TOKEN}
} }
} }
{SIGN}?{UNSIGNED_NUMBER}?"'"[bB][01_xz]+ { {SIGN}?{UNSIGNED_NUMBER}?"'"[sS]?[bB][01_xz]+ {
VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text);
return CONSTANT; return CONSTANT;
} }
{SIGN}?{UNSIGNED_NUMBER}?"'"[oO][0-7_xz]+ { {SIGN}?{UNSIGNED_NUMBER}?"'"[sS]?[oO][0-7_xz]+ {
VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text);
return CONSTANT; return CONSTANT;
} }
{SIGN}?{UNSIGNED_NUMBER}?"'"[dD][0-9_]+ { {SIGN}?{UNSIGNED_NUMBER}?"'"[sS]?[dD][0-9_]+ {
VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text);
return CONSTANT; return CONSTANT;
} }
{SIGN}?{UNSIGNED_NUMBER}?"'"[hH][0-9a-fA-F_xz]+ { {SIGN}?{UNSIGNED_NUMBER}?"'"[sS]?[hH][0-9a-fA-F_xz]+ {
VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text);
return CONSTANT; return CONSTANT;
} }

View File

@ -41,31 +41,35 @@ public:
CellSeq *remove_cells, CellSeq *remove_cells,
FILE *stream, FILE *stream,
Network *network); Network *network);
void writeModule(Instance *inst); void writeModules();
protected: protected:
void writePorts(Cell *cell); void writeModule(const Instance *inst);
void writePortDcls(Cell *cell); InstanceSeq findHierChildren();
void writeWireDcls(Instance *inst); void findHierChildren(const Instance *inst,
InstanceSeq &children,
CellSet &cells);
void writePorts(const Cell *cell);
void writePortDcls(const Cell *cell);
void writeWireDcls(const Instance *inst);
const char *verilogPortDir(PortDirection *dir); const char *verilogPortDir(PortDirection *dir);
void writeChildren(Instance *inst); void writeChildren(const Instance *inst);
void writeChild(Instance *child); void writeChild(const Instance *child);
void writeInstPin(Instance *inst, void writeInstPin(const Instance *inst,
Port *port, const Port *port,
bool &first_port); bool &first_port);
void writeInstBusPin(Instance *inst, void writeInstBusPin(const Instance *inst,
Port *port, const Port *port,
bool &first_port); bool &first_port);
void writeInstBusPinBit(Instance *inst, void writeInstBusPinBit(const Instance *inst,
Port *port, const Port *port,
bool &first_member); bool &first_member);
void writeAssigns(Instance *inst); void writeAssigns(const Instance *inst);
int findUnconnectedNetCount(); int findUnconnectedNetCount(const Instance *inst);
int findNCcount(Instance *inst); int findChildNCcount(const Instance *child);
int findChildNCcount(Instance *child); int findPortNCcount(const Instance *inst,
int findPortNCcount(Instance *inst, const Port *port);
Port *port);
const char *filename_; const char *filename_;
bool sort_; bool sort_;
@ -73,9 +77,6 @@ protected:
CellSet remove_cells_; CellSet remove_cells_;
FILE *stream_; FILE *stream_;
Network *network_; Network *network_;
CellSet written_cells_;
Vector<Instance*> pending_children_;
int unconnected_net_index_; int unconnected_net_index_;
}; };
@ -91,7 +92,7 @@ writeVerilog(const char *filename,
if (stream) { if (stream) {
VerilogWriter writer(filename, sort, include_pwr_gnd, VerilogWriter writer(filename, sort, include_pwr_gnd,
remove_cells, stream, network); remove_cells, stream, network);
writer.writeModule(network->topInstance()); writer.writeModules();
fclose(stream); fclose(stream);
} }
else else
@ -111,7 +112,6 @@ VerilogWriter::VerilogWriter(const char *filename,
remove_cells_(network), remove_cells_(network),
stream_(stream), stream_(stream),
network_(network), network_(network),
written_cells_(network),
unconnected_net_index_(1) unconnected_net_index_(1)
{ {
if (remove_cells) { if (remove_cells) {
@ -121,7 +121,54 @@ VerilogWriter::VerilogWriter(const char *filename,
} }
void void
VerilogWriter::writeModule(Instance *inst) VerilogWriter::writeModules()
{
// Write the top level modeule first.
writeModule(network_->topInstance());
InstanceSeq hier_childrenn = findHierChildren();
for (const Instance *child : hier_childrenn)
writeModule(child);
}
InstanceSeq
VerilogWriter::findHierChildren()
{
InstanceSeq children;
CellSet cells(network_);
findHierChildren(network_->topInstance(), children, cells);
if (sort_)
sort(children, [this](const Instance *inst1,
const Instance *inst2) {
const char *cell_name1 = network_->cellName(inst1);
const char *cell_name2 = network_->cellName(inst2);
return stringLess(cell_name1, cell_name2);
});
return children;
}
void
VerilogWriter::findHierChildren(const Instance *inst,
InstanceSeq &children,
CellSet &cells)
{
InstanceChildIterator *child_iter = network_->childIterator(inst);
while (child_iter->hasNext()) {
const Instance *child = child_iter->next();
const Cell *cell = network_->cell(child);
if (network_->isHierarchical(child)
&& !cells.hasKey(cell)) {
children.push_back(child);
cells.insert(cell);
findHierChildren(child, children, cells);
}
}
delete child_iter;
}
void
VerilogWriter::writeModule(const Instance *inst)
{ {
Cell *cell = network_->cell(inst); Cell *cell = network_->cell(inst);
fprintf(stream_, "module %s (", fprintf(stream_, "module %s (",
@ -134,22 +181,10 @@ VerilogWriter::writeModule(Instance *inst)
writeChildren(inst); writeChildren(inst);
writeAssigns(inst); writeAssigns(inst);
fprintf(stream_, "endmodule\n"); fprintf(stream_, "endmodule\n");
written_cells_.insert(cell);
if (sort_)
sort(pending_children_, [this](const Instance *inst1,
const Instance *inst2) {
return stringLess(network_->cellName(inst1), network_->cellName(inst2));
});
for (auto child : pending_children_) {
Cell *child_cell = network_->cell(child);
if (!written_cells_.hasKey(child_cell))
writeModule(child);
}
} }
void void
VerilogWriter::writePorts(Cell *cell) VerilogWriter::writePorts(const Cell *cell)
{ {
bool first = true; bool first = true;
CellPortIterator *port_iter = network_->portIterator(cell); CellPortIterator *port_iter = network_->portIterator(cell);
@ -170,7 +205,7 @@ VerilogWriter::writePorts(Cell *cell)
} }
void void
VerilogWriter::writePortDcls(Cell *cell) VerilogWriter::writePortDcls(const Cell *cell)
{ {
CellPortIterator *port_iter = network_->portIterator(cell); CellPortIterator *port_iter = network_->portIterator(cell);
while (port_iter->hasNext()) { while (port_iter->hasNext()) {
@ -228,7 +263,7 @@ VerilogWriter::verilogPortDir(PortDirection *dir)
typedef std::pair<int, int> BusIndexRange; typedef std::pair<int, int> BusIndexRange;
void void
VerilogWriter::writeWireDcls(Instance *inst) VerilogWriter::writeWireDcls(const Instance *inst)
{ {
Cell *cell = network_->cell(inst); Cell *cell = network_->cell(inst);
char escape = network_->pathEscape(); char escape = network_->pathEscape();
@ -268,22 +303,19 @@ VerilogWriter::writeWireDcls(Instance *inst)
} }
// Wire net dcls for writeInstBusPinBit. // Wire net dcls for writeInstBusPinBit.
int nc_count = findUnconnectedNetCount(); int nc_count = findUnconnectedNetCount(inst);
for (int i = 1; i < nc_count + 1; i++) for (int i = 1; i < nc_count + 1; i++)
fprintf(stream_, " wire _NC%d;\n", i); fprintf(stream_, " wire _NC%d;\n", i);
} }
void void
VerilogWriter::writeChildren(Instance *inst) VerilogWriter::writeChildren(const Instance *inst)
{ {
Vector<Instance*> children; Vector<Instance*> children;
InstanceChildIterator *child_iter = network_->childIterator(inst); InstanceChildIterator *child_iter = network_->childIterator(inst);
while (child_iter->hasNext()) { while (child_iter->hasNext()) {
Instance *child = child_iter->next(); Instance *child = child_iter->next();
children.push_back(child); children.push_back(child);
if (network_->isHierarchical(child)) {
pending_children_.push_back(child);
}
} }
delete child_iter; delete child_iter;
@ -298,7 +330,7 @@ VerilogWriter::writeChildren(Instance *inst)
} }
void void
VerilogWriter::writeChild(Instance *child) VerilogWriter::writeChild(const Instance *child)
{ {
Cell *child_cell = network_->cell(child); Cell *child_cell = network_->cell(child);
if (!remove_cells_.hasKey(child_cell)) { if (!remove_cells_.hasKey(child_cell)) {
@ -325,8 +357,8 @@ VerilogWriter::writeChild(Instance *child)
} }
void void
VerilogWriter::writeInstPin(Instance *inst, VerilogWriter::writeInstPin(const Instance *inst,
Port *port, const Port *port,
bool &first_port) bool &first_port)
{ {
Pin *pin = network_->findPin(inst, port); Pin *pin = network_->findPin(inst, port);
@ -348,8 +380,8 @@ VerilogWriter::writeInstPin(Instance *inst,
} }
void void
VerilogWriter::writeInstBusPin(Instance *inst, VerilogWriter::writeInstBusPin(const Instance *inst,
Port *port, const Port *port,
bool &first_port) bool &first_port)
{ {
if (!first_port) if (!first_port)
@ -382,8 +414,8 @@ VerilogWriter::writeInstBusPin(Instance *inst,
} }
void void
VerilogWriter::writeInstBusPinBit(Instance *inst, VerilogWriter::writeInstBusPinBit(const Instance *inst,
Port *port, const Port *port,
bool &first_member) bool &first_member)
{ {
Pin *pin = network_->findPin(inst, port); Pin *pin = network_->findPin(inst, port);
@ -405,12 +437,13 @@ VerilogWriter::writeInstBusPinBit(Instance *inst,
// Use an assign statement to alias the net when it is connected to // Use an assign statement to alias the net when it is connected to
// multiple output ports. // multiple output ports.
void void
VerilogWriter::writeAssigns(Instance *inst) VerilogWriter::writeAssigns(const Instance *inst)
{ {
InstancePinIterator *pin_iter = network_->pinIterator(inst); InstancePinIterator *pin_iter = network_->pinIterator(inst);
while (pin_iter->hasNext()) { while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next(); Pin *pin = pin_iter->next();
Term *term = network_->term(pin); Term *term = network_->term(pin);
if (term) {
Net *net = network_->net(term); Net *net = network_->net(term);
Port *port = network_->port(pin); Port *port = network_->port(pin);
if (port if (port
@ -429,21 +462,14 @@ VerilogWriter::writeAssigns(Instance *inst)
net_vname.c_str()); net_vname.c_str());
} }
} }
}
delete pin_iter; delete pin_iter;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Walk the hierarch counting unconnected nets used to connect to
// bus ports with concatenation.
int int
VerilogWriter::findUnconnectedNetCount() VerilogWriter::findUnconnectedNetCount(const Instance *inst)
{
return findNCcount(network_->topInstance());
}
int
VerilogWriter::findNCcount(Instance *inst)
{ {
int nc_count = 0; int nc_count = 0;
InstanceChildIterator *child_iter = network_->childIterator(inst); InstanceChildIterator *child_iter = network_->childIterator(inst);
@ -456,7 +482,7 @@ VerilogWriter::findNCcount(Instance *inst)
} }
int int
VerilogWriter::findChildNCcount(Instance *child) VerilogWriter::findChildNCcount(const Instance *child)
{ {
int nc_count = 0; int nc_count = 0;
Cell *child_cell = network_->cell(child); Cell *child_cell = network_->cell(child);
@ -473,8 +499,8 @@ VerilogWriter::findChildNCcount(Instance *child)
} }
int int
VerilogWriter::findPortNCcount(Instance *inst, VerilogWriter::findPortNCcount(const Instance *inst,
Port *port) const Port *port)
{ {
int nc_count = 0; int nc_count = 0;
LibertyPort *lib_port = network_->libertyPort(port); LibertyPort *lib_port = network_->libertyPort(port);