Merge branch 'master' into master

This commit is contained in:
James Cherry 2019-01-20 09:56:23 -08:00 committed by GitHub
commit 3c779e4cf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 228 additions and 168 deletions

2
README
View File

@ -32,7 +32,7 @@ See INSTALL for installation and build instructions. Alternatively, run using Do
* Liberty * Liberty
* SDC * SDC
* SDF * SDF
* RSPF/DSPF/SPEF * SPEF
## Exception path support ## Exception path support
* False path * False path

View File

@ -1127,20 +1127,14 @@ ConcreteNetwork::makeConcreteInstance(ConcreteCell *cell,
} }
void void
ConcreteNetwork::makeInternalPins(Instance *inst) ConcreteNetwork::makePins(Instance *inst)
{ {
LibertyCell *lib_cell = libertyCell(inst); CellPortBitIterator *port_iterator = portBitIterator(cell(inst));
if (lib_cell && lib_cell->hasInternalPorts()) { while (port_iterator->hasNext()) {
CellPortBitIterator *port_iterator = portBitIterator(cell(inst)); Port *port = port_iterator->next();
while (port_iterator->hasNext()) { makePin(inst, port, NULL);
Port *port = port_iterator->next();
LibertyPort *lib_port = libertyPort(port);
if (lib_port->direction()->isInternal()
&& lib_cell->hasTimingArcs(lib_port))
makePin(inst, port, NULL);
}
delete port_iterator;
} }
delete port_iterator;
} }
void void

View File

@ -185,7 +185,7 @@ public:
virtual Instance *makeInstance(LibertyCell *cell, virtual Instance *makeInstance(LibertyCell *cell,
const char *name, const char *name,
Instance *parent); Instance *parent);
void makeInternalPins(Instance *inst); void makePins(Instance *inst);
// For linking. // For linking.
virtual Instance *makeInstance(Cell *cell, virtual Instance *makeInstance(Cell *cell,
const char *name, const char *name,

View File

@ -482,8 +482,7 @@ public:
virtual Instance *makeInstance(LibertyCell *cell, virtual Instance *makeInstance(LibertyCell *cell,
const char *name, const char *name,
Instance *parent) = 0; Instance *parent) = 0;
// Make liberty internal pins. virtual void makePins(Instance *inst) = 0;
virtual void makeInternalPins(Instance *inst) = 0;
virtual void swapCell(Instance *inst, virtual void swapCell(Instance *inst,
LibertyCell *cell) = 0; LibertyCell *cell) = 0;
// Deleting instance also deletes instance pins. // Deleting instance also deletes instance pins.

View File

@ -903,9 +903,9 @@ NetworkNameAdapter::makeInstance(LibertyCell *cell,
} }
void void
NetworkNameAdapter::makeInternalPins(Instance *inst) NetworkNameAdapter::makePins(Instance *inst)
{ {
network_edit_->makeInternalPins(inst); network_edit_->makePins(inst);
} }
void void

View File

@ -122,7 +122,7 @@ public:
virtual Instance *makeInstance(LibertyCell *cell, virtual Instance *makeInstance(LibertyCell *cell,
const char *name, const char *name,
Instance *parent); Instance *parent);
virtual void makeInternalPins(Instance *inst); virtual void makePins(Instance *inst);
virtual void swapCell(Instance *inst, virtual void swapCell(Instance *inst,
LibertyCell *cell); LibertyCell *cell);
virtual Net *makeNet(const char *name, virtual Net *makeNet(const char *name,

View File

@ -3565,7 +3565,7 @@ Sta::makeInstance(const char *name,
{ {
NetworkEdit *network = networkCmdEdit(); NetworkEdit *network = networkCmdEdit();
Instance *inst = network->makeInstance(cell, name, parent); Instance *inst = network->makeInstance(cell, name, parent);
network->makeInternalPins(inst); network->makePins(inst);
makeInstanceAfter(inst); makeInstanceAfter(inst);
return inst; return inst;
} }
@ -3645,20 +3645,17 @@ Sta::disconnectPin(Pin *pin)
// //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Network::makeInternalPins with connectPinAfter. // Network::makePins with connectPinAfter.
void void
Sta::makeInstanceAfter(Instance *inst) Sta::makeInstanceAfter(Instance *inst)
{ {
LibertyCell *lib_cell = network_->libertyCell(inst); LibertyCell *lib_cell = network_->libertyCell(inst);
if (lib_cell && lib_cell->hasInternalPorts()) { if (lib_cell) {
LibertyCellPortBitIterator port_iter(lib_cell); LibertyCellPortBitIterator port_iter(lib_cell);
while (port_iter.hasNext()) { while (port_iter.hasNext()) {
LibertyPort *lib_port = port_iter.next(); LibertyPort *lib_port = port_iter.next();
if (lib_port->direction()->isInternal() Pin *pin = network_->findPin(inst, lib_port);
&& lib_cell->hasTimingArcs(lib_port)) { connectPinAfter(pin);
Pin *pin = network_->findPin(inst, lib_port);
connectPinAfter(pin);
}
} }
} }
} }

View File

@ -37,6 +37,7 @@
#include "PathRef.hh" #include "PathRef.hh"
#include "PathExpanded.hh" #include "PathExpanded.hh"
#include "StaState.hh" #include "StaState.hh"
#include "Sim.hh"
#include "WritePathSpice.hh" #include "WritePathSpice.hh"
namespace sta { namespace sta {
@ -49,6 +50,7 @@ typedef Vector<string> StringVector;
typedef Map<string, StringVector*> CellSpicePortNames; typedef Map<string, StringVector*> CellSpicePortNames;
typedef int Stage; typedef int Stage;
typedef Map<ParasiticNode*, int> ParasiticNodeMap; typedef Map<ParasiticNode*, int> ParasiticNodeMap;
typedef Map<LibertyPort*, LogicValue> LibertyPortLogicValues;
void void
split(const string &text, split(const string &text,
@ -88,6 +90,7 @@ private:
void writeGateStage(Stage stage); void writeGateStage(Stage stage);
void writeStageVoltageSources(LibertyCell *cell, void writeStageVoltageSources(LibertyCell *cell,
StringVector *spice_port_names, StringVector *spice_port_names,
const Instance *inst,
const char *inst_name, const char *inst_name,
LibertyPort *from_port, LibertyPort *from_port,
LibertyPort *drvr_port); LibertyPort *drvr_port);
@ -105,14 +108,29 @@ private:
void initNodeMap(const char *net_name); void initNodeMap(const char *net_name);
const char *spiceTrans(const TransRiseFall *tr); const char *spiceTrans(const TransRiseFall *tr);
void writeMeasureDelayStmt(Stage stage, void writeMeasureDelayStmt(Stage stage,
Path *input_path); Path *from_path,
Path *to_path);
void writeMeasureSlewStmt(Stage stage, void writeMeasureSlewStmt(Stage stage,
Path *path); Path *path);
void sensitizationValues(const Instance *inst,
FuncExpr *expr,
LibertyPort *from_port,
// Return values.
LibertyPortLogicValues &port_values);
// Stage "accessors". // Stage "accessors".
//
// stage
// |---------------|
// |\ |\
// -------| >---/\/\/----| >---
// gate |/ drvr load|/
// input
//
// A path from an input port has no GateInputPath.
// Internally a stage index from stageFirst() to stageLast() // Internally a stage index from stageFirst() to stageLast()
// is turned into an index into path_expanded_. // is turned into an index into path_expanded_.
// A path from an input port has no GateInputPath. //
Stage stageFirst(); Stage stageFirst();
Stage stageLast(); Stage stageLast();
string stageName(Stage stage); string stageName(Stage stage);
@ -149,9 +167,8 @@ private:
const char *net_name_; const char *net_name_;
float power_voltage_; float power_voltage_;
float gnd_voltage_; float gnd_voltage_;
// Resistance to use to simulate a short circuit between spice nodes. // Resistance to use to simulate a short circuit between spice nodes.
static const float short_ckt_resistance_; float short_ckt_resistance_;
}; };
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -200,8 +217,6 @@ writePathSpice(Path *path,
writer.writeSpice(); writer.writeSpice();
} }
const float WritePathSpice::short_ckt_resistance_ = .0001;
WritePathSpice::WritePathSpice(Path *path, WritePathSpice::WritePathSpice(Path *path,
const char *spice_filename, const char *spice_filename,
const char *subckt_filename, const char *subckt_filename,
@ -219,7 +234,8 @@ WritePathSpice::WritePathSpice(Path *path,
power_name_(power_name), power_name_(power_name),
gnd_name_(gnd_name), gnd_name_(gnd_name),
path_expanded_(sta), path_expanded_(sta),
net_name_(NULL) net_name_(NULL),
short_ckt_resistance_(.0001)
{ {
auto lib = network_->defaultLibertyLibrary(); auto lib = network_->defaultLibertyLibrary();
power_voltage_ = lib->supplyVoltage(power_name_); power_voltage_ = lib->supplyVoltage(power_name_);
@ -369,41 +385,51 @@ WritePathSpice::writeMeasureStmts()
streamPrint(spice_stream_, "********************\n\n"); streamPrint(spice_stream_, "********************\n\n");
for (auto stage = stageFirst(); stage <= stageLast(); stage++) { for (auto stage = stageFirst(); stage <= stageLast(); stage++) {
auto input_path = (stage == stageFirst()) auto gate_input_path = stageGateInputPath(stage);
? stageDrvrPath(stage) auto drvr_path = stageDrvrPath(stage);
: stageGateInputPath(stage); auto load_path = stageLoadPath(stage);
writeMeasureDelayStmt(stage, input_path); if (gate_input_path) {
writeMeasureSlewStmt(stage, input_path); // gate input -> gate output
writeMeasureSlewStmt(stage, gate_input_path);
writeMeasureDelayStmt(stage, gate_input_path, drvr_path);
}
writeMeasureSlewStmt(stage, drvr_path);
// gate output | input port -> load
writeMeasureDelayStmt(stage, drvr_path, load_path);
if (stage == stageLast()) if (stage == stageLast())
writeMeasureSlewStmt(stage, stageLoadPath(stage)); writeMeasureSlewStmt(stage, load_path);
} }
streamPrint(spice_stream_, "\n"); streamPrint(spice_stream_, "\n");
} }
void void
WritePathSpice::writeMeasureDelayStmt(Stage stage, WritePathSpice::writeMeasureDelayStmt(Stage stage,
Path *input_path) Path *from_path,
Path *to_path)
{ {
auto lib = network_->defaultLibertyLibrary(); auto lib = network_->defaultLibertyLibrary();
auto input_pin_name = network_->pathName(input_path->pin(this)); auto from_pin_name = network_->pathName(from_path->pin(this));
auto input_tr = input_path->transition(this); auto from_tr = from_path->transition(this);
auto input_threshold = power_voltage_ * lib->inputThreshold(input_tr); auto from_threshold = power_voltage_ * lib->inputThreshold(from_tr);
auto load_path = stageLoadPath(stage); auto to_pin_name = network_->pathName(to_path->pin(this));
auto load_pin_name = stageLoadPinName(stage); auto to_tr = to_path->transition(this);
auto load_tr = load_path->transition(this); auto to_threshold = power_voltage_ * lib->inputThreshold(to_tr);
auto load_threshold = power_voltage_ * lib->inputThreshold(load_tr);
streamPrint(spice_stream_, streamPrint(spice_stream_,
".measure tran %s_%s_delay_%s trig v(%s) val=%.3f %s=last targ v(%s) val=%.3f %s=last\n", ".measure tran %s_%s_delay_%s\n",
stageName(stage).c_str(), stageName(stage).c_str(),
input_pin_name, from_pin_name,
load_pin_name, to_pin_name);
input_pin_name, streamPrint(spice_stream_,
input_threshold, "+trig v(%s) val=%.3f %s=last\n",
spiceTrans(input_tr), from_pin_name,
load_pin_name, from_threshold,
load_threshold, spiceTrans(from_tr));
spiceTrans(load_tr)); streamPrint(spice_stream_,
"+targ v(%s) val=%.3f %s=last\n",
to_pin_name,
to_threshold,
spiceTrans(to_tr));
} }
void void
@ -426,12 +452,16 @@ WritePathSpice::writeMeasureSlewStmt(Stage stage,
threshold2 = lower; threshold2 = lower;
} }
streamPrint(spice_stream_, streamPrint(spice_stream_,
".measure tran %s_%s_slew trig v(%s) val=%.3f %s=last targ v(%s) val=%.3f %s=last\n", ".measure tran %s_%s_slew\n",
stageName(stage).c_str(), stageName(stage).c_str(),
pin_name, pin_name);
streamPrint(spice_stream_,
"+trig v(%s) val=%.3f %s=last\n",
pin_name, pin_name,
threshold1, threshold1,
spice_tr, spice_tr);
streamPrint(spice_stream_,
"+targ v(%s) val=%.3f %s=last\n",
pin_name, pin_name,
threshold2, threshold2,
spice_tr); spice_tr);
@ -515,74 +545,18 @@ WritePathSpice::writeGateStage(Stage stage)
streamPrint(spice_stream_, " %s\n", cell_name); streamPrint(spice_stream_, " %s\n", cell_name);
writeStageVoltageSources(cell, spice_port_names, writeStageVoltageSources(cell, spice_port_names,
inst_name, inst, inst_name,
network_->libertyPort(input_pin), network_->libertyPort(input_pin),
network_->libertyPort(drvr_pin)); network_->libertyPort(drvr_pin));
writeStageParasitics(stage); writeStageParasitics(stage);
streamPrint(spice_stream_, ".ends\n\n"); streamPrint(spice_stream_, ".ends\n\n");
} }
typedef Map<LibertyPort*, LogicValue> LibertyPortLogicValues;
// Find the logic values for expression inputs to enable paths from_port.
void
sensitizationValues(FuncExpr *expr,
LibertyPort *from_port,
// Return values.
LibertyPortLogicValues &port_values)
{
switch (expr->op()) {
case FuncExpr::op_port: {
break;
}
case FuncExpr::op_not: {
sensitizationValues(expr->left(), from_port, port_values);
break;
}
case FuncExpr::op_or: {
auto left = expr->left();
auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
else if (right->port() == from_port
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_zero;
break;
}
case FuncExpr::op_and: {
auto left = expr->left();
auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_one;
else if (right->port() == from_port
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_one;
break;
}
case FuncExpr::op_xor: {
// Need to know timing arc sense to get this right.
auto left = expr->left();
auto right = expr->right();
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
else if (right->port() == from_port
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_zero;
break;
}
case FuncExpr::op_one:
case FuncExpr::op_zero:
break;
}
}
// Power/ground and input voltage sources. // Power/ground and input voltage sources.
void void
WritePathSpice::writeStageVoltageSources(LibertyCell *cell, WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
StringVector *spice_port_names, StringVector *spice_port_names,
const Instance *inst,
const char *inst_name, const char *inst_name,
LibertyPort *from_port, LibertyPort *from_port,
LibertyPort *drvr_port) LibertyPort *drvr_port)
@ -591,7 +565,7 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
auto drvr_port_name = drvr_port->name(); auto drvr_port_name = drvr_port->name();
auto lib = cell->libertyLibrary(); auto lib = cell->libertyLibrary();
LibertyPortLogicValues port_values; LibertyPortLogicValues port_values;
sensitizationValues(drvr_port->function(), from_port, port_values); sensitizationValues(inst, drvr_port->function(), from_port, port_values);
int volt_source = 1; int volt_source = 1;
debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name()); debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name());
StringVector::Iterator port_iter(spice_port_names); StringVector::Iterator port_iter(spice_port_names);
@ -614,49 +588,127 @@ WritePathSpice::writeStageVoltageSources(LibertyCell *cell,
auto port = cell->findLibertyPort(subckt_port_name); auto port = cell->findLibertyPort(subckt_port_name);
if (port) { if (port) {
const char *pg_port_name = NULL; const char *pg_port_name = NULL;
bool port_has_value; const Pin *pin = network_->findPin(inst, port);
LogicValue port_value; // Look for tie high/low or propagated constant values.
port_values.findKey(port, port_value, port_has_value); LogicValue port_value = sim_->logicValue(pin);
if (port_has_value) { if (port_value == logic_unknown) {
switch (port_value) { bool has_value;
case logic_zero: LogicValue value;
pg_port_name = port->relatedGroundPin(); port_values.findKey(port, value, has_value);
break; if (has_value)
case logic_one: port_value = value;
pg_port_name = port->relatedPowerPin(); }
break; if (port_value == logic_zero)
default: pg_port_name = port->relatedGroundPin();
break; else if (port_value == logic_one)
} pg_port_name = port->relatedPowerPin();
if (pg_port_name) { if (pg_port_name) {
auto pg_port = cell->findPgPort(pg_port_name); auto pg_port = cell->findPgPort(pg_port_name);
if (pg_port) { if (pg_port) {
auto voltage_name = pg_port->voltageName(); auto voltage_name = pg_port->voltageName();
if (voltage_name) { if (voltage_name) {
float voltage = lib->supplyVoltage(voltage_name); float voltage = lib->supplyVoltage(voltage_name);
streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n", streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
volt_source, volt_source,
inst_name, subckt_port_name, inst_name, subckt_port_name,
voltage); voltage);
volt_source++; volt_source++;
} }
else else
report_->error("port %s %s voltage %s not found,\n", report_->error("port %s %s voltage %s not found,\n",
subckt_port_name, subckt_port_name,
pg_port_name, pg_port_name,
voltage_name); voltage_name);
}
else
report_->error("port %s %s not found,\n",
subckt_port_name,
pg_port_name);
} }
else
report_->error("port %s %s not found,\n",
subckt_port_name,
pg_port_name);
} }
} }
} }
} }
} }
// Find the logic values for expression inputs to enable paths from_port.
void
WritePathSpice::sensitizationValues(const Instance *inst,
FuncExpr *expr,
LibertyPort *from_port,
// Return values.
LibertyPortLogicValues &port_values)
{
auto left = expr->left();
auto right = expr->right();
switch (expr->op()) {
case FuncExpr::op_port:
break;
case FuncExpr::op_not:
sensitizationValues(inst, expr->left(), from_port, port_values);
break;
case FuncExpr::op_or:
if (left->hasPort(from_port)
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
else if (left->hasPort(from_port)
&& right->op() == FuncExpr::op_not
&& right->left()->op() == FuncExpr::op_port)
// from_port + !right_port
port_values[right->left()->port()] = logic_one;
else if (right->hasPort(from_port)
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_zero;
else if (right->hasPort(from_port)
&& left->op() == FuncExpr::op_not
&& left->left()->op() == FuncExpr::op_port)
// from_port + !left_port
port_values[left->left()->port()] = logic_one;
else {
sensitizationValues(inst, expr->left(), from_port, port_values);
sensitizationValues(inst, expr->right(), from_port, port_values);
}
break;
case FuncExpr::op_and:
if (left->hasPort(from_port)
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_one;
else if (left->hasPort(from_port)
&& right->op() == FuncExpr::op_not
&& right->left()->op() == FuncExpr::op_port)
// from_port * !right_port
port_values[right->left()->port()] = logic_zero;
else if (right->hasPort(from_port)
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_one;
else if (right->hasPort(from_port)
&& left->op() == FuncExpr::op_not
&& left->left()->op() == FuncExpr::op_port)
// from_port * !left_port
port_values[left->left()->port()] = logic_zero;
else {
sensitizationValues(inst, expr->left(), from_port, port_values);
sensitizationValues(inst, expr->right(), from_port, port_values);
}
break;
case FuncExpr::op_xor:
// Need to know timing arc sense to get this right.
if (left->port() == from_port
&& right->op() == FuncExpr::op_port)
port_values[right->port()] = logic_zero;
else if (right->port() == from_port
&& left->op() == FuncExpr::op_port)
port_values[left->port()] = logic_zero;
else {
sensitizationValues(inst, expr->left(), from_port, port_values);
sensitizationValues(inst, expr->right(), from_port, port_values);
}
break;
case FuncExpr::op_one:
case FuncExpr::op_zero:
break;
}
}
class ParasiticNodeNameLess class ParasiticNodeNameLess
{ {
public: public:
@ -699,7 +751,8 @@ findParasiticDevicesNodes(ParasiticNode *node,
if (!devices.hasKey(device)) { if (!devices.hasKey(device)) {
devices.insert(device); devices.insert(device);
auto other_node = parasitics->otherNode(device, node); auto other_node = parasitics->otherNode(device, node);
findParasiticDevicesNodes(other_node, parasitics, nodes, devices); if (other_node)
findParasiticDevicesNodes(other_node, parasitics, nodes, devices);
} }
} }
delete device_iter; delete device_iter;
@ -717,7 +770,7 @@ WritePathSpice::writeStageParasitics(Stage stage)
int resistor_index = 1; int resistor_index = 1;
int cap_index = 1; int cap_index = 1;
if (parasitic) { if (parasitic) {
Net *net = network_->net(drvr_pin); auto net = network_->net(drvr_pin);
auto net_name = auto net_name =
net ? network_->pathName(net) : network_->pathName(drvr_pin); net ? network_->pathName(net) : network_->pathName(drvr_pin);
initNodeMap(net_name); initNodeMap(net_name);
@ -756,18 +809,22 @@ WritePathSpice::writeStageParasitics(Stage stage)
while (node_iter.hasNext()) { while (node_iter.hasNext()) {
auto node = node_iter.next(); auto node = node_iter.next();
auto cap = parasitics_->nodeGndCap(node, parasitic_ap); auto cap = parasitics_->nodeGndCap(node, parasitic_ap);
streamPrint(spice_stream_, "C%d %s 0 %.3e\n", if (cap > 0.0) {
cap_index, streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
nodeName(node), cap_index,
cap); nodeName(node),
cap_index++; cap);
cap_index++;
}
} }
} }
else else {
streamPrint(spice_stream_, "* No parasitics found for this net.\n");
streamPrint(spice_stream_, "R1 %s %s %.3e\n", streamPrint(spice_stream_, "R1 %s %s %.3e\n",
network_->pathName(drvr_pin), network_->pathName(drvr_pin),
network_->pathName(load_pin), network_->pathName(load_pin),
short_ckt_resistance_); short_ckt_resistance_);
}
} }
void void

View File

@ -1926,7 +1926,7 @@ define_cmd_args "write_path_spice" { -path_args path_args\
-ground ground} -ground ground}
proc write_path_spice { args } { proc write_path_spice { args } {
parse_key_args "write_spice" args \ parse_key_args "write_path_spice" args \
keys {-spice_directory -lib_subckt_file -model_file \ keys {-spice_directory -lib_subckt_file -model_file \
-power -ground -path_args} \ -power -ground -path_args} \
flags {} flags {}

View File

@ -4651,7 +4651,7 @@ liberty_supply_exists(const char *supply_name)
{ {
auto network = Sta::sta()->network(); auto network = Sta::sta()->network();
auto lib = network->defaultLibertyLibrary(); auto lib = network->defaultLibertyLibrary();
return lib->supplyExists(supply_name); return lib && lib->supplyExists(supply_name);
} }
void void

View File

@ -1805,8 +1805,18 @@ VerilogReader::makeModuleInstNetwork(VerilogModuleInst *mod_inst,
if (cell) { if (cell) {
Instance *inst = network_->makeInstance(cell, mod_inst->instanceName(), Instance *inst = network_->makeInstance(cell, mod_inst->instanceName(),
parent); parent);
network_->makeInternalPins(inst);
bool is_leaf = network_->isLeaf(cell); bool is_leaf = network_->isLeaf(cell);
if (is_leaf) {
// Make all pins.
LibertyCell *lib_cell = network_->libertyCell(cell);
if (lib_cell) {
LibertyCellPortBitIterator port_iter(lib_cell);
while (port_iter.hasNext()) {
LibertyPort *port = port_iter.next();
network_->makePin(inst, reinterpret_cast<Port*>(port), NULL);
}
}
}
VerilogBindingTbl bindings(zero_net_name_, one_net_name_); VerilogBindingTbl bindings(zero_net_name_, one_net_name_);
if (mod_inst->hasPins()) { if (mod_inst->hasPins()) {
if (mod_inst->namedPins()) if (mod_inst->namedPins())
@ -1945,8 +1955,12 @@ VerilogReader::makeInstPin(Instance *inst,
Net *net = NULL; Net *net = NULL;
if (net_name) if (net_name)
net = parent_bindings->ensureNetBinding(net_name, parent, network_); net = parent_bindings->ensureNetBinding(net_name, parent, network_);
// Guard against repeated port name. if (is_leaf) {
if (network_->findPin(inst, port) == NULL) { // Connect leaf pin to net.
if (net)
network_->connect(inst, port, net);
}
else {
Pin *pin = network_->makePin(inst, port, net); Pin *pin = network_->makePin(inst, port, net);
if (!is_leaf && net) { if (!is_leaf && net) {
const char *port_name = network_->name(port); const char *port_name = network_->name(port);
@ -1990,10 +2004,9 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
} }
network_->makePin(inst, reinterpret_cast<Port*>(port), net); network_->makePin(inst, reinterpret_cast<Port*>(port), net);
} }
// Make internal pin. else
if (port->direction()->isInternal() // Make unconnected pin.
&& lib_cell->hasTimingArcs(port)) network_->makePin(inst, reinterpret_cast<Port*>(port), NULL);
network_->makePin(inst, reinterpret_cast<Port*>(port), NULL);
} }
} }