diff --git a/app/Main.cc b/app/Main.cc index fe3a8685..12735f63 100644 --- a/app/Main.cc +++ b/app/Main.cc @@ -31,6 +31,10 @@ extern "C" { extern int Sta_Init(Tcl_Interp *interp); } +namespace sta { +extern const char *tcl_inits[]; +} + int main(int argc, char **argv) { @@ -44,7 +48,7 @@ main(int argc, char **argv) } else { Sta *sta = new Sta; - staMain(sta, argc, argv, Sta_Init); + staMain(sta, argc, argv, Sta_Init, sta::tcl_inits); return 0; } } diff --git a/app/StaMain.cc b/app/StaMain.cc index 2366fc5e..47fdcbdb 100644 --- a/app/StaMain.cc +++ b/app/StaMain.cc @@ -29,10 +29,10 @@ typedef sta::Vector SwigInitFuncSeq; // "Arguments" passed to staTclAppInit. static int sta_argc; static char **sta_argv; +static const char **sta_tcl_inits; static SwigInitFunc sta_swig_init; static const char *init_filename = "[file join $env(HOME) .sta]"; -extern const char *tcl_inits[]; static void sourceTclFileEchoVerbose(const char *filename, @@ -42,7 +42,8 @@ void staMain(Sta *sta, int argc, char **argv, - SwigInitFunc swig_init) + SwigInitFunc swig_init, + const char *tcl_inits[]) { initSta(); @@ -55,7 +56,7 @@ staMain(Sta *sta, if (threads_exists) sta->setThreadCount(thread_count); - staSetupAppInit(argc, argv, swig_init); + staSetupAppInit(argc, argv, swig_init, tcl_inits); // Set argc to 1 so Tcl_Main doesn't source any files. // Tcl_Main never returns. Tcl_Main(1, argv, staTclAppInit); @@ -86,10 +87,12 @@ parseThreadsArg(int argc, void staSetupAppInit(int argc, char **argv, - SwigInitFunc swig_init) + SwigInitFunc swig_init, + const char *tcl_inits[]) { sta_argc = argc; sta_argv = argv; + sta_tcl_inits = tcl_inits; sta_swig_init = swig_init; } @@ -110,7 +113,7 @@ staTclAppInit(Tcl_Interp *interp) sta->setTclInterp(interp); // Eval encoded sta TCL sources. - evalTclInit(interp, tcl_inits); + evalTclInit(interp, sta_tcl_inits); if (!findCmdLineFlag(argc, argv, "-no_splash")) Tcl_Eval(interp, "sta::show_splash"); diff --git a/app/StaMain.hh b/app/StaMain.hh index d553e2b4..ab265c27 100644 --- a/app/StaMain.hh +++ b/app/StaMain.hh @@ -21,6 +21,7 @@ struct Tcl_Interp; namespace sta { +class Sta; typedef int (*SwigInitFunc)(Tcl_Interp *); // The swig_init function is called to define the swig interface @@ -29,17 +30,16 @@ void staMain(Sta *sta, int argc, char **argv, - SwigInitFunc swig_init); + SwigInitFunc swig_init, + const char *tcl_inits[]); // Set arguments passed to staTclAppInit inside the tcl interpreter. void staSetupAppInit(int argc, char **argv, - SwigInitFunc swig_init); + SwigInitFunc swig_init, + const char *tcl_inits[]); -// The variable tcl_init is an implicit argument to this function that -// provides the definitions for builtin tcl commands encoded by -// etc/TclEncode.tcl. int staTclAppInit(Tcl_Interp *interp); diff --git a/liberty/FuncExpr.cc b/liberty/FuncExpr.cc index 76d7e368..d157a0ed 100644 --- a/liberty/FuncExpr.cc +++ b/liberty/FuncExpr.cc @@ -89,6 +89,14 @@ FuncExpr::deleteSubexprs() delete this; } +FuncExpr * +FuncExpr::copy() +{ + FuncExpr *left = left_ ? left_->copy() : nullptr; + FuncExpr *right = right_ ? right_->copy() : nullptr; + return new FuncExpr(op_, left, right, port_); +} + LibertyPort * FuncExpr::port() const { diff --git a/liberty/FuncExpr.hh b/liberty/FuncExpr.hh index a605910c..c22ef602 100644 --- a/liberty/FuncExpr.hh +++ b/liberty/FuncExpr.hh @@ -51,6 +51,8 @@ public: static bool less(const FuncExpr *expr1, const FuncExpr *expr2); + // Deep copy. + FuncExpr *copy(); // Delete expression and all of its subexpressions. void deleteSubexprs(); // op == op_port diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index e6c81ced..9586d2d1 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -276,7 +276,7 @@ void ConcreteNetwork::deleteTopInstance() { if (top_instance_) { - deleteInstance(reinterpret_cast(top_instance_)); + deleteInstance(top_instance_); top_instance_ = nullptr; } } @@ -296,7 +296,7 @@ ConcreteNetwork::deleteCellNetworkViews() Instance * ConcreteNetwork::topInstance() const { - return reinterpret_cast(top_instance_); + return top_instance_; } //////////////////////////////////////////////////////////////// @@ -404,9 +404,10 @@ ConcreteNetwork::libertyLibraryIterator() const //////////////////////////////////////////////////////////////// Library * -ConcreteNetwork::makeLibrary(const char *name) +ConcreteNetwork::makeLibrary(const char *name, + const char *filename) { - ConcreteLibrary *library = new ConcreteLibrary(name, nullptr); + ConcreteLibrary *library = new ConcreteLibrary(name, filename); addLibrary(library); return reinterpret_cast(library); } @@ -1120,7 +1121,7 @@ ConcreteNetwork::makeConcreteInstance(ConcreteCell *cell, { ConcreteInstance *cparent = reinterpret_cast(parent); - ConcreteInstance *inst = new ConcreteInstance(name, cell, cparent); + ConcreteInstance *inst = new ConcreteInstance(cell, name, cparent); if (parent) cparent->addChild(inst); return reinterpret_cast(inst); @@ -1257,7 +1258,7 @@ ConcreteNetwork::connect(Instance *inst, cpin = new ConcretePin(cinst, cport, cnet); cinst->addPin(cpin); } - if (cinst == top_instance_) { + if (inst == top_instance_) { // makeTerm ConcreteTerm *cterm = new ConcreteTerm(cpin, cnet); cnet->addTerm(cterm); @@ -1296,7 +1297,7 @@ void ConcreteNetwork::disconnectPin(Pin *pin) { ConcretePin *cpin = reinterpret_cast(pin); - if (cpin->instance() == top_instance_) { + if (reinterpret_cast(cpin->instance()) == top_instance_) { ConcreteTerm *cterm = cpin->term_; if (cterm) { ConcreteNet *cnet = cterm->net_; @@ -1450,19 +1451,26 @@ ConcreteNetwork::visitConnectedPins(const Net *net, //////////////////////////////////////////////////////////////// -ConcreteInstance::ConcreteInstance(const char *name, - ConcreteCell *cell, +ConcreteInstance::ConcreteInstance(ConcreteCell *cell, + const char *name, ConcreteInstance *parent) : - name_(stringCopy(name)), cell_(cell), + name_(stringCopy(name)), parent_(parent), children_(nullptr), nets_(nullptr) { - int pin_count = reinterpret_cast(cell)->portBitCount(); - pins_ = new ConcretePin*[pin_count]; - for (int i = 0; i < pin_count; i++) - pins_[i] = nullptr; + initPins(); +} + +void +ConcreteInstance::initPins() +{ + int pin_count = reinterpret_cast(cell_)->portBitCount(); + if (pin_count) + pins_ = new ConcretePin*[pin_count]{nullptr}; + else + pins_ = nullptr; } ConcreteInstance::~ConcreteInstance() @@ -1789,10 +1797,10 @@ ConcreteNetwork::readNetlistBefore() } void -ConcreteNetwork::setTopInstance(ConcreteInstance *top_inst) +ConcreteNetwork::setTopInstance(Instance *top_inst) { if (top_instance_) { - deleteInstance(reinterpret_cast(top_instance_)); + deleteInstance(top_instance_); clearConstantNets(); clearNetDrvPinrMap(); } @@ -1815,10 +1823,7 @@ ConcreteNetwork::linkNetwork(const char *top_cell_name, deleteTopInstance(); Cell *top_cell = findAnyCell(top_cell_name); if (top_cell) { - top_instance_ = - reinterpret_cast(link_func_(top_cell, - make_black_boxes, - report, this)); + top_instance_ = link_func_(top_cell, make_black_boxes, report, this); return top_instance_ != nullptr; } else { diff --git a/network/ConcreteNetwork.hh b/network/ConcreteNetwork.hh index 4eeb88fe..5b1109e3 100644 --- a/network/ConcreteNetwork.hh +++ b/network/ConcreteNetwork.hh @@ -155,7 +155,8 @@ public: LogicValue value); // Edit methods. - virtual Library *makeLibrary(const char *name); + virtual Library *makeLibrary(const char *name, + const char *filename); virtual LibertyLibrary *makeLibertyLibrary(const char *name, const char *filename); virtual Cell *makeCell(Library *library, @@ -221,7 +222,7 @@ public: virtual void readNetlistBefore(); virtual void setLinkFunc(LinkNetworkFunc *link); - void setTopInstance(ConcreteInstance *top_inst); + void setTopInstance(Instance *top_inst); using Network::netIterator; using Network::findPin; @@ -250,7 +251,7 @@ protected: // Cell lookup search order sequence. ConcreteLibrarySeq library_seq_; ConcreteLibraryMap library_map_; - ConcreteInstance *top_instance_; + Instance *top_instance_; NetSet constant_nets_[2]; // LogicValue::zero/one LinkNetworkFunc *link_func_; CellNetworkViewMap cell_network_view_map_; @@ -284,15 +285,16 @@ public: ConcreteNet *net); void deleteNet(ConcreteNet *net); void setCell(LibertyCell *cell); + void initPins(); -private: - ConcreteInstance(const char *name, - ConcreteCell *cell, +protected: + ConcreteInstance(ConcreteCell *cell, + const char *name, ConcreteInstance *parent); ~ConcreteInstance(); - const char *name_; ConcreteCell *cell_; + const char *name_; ConcreteInstance *parent_; // Array of pins indexed by pin->port->index(). ConcretePin **pins_; @@ -373,12 +375,13 @@ public: void mergeInto(ConcreteNet *net); ConcreteNet *mergedInto() { return merged_into_; } -private: +protected: DISALLOW_COPY_AND_ASSIGN(ConcreteNet); ConcreteNet(const char *name, ConcreteInstance *instance); virtual ~ConcreteNet(); +private: const char *name_; ConcreteInstance *instance_; // Pointer to head of linked list of pins. diff --git a/network/Network.hh b/network/Network.hh index a974d1c7..d064dc5f 100644 --- a/network/Network.hh +++ b/network/Network.hh @@ -520,7 +520,8 @@ public: // Called before reading a netlist to delete any previously linked network. virtual void readNetlistBefore() = 0; virtual void setLinkFunc(LinkNetworkFunc *link) = 0; - virtual Library *makeLibrary(const char *name) = 0; + virtual Library *makeLibrary(const char *name, + const char *filename) = 0; // Search the libraries in read order for a cell by name. virtual Cell *findAnyCell(const char *name) = 0; virtual Cell *makeCell(Library *library, diff --git a/search/Power.cc b/search/Power.cc index eec79f9f..44ca0cc9 100644 --- a/search/Power.cc +++ b/search/Power.cc @@ -405,6 +405,7 @@ Power::ensureActivities() // Propagate activiities across register D->Q. seedRegOutputActivities(reg, bfs); } + delete regs; visitor.init(); bfs.visit(levelize_->maxLevel(), &visitor); } @@ -546,7 +547,6 @@ Power::findInternalPower(const Pin *to_pin, debugPrint1(debug_, "power", 2, " cap = %s\n", units_->capacitanceUnit()->asString(load_cap)); debugPrint0(debug_, "power", 2, " when act/ns duty energy power\n"); - float input_duty_sum = inputDutySum(inst); float internal = 0.0; LibertyCellInternalPowerIterator pwr_iter(cell); while (pwr_iter.hasNext()) { @@ -554,26 +554,35 @@ Power::findInternalPower(const Pin *to_pin, if (pwr->port() == to_port) { const char *related_pg_pin = pwr->relatedPgPin(); const LibertyPort *from_port = pwr->relatedPort(); - if (from_port == nullptr) - // Input port internal power. - from_port = to_port; FuncExpr *when = pwr->when(); + FuncExpr *infered_when = nullptr; + if (from_port) { + if (when == nullptr) { + FuncExpr *func = to_port->function(); + if (func) + infered_when = inferedWhen(func, from_port); + } + } + else + from_port = to_port; // If all the "when" clauses exist VSS internal power is ignored. if ((when && internalPowerMissingWhen(cell, to_port, related_pg_pin)) || pgNameVoltage(cell, related_pg_pin, dcalc_ap) != 0.0) { const Pin *from_pin = network_->findPin(inst, from_port); Vertex *from_vertex = graph_->pinLoadVertex(from_pin); float duty; - if (when) + if (infered_when) { + PwrActivity from_activity = findActivity(from_pin); + PwrActivity to_activity = findActivity(to_pin); + float duty1 = evalActivity(infered_when, inst).duty(); + duty = from_activity.activity() / to_activity.activity() * duty1; + } + else if (when) duty = evalActivity(when, inst).duty(); else if (search_->isClock(from_vertex)) duty = 1.0; - else { - PwrActivity from_activity = findActivity(from_pin); - PwrActivity to_activity = findActivity(to_pin); - float duty1 = input_duty_sum - from_activity.duty(); - duty = from_activity.activity() * (1.0 - duty1) / to_activity.activity(); - } + else + duty = 0.5; float port_energy = 0.0; TransRiseFallIterator tr_iter; while (tr_iter.hasNext()) { @@ -596,7 +605,7 @@ Power::findInternalPower(const Pin *to_pin, debugPrint8(debug_, "power", 2, " %s -> %s %s %.2f %.2f %9.2e %9.2e %s\n", from_port->name(), to_port->name(), - pwr->when() ? pwr->when()->asString() : " ", + when ? when->asString() : (infered_when ? infered_when->asString() : " "), to_activity.activity() * 1e-9, duty, port_energy, @@ -604,11 +613,69 @@ Power::findInternalPower(const Pin *to_pin, related_pg_pin ? related_pg_pin : "no pg_pin"); internal += port_internal; } + if (infered_when) + infered_when->deleteSubexprs(); } } result.setInternal(result.internal() + internal); } +//////////////////////////////////////////////////////////////// + +static bool +isPortRef(FuncExpr *expr, + const LibertyPort *port) +{ + return (expr->op() == FuncExpr::op_port + && expr->port() == port) + || (expr->op() == FuncExpr::op_not + && expr->left()->op() == FuncExpr::op_port + && expr->left()->port() == port); +} + +static FuncExpr * +negate(FuncExpr *expr) +{ + if (expr->op() == FuncExpr::op_not) + return expr->left()->copy(); + else + return FuncExpr::makeNot(expr->copy()); +} + +FuncExpr * +Power::inferedWhen(FuncExpr *expr, + const LibertyPort *from_port) +{ + switch (expr->op()) { + case FuncExpr::op_port: { + if (expr->port() == from_port) + return FuncExpr::makeOne(); + else + return nullptr; + } + case FuncExpr::op_not: + return inferedWhen(expr->left(), from_port); + case FuncExpr::op_or: + case FuncExpr::op_xor: { + if (isPortRef(expr->left(), from_port)) + return negate(expr->right()); + if (isPortRef(expr->right(), from_port)) + return negate(expr->left()); + } + case FuncExpr::op_and: { + if (isPortRef(expr->left(), from_port)) + return expr->right()->copy(); + if (isPortRef(expr->right(), from_port)) + return expr->left()->copy(); + } + case FuncExpr::op_one: + case FuncExpr::op_zero: + return nullptr; + } +} + +//////////////////////////////////////////////////////////////// + // Return true if some a "when" clause for the internal power to_port // is missing. bool @@ -645,20 +712,6 @@ funcExprPortCount(FuncExpr *expr) return port_count; } -float -Power::inputDutySum(const Instance *inst) -{ - float duty_sum = 0.0; - InstancePinIterator *pin_iter = network_->pinIterator(inst); - while (pin_iter->hasNext()) { - const Pin *pin = pin_iter->next(); - if (network_->direction(pin)->isAnyInput()) - duty_sum += findClkedActivity(pin).duty(); - } - delete pin_iter; - return duty_sum; -} - void Power::findLeakagePower(const Instance *, LibertyCell *cell, diff --git a/search/Power.hh b/search/Power.hh index 8321ceb5..bbb47b9e 100644 --- a/search/Power.hh +++ b/search/Power.hh @@ -147,10 +147,11 @@ protected: BfsFwdIterator &bfs); PwrActivity evalActivity(FuncExpr *expr, const Instance *inst); - float inputDutySum(const Instance *inst); bool internalPowerMissingWhen(LibertyCell *cell, const LibertyPort *to_port, const char *related_pg_pin); + FuncExpr *inferedWhen(FuncExpr *expr, + const LibertyPort *from_port); private: PwrActivity global_activity_; diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index dabd06ad..42ad15f7 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -2652,7 +2652,6 @@ PropertyValue pin_property(const Pin *pin, const char *property) { - cmdGraph(); return getProperty(pin, property, Sta::sta()); } @@ -2660,7 +2659,6 @@ PropertyValue instance_property(const Instance *inst, const char *property) { - cmdGraph(); return getProperty(inst, property, Sta::sta()); } @@ -2668,7 +2666,6 @@ PropertyValue net_property(const Net *net, const char *property) { - cmdGraph(); return getProperty(net, property, Sta::sta()); } @@ -2676,7 +2673,6 @@ PropertyValue port_property(const Port *port, const char *property) { - cmdGraph(); return getProperty(port, property, Sta::sta()); } diff --git a/verilog/Verilog.tcl b/verilog/Verilog.tcl index 6984c050..af9da635 100644 --- a/verilog/Verilog.tcl +++ b/verilog/Verilog.tcl @@ -14,8 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Network commands. - namespace eval sta { # Defined by SWIG interface Verilog.i. diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index 3753bf97..95415898 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -204,7 +204,7 @@ VerilogReader::init(const char *filename) library_ = network_->findLibrary("verilog"); if (library_ == nullptr) - library_ = network_->makeLibrary("verilog"); + library_ = network_->makeLibrary("verilog", nullptr); report_stmt_stats_ = debugCheck(debug_, "verilog", 1); module_count_ = 0;