or20190411 write_path_spice with no voltage_map, pg_pins
This commit is contained in:
parent
2d519b4740
commit
4fc8801e76
|
|
@ -2473,9 +2473,9 @@ LibertyReader::visitClockGatingIntegratedCell(LibertyAttr *attr)
|
||||||
if (cell_) {
|
if (cell_) {
|
||||||
const char *clock_gate_type = getAttrString(attr);
|
const char *clock_gate_type = getAttrString(attr);
|
||||||
if (clock_gate_type) {
|
if (clock_gate_type) {
|
||||||
if (stringBeginEq(clock_gate_type, "latch_posedge"))
|
if (stringBeginEqual(clock_gate_type, "latch_posedge"))
|
||||||
cell_->setClockGateType(ClockGateType::latch_posedge);
|
cell_->setClockGateType(ClockGateType::latch_posedge);
|
||||||
else if (stringBeginEq(clock_gate_type, "latch_negedge"))
|
else if (stringBeginEqual(clock_gate_type, "latch_negedge"))
|
||||||
cell_->setClockGateType(ClockGateType::latch_negedge);
|
cell_->setClockGateType(ClockGateType::latch_negedge);
|
||||||
else
|
else
|
||||||
cell_->setClockGateType(ClockGateType::other);
|
cell_->setClockGateType(ClockGateType::other);
|
||||||
|
|
|
||||||
|
|
@ -108,9 +108,6 @@ private:
|
||||||
StringSet &path_cell_names);
|
StringSet &path_cell_names);
|
||||||
void recordSpicePortNames(const char *cell_name,
|
void recordSpicePortNames(const char *cell_name,
|
||||||
StringVector &tokens);
|
StringVector &tokens);
|
||||||
float pgPortVoltage(const char *pg_port_name,
|
|
||||||
LibertyCell *cell);
|
|
||||||
float pgPortVoltage(LibertyPgPort *pg_port);
|
|
||||||
float maxTime();
|
float maxTime();
|
||||||
const char *nodeName(ParasiticNode *node);
|
const char *nodeName(ParasiticNode *node);
|
||||||
void initNodeMap(const char *net_name);
|
void initNodeMap(const char *net_name);
|
||||||
|
|
@ -159,12 +156,18 @@ private:
|
||||||
TimingArc *next_arc,
|
TimingArc *next_arc,
|
||||||
DcalcAPIndex dcalc_ap_index);
|
DcalcAPIndex dcalc_ap_index);
|
||||||
LibertyPort *onePort(FuncExpr *expr);
|
LibertyPort *onePort(FuncExpr *expr);
|
||||||
|
void writeVoltageSource(const char *inst_name,
|
||||||
|
const char *port_name,
|
||||||
|
float voltage,
|
||||||
|
int &volt_index);
|
||||||
void writeVoltageSource(LibertyCell *cell,
|
void writeVoltageSource(LibertyCell *cell,
|
||||||
const char *inst_name,
|
const char *inst_name,
|
||||||
const char *subckt_port_name,
|
const char *subckt_port_name,
|
||||||
const char *pg_port_name,
|
const char *pg_port_name,
|
||||||
|
float voltage,
|
||||||
int &volt_index);
|
int &volt_index);
|
||||||
float slewAxisMinValue(TimingArc *arc);
|
float slewAxisMinValue(TimingArc *arc);
|
||||||
|
float pgPortVoltage(LibertyPgPort *pg_port);
|
||||||
|
|
||||||
// Stage "accessors".
|
// Stage "accessors".
|
||||||
//
|
//
|
||||||
|
|
@ -296,11 +299,16 @@ WritePathSpice::WritePathSpice(Path *path,
|
||||||
{
|
{
|
||||||
bool exists;
|
bool exists;
|
||||||
default_library_->supplyVoltage(power_name_, power_voltage_, exists);
|
default_library_->supplyVoltage(power_name_, power_voltage_, exists);
|
||||||
if (!exists)
|
if (!exists) {
|
||||||
report_->error("supply %s voltage not found,\n", power_name_);
|
auto dcalc_ap = path_->dcalcAnalysisPt(this);
|
||||||
|
auto op_cond = dcalc_ap->operatingConditions();
|
||||||
|
if (op_cond == nullptr)
|
||||||
|
op_cond = network_->defaultLibertyLibrary()->defaultOperatingConditions();
|
||||||
|
power_voltage_ = op_cond->voltage();
|
||||||
|
}
|
||||||
default_library_->supplyVoltage(gnd_name_, gnd_voltage_, exists);
|
default_library_->supplyVoltage(gnd_name_, gnd_voltage_, exists);
|
||||||
if (!exists)
|
if (!exists)
|
||||||
report_->error("supply %s voltage not found,\n", gnd_name_);
|
gnd_voltage_ = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WritePathSpice::~WritePathSpice()
|
WritePathSpice::~WritePathSpice()
|
||||||
|
|
@ -403,26 +411,31 @@ WritePathSpice::writeStageInstances()
|
||||||
streamPrint(spice_stream_, "\n");
|
streamPrint(spice_stream_, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
|
||||||
WritePathSpice::pgPortVoltage(const char *pg_port_name,
|
|
||||||
LibertyCell *cell)
|
|
||||||
{
|
|
||||||
auto pg_port = cell->findPgPort(pg_port_name);
|
|
||||||
return pgPortVoltage(pg_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
WritePathSpice::pgPortVoltage(LibertyPgPort *pg_port)
|
WritePathSpice::pgPortVoltage(LibertyPgPort *pg_port)
|
||||||
{
|
{
|
||||||
auto cell = pg_port->cell();
|
LibertyLibrary *liberty = pg_port->cell()->libertyLibrary();
|
||||||
auto voltage_name = pg_port->voltageName();
|
float voltage = 0.0;
|
||||||
auto lib = cell->libertyLibrary();
|
|
||||||
float voltage;
|
|
||||||
bool exists;
|
bool exists;
|
||||||
lib->supplyVoltage(voltage_name, voltage, exists);
|
auto voltage_name = pg_port->voltageName();
|
||||||
if (!exists)
|
if (voltage_name) {
|
||||||
report_->error("pg_port %s voltage %s not found,\n",
|
liberty->supplyVoltage(voltage_name, voltage, exists);
|
||||||
pg_port->name(), voltage_name);
|
if (!exists) {
|
||||||
|
if (stringEqual(voltage_name, power_name_))
|
||||||
|
voltage = power_voltage_;
|
||||||
|
else if (stringEqual(voltage_name, gnd_name_))
|
||||||
|
voltage = gnd_voltage_;
|
||||||
|
else
|
||||||
|
report_->error("pg_pin %s/%s voltage %s not found,\n",
|
||||||
|
pg_port->cell()->name(),
|
||||||
|
pg_port->name(),
|
||||||
|
voltage_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
report_->error("Liberty pg_port %s/%s missing voltage_name attribute,\n",
|
||||||
|
pg_port->cell()->name(),
|
||||||
|
pg_port->name());
|
||||||
return voltage;
|
return voltage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -818,6 +831,9 @@ WritePathSpice::writeSubcktInst(const Pin *input_pin)
|
||||||
}
|
}
|
||||||
else if (pg_port)
|
else if (pg_port)
|
||||||
streamPrint(spice_stream_, " %s/%s", inst_name, subckt_port_cname);
|
streamPrint(spice_stream_, " %s/%s", inst_name, subckt_port_cname);
|
||||||
|
else if (stringEq(subckt_port_cname, power_name_)
|
||||||
|
|| stringEq(subckt_port_cname, gnd_name_))
|
||||||
|
streamPrint(spice_stream_, " %s/%s", inst_name, subckt_port_cname);
|
||||||
}
|
}
|
||||||
streamPrint(spice_stream_, " %s\n", cell_name);
|
streamPrint(spice_stream_, " %s\n", cell_name);
|
||||||
}
|
}
|
||||||
|
|
@ -851,14 +867,16 @@ WritePathSpice::writeSubcktInstVoltSrcs(Stage stage,
|
||||||
debugPrint2(debug_, "write_spice", 2, " port %s%s\n",
|
debugPrint2(debug_, "write_spice", 2, " port %s%s\n",
|
||||||
subckt_port_name,
|
subckt_port_name,
|
||||||
pg_port ? " pwr/gnd" : "");
|
pg_port ? " pwr/gnd" : "");
|
||||||
if (pg_port) {
|
if (pg_port)
|
||||||
auto voltage = pgPortVoltage(pg_port);
|
writeVoltageSource(inst_name, subckt_port_name,
|
||||||
streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
|
pgPortVoltage(pg_port), volt_index);
|
||||||
volt_index,
|
else if (stringEq(subckt_port_name, power_name_))
|
||||||
inst_name, subckt_port_name,
|
writeVoltageSource(inst_name, subckt_port_name,
|
||||||
voltage);
|
power_voltage_, volt_index);
|
||||||
volt_index++;
|
else if (stringEq(subckt_port_name, gnd_name_))
|
||||||
} else if (!(stringEq(subckt_port_name, input_port_name)
|
writeVoltageSource(inst_name, subckt_port_name,
|
||||||
|
gnd_voltage_, volt_index);
|
||||||
|
else if (!(stringEq(subckt_port_name, input_port_name)
|
||||||
|| stringEq(subckt_port_name, drvr_port_name))) {
|
|| stringEq(subckt_port_name, drvr_port_name))) {
|
||||||
// Input voltage to sensitize path from gate input to output.
|
// Input voltage to sensitize path from gate input to output.
|
||||||
auto port = cell->findLibertyPort(subckt_port_name);
|
auto port = cell->findLibertyPort(subckt_port_name);
|
||||||
|
|
@ -879,11 +897,13 @@ WritePathSpice::writeSubcktInstVoltSrcs(Stage stage,
|
||||||
case LogicValue::unknown:
|
case LogicValue::unknown:
|
||||||
writeVoltageSource(cell, inst_name, subckt_port_name,
|
writeVoltageSource(cell, inst_name, subckt_port_name,
|
||||||
port->relatedGroundPin(),
|
port->relatedGroundPin(),
|
||||||
|
gnd_voltage_,
|
||||||
volt_index);
|
volt_index);
|
||||||
break;
|
break;
|
||||||
case LogicValue::one:
|
case LogicValue::one:
|
||||||
writeVoltageSource(cell, inst_name, subckt_port_name,
|
writeVoltageSource(cell, inst_name, subckt_port_name,
|
||||||
port->relatedPowerPin(),
|
port->relatedPowerPin(),
|
||||||
|
power_voltage_,
|
||||||
volt_index);
|
volt_index);
|
||||||
break;
|
break;
|
||||||
case LogicValue::rise:
|
case LogicValue::rise:
|
||||||
|
|
@ -914,39 +934,38 @@ WritePathSpice::writeClkedStepSource(const Pin *pin,
|
||||||
writeStepVoltSource(pin, tr, slew, time, volt_index);
|
writeStepVoltSource(pin, tr, slew, time, volt_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WritePathSpice::writeVoltageSource(const char *inst_name,
|
||||||
|
const char *port_name,
|
||||||
|
float voltage,
|
||||||
|
int &volt_index)
|
||||||
|
{
|
||||||
|
streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
|
||||||
|
volt_index,
|
||||||
|
inst_name, port_name,
|
||||||
|
voltage);
|
||||||
|
volt_index++;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WritePathSpice::writeVoltageSource(LibertyCell *cell,
|
WritePathSpice::writeVoltageSource(LibertyCell *cell,
|
||||||
const char *inst_name,
|
const char *inst_name,
|
||||||
const char *subckt_port_name,
|
const char *subckt_port_name,
|
||||||
const char *pg_port_name,
|
const char *pg_port_name,
|
||||||
|
float voltage,
|
||||||
int &volt_index)
|
int &volt_index)
|
||||||
{
|
{
|
||||||
auto pg_port = cell->findPgPort(pg_port_name);
|
if (pg_port_name) {
|
||||||
if (pg_port) {
|
auto pg_port = cell->findPgPort(pg_port_name);
|
||||||
auto voltage_name = pg_port->voltageName();
|
if (pg_port)
|
||||||
if (voltage_name) {
|
voltage = pgPortVoltage(pg_port);
|
||||||
float voltage;
|
|
||||||
bool exists;
|
|
||||||
cell->libertyLibrary()->supplyVoltage(voltage_name, voltage, exists);
|
|
||||||
if (!exists)
|
|
||||||
report_->error("pg_port %s voltage %s not found,\n",
|
|
||||||
pg_port_name, voltage_name);
|
|
||||||
streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
|
|
||||||
volt_index,
|
|
||||||
inst_name, subckt_port_name,
|
|
||||||
voltage);
|
|
||||||
volt_index++;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
report_->error("port %s %s voltage %s not found,\n",
|
report_->error("%s pg_port %s not found,\n",
|
||||||
subckt_port_name,
|
cell->name(),
|
||||||
pg_port_name,
|
pg_port_name);
|
||||||
voltage_name);
|
|
||||||
}
|
}
|
||||||
else
|
writeVoltageSource(inst_name, subckt_port_name, voltage, volt_index);
|
||||||
report_->error("port %s %s not found,\n",
|
|
||||||
subckt_port_name,
|
|
||||||
pg_port_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1345,7 +1364,7 @@ WritePathSpice::writeSubckts()
|
||||||
bool found_ends = false;
|
bool found_ends = false;
|
||||||
while (getline(lib_subckts_stream, line)) {
|
while (getline(lib_subckts_stream, line)) {
|
||||||
subckts_stream << line << "\n";
|
subckts_stream << line << "\n";
|
||||||
if (stringEqual(line.c_str(), ".ends")) {
|
if (stringBeginEqual(line.c_str(), ".ends")) {
|
||||||
subckts_stream << "\n";
|
subckts_stream << "\n";
|
||||||
found_ends = true;
|
found_ends = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1416,8 +1435,11 @@ WritePathSpice::recordSpicePortNames(const char *cell_name,
|
||||||
auto port_name = tokens[i].c_str();
|
auto port_name = tokens[i].c_str();
|
||||||
auto port = cell->findLibertyPort(port_name);
|
auto port = cell->findLibertyPort(port_name);
|
||||||
auto pg_port = cell->findPgPort(port_name);
|
auto pg_port = cell->findPgPort(port_name);
|
||||||
if (port == nullptr && pg_port == nullptr)
|
if (port == nullptr
|
||||||
report_->error("subckt %s port %s has no corresponding liberty port or pg_port.\n",
|
&& pg_port == nullptr
|
||||||
|
&& !stringEqual(port_name, power_name_)
|
||||||
|
&& !stringEqual(port_name, gnd_name_))
|
||||||
|
report_->error("subckt %s port %s has no corresponding liberty port, pg_port and is not power or ground.\n",
|
||||||
cell_name, port_name);
|
cell_name, port_name);
|
||||||
spice_port_names->push_back(port_name);
|
spice_port_names->push_back(port_name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1942,18 +1942,12 @@ proc write_path_spice { args } {
|
||||||
|
|
||||||
if { [info exists keys(-power)] } {
|
if { [info exists keys(-power)] } {
|
||||||
set power $keys(-power)
|
set power $keys(-power)
|
||||||
if { ![liberty_supply_exists $power] } {
|
|
||||||
sta_error "liberty $power not found.\n"
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sta_error "No -power specified.\n"
|
sta_error "No -power specified.\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if { [info exists keys(-ground)] } {
|
if { [info exists keys(-ground)] } {
|
||||||
set ground $keys(-ground)
|
set ground $keys(-ground)
|
||||||
if { ![liberty_supply_exists $ground] } {
|
|
||||||
sta_error "liberty $ground not found.\n"
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sta_error "No -ground specified.\n"
|
sta_error "No -ground specified.\n"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,12 +49,12 @@ stringEqIf(const char *str1,
|
||||||
|| (str1 && str2 && strcmp(str1, str2) == 0);
|
|| (str1 && str2 && strcmp(str1, str2) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare the beginning of str1 to str2.
|
// Case insensitive compare the beginning of str1 to str2.
|
||||||
inline bool
|
inline bool
|
||||||
stringBeginEq(const char *str1,
|
stringBeginEqual(const char *str1,
|
||||||
const char *str2)
|
const char *str2)
|
||||||
{
|
{
|
||||||
return strncasecmp(str1, str2, strlen(str2)) == 9;
|
return strncasecmp(str1, str2, strlen(str2)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case insensitive compare.
|
// Case insensitive compare.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue