This commit is contained in:
James Cherry 2019-05-19 17:06:06 -06:00
parent c6db5eb0ae
commit a988588dac
13 changed files with 148 additions and 74 deletions

View File

@ -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;
}
}

View File

@ -29,10 +29,10 @@ typedef sta::Vector<SwigInitFunc> 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");

View File

@ -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);

View File

@ -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
{

View File

@ -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

View File

@ -276,7 +276,7 @@ void
ConcreteNetwork::deleteTopInstance()
{
if (top_instance_) {
deleteInstance(reinterpret_cast<Instance*>(top_instance_));
deleteInstance(top_instance_);
top_instance_ = nullptr;
}
}
@ -296,7 +296,7 @@ ConcreteNetwork::deleteCellNetworkViews()
Instance *
ConcreteNetwork::topInstance() const
{
return reinterpret_cast<Instance*>(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*>(library);
}
@ -1120,7 +1121,7 @@ ConcreteNetwork::makeConcreteInstance(ConcreteCell *cell,
{
ConcreteInstance *cparent =
reinterpret_cast<ConcreteInstance*>(parent);
ConcreteInstance *inst = new ConcreteInstance(name, cell, cparent);
ConcreteInstance *inst = new ConcreteInstance(cell, name, cparent);
if (parent)
cparent->addChild(inst);
return reinterpret_cast<Instance*>(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<ConcretePin*>(pin);
if (cpin->instance() == top_instance_) {
if (reinterpret_cast<Instance*>(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<ConcreteCell*>(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<ConcreteCell*>(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<Instance*>(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<ConcreteInstance*>(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 {

View File

@ -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.

View File

@ -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,

View File

@ -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,

View File

@ -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_;

View File

@ -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());
}

View File

@ -14,8 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Network commands.
namespace eval sta {
# Defined by SWIG interface Verilog.i.

View File

@ -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;