commit
b7a94af32f
|
|
@ -57,7 +57,7 @@ is also licensed for commerical applications by Parallax Software without
|
|||
the GPL's requirements.
|
||||
|
||||
OpenSTA is open source, meaning the sources are published and can be compiled locally.
|
||||
Derivatives works are supported as long as they adhere to the GPL license requirements.
|
||||
Derivative works are supported as long as they adhere to the GPL license requirements.
|
||||
However, OpenSTA is not supported by a public community of developers as many other
|
||||
open source projects are. The copyright and develpment are exclusive to Parallax
|
||||
Software. OpenSTA does not accept external code contributions.
|
||||
|
|
|
|||
|
|
@ -113,42 +113,40 @@ class ArnoldiDelayCalc : public RCDelayCalc
|
|||
public:
|
||||
ArnoldiDelayCalc(StaState *sta);
|
||||
virtual ~ArnoldiDelayCalc();
|
||||
virtual ArcDelayCalc *copy();
|
||||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual ReducedParasiticType reducedParasiticType() const;
|
||||
virtual void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
// Pass in load_cap or drvr_parasitic.
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew);
|
||||
virtual void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew);
|
||||
virtual void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
ArcDelayCalc *copy() override;
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) override;
|
||||
void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew) override;
|
||||
string reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
void delay_work_set_thresholds(delay_work *D,
|
||||
double lo,
|
||||
double hi,
|
||||
|
|
@ -455,7 +453,7 @@ ArnoldiDelayCalc::loadDelay(const Pin *load_pin,
|
|||
thresholdAdjust(load_pin, wire_delay, load_slew);
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
ArnoldiDelayCalc::reportGateDelay(const LibertyCell *,
|
||||
const TimingArc *,
|
||||
const Slew &,
|
||||
|
|
@ -464,9 +462,9 @@ ArnoldiDelayCalc::reportGateDelay(const LibertyCell *,
|
|||
float,
|
||||
const Pvt *,
|
||||
const DcalcAnalysisPt *,
|
||||
int,
|
||||
string *)
|
||||
int)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ set_delay_calc_incremental_tolerance(float tol)
|
|||
sta::Sta::sta()->setIncrementalDelayTolerance(tol);
|
||||
}
|
||||
|
||||
TmpString *
|
||||
string
|
||||
report_delay_calc_cmd(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
|
|
|
|||
|
|
@ -1666,7 +1666,7 @@ DmpCeffDelayCalc::ceff(const LibertyCell *drvr_cell,
|
|||
return load_cap;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -1675,8 +1675,7 @@ DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result)
|
||||
int digits)
|
||||
{
|
||||
ArcDelay gate_delay;
|
||||
Slew drvr_slew;
|
||||
|
|
@ -1685,6 +1684,7 @@ DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
gate_delay, drvr_slew);
|
||||
GateTimingModel *model = gateModel(arc, dcalc_ap);
|
||||
float c_eff = 0.0;
|
||||
string result;
|
||||
if (drvr_parasitic_ && dmp_alg_) {
|
||||
c_eff = dmp_alg_->ceff();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
|
|
@ -1693,24 +1693,24 @@ DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
const Unit *res_unit = units->resistanceUnit();
|
||||
float c2, rpi, c1;
|
||||
parasitics_->piModel(drvr_parasitic_, c2, rpi, c1);
|
||||
*result += "Pi model C2=";
|
||||
*result += cap_unit->asString(c2, digits);
|
||||
*result += " Rpi=";
|
||||
*result += res_unit->asString(rpi, digits);
|
||||
*result += " C1=";
|
||||
*result += cap_unit->asString(c1, digits);
|
||||
*result += ", Ceff=";
|
||||
*result += cap_unit->asString(c_eff, digits);
|
||||
*result += '\n';
|
||||
result += "Pi model C2=";
|
||||
result += cap_unit->asString(c2, digits);
|
||||
result += " Rpi=";
|
||||
result += res_unit->asString(rpi, digits);
|
||||
result += " C1=";
|
||||
result += cap_unit->asString(c1, digits);
|
||||
result += ", Ceff=";
|
||||
result += cap_unit->asString(c_eff, digits);
|
||||
result += '\n';
|
||||
}
|
||||
else
|
||||
c_eff = load_cap;
|
||||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
model->reportGateDelay(drvr_cell, pvt, in_slew1, c_eff,
|
||||
related_out_cap, pocv_enabled_,
|
||||
digits, result);
|
||||
result += model->reportGateDelay(drvr_cell, pvt, in_slew1, c_eff,
|
||||
related_out_cap, pocv_enabled_, digits);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static double
|
||||
|
|
|
|||
|
|
@ -58,16 +58,15 @@ public:
|
|||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
virtual string reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits);
|
||||
virtual void copyState(const StaState *sta);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -33,21 +33,21 @@ class DmpCeffElmoreDelayCalc : public DmpCeffDelayCalc
|
|||
{
|
||||
public:
|
||||
DmpCeffElmoreDelayCalc(StaState *sta);
|
||||
virtual ArcDelayCalc *copy();
|
||||
virtual void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_,
|
||||
Slew &drvr_slew);
|
||||
virtual void loadDelay(const Pin *load_pin,
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew);
|
||||
ArcDelayCalc *copy() override;
|
||||
void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_,
|
||||
Slew &drvr_slew) override;
|
||||
void loadDelay(const Pin *load_pin,
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew) override;
|
||||
};
|
||||
|
||||
ArcDelayCalc *
|
||||
|
|
|
|||
|
|
@ -36,14 +36,14 @@ GraphDelayCalc::setObserver(DelayCalcObserver *observer)
|
|||
delete observer;
|
||||
}
|
||||
|
||||
string *
|
||||
string
|
||||
GraphDelayCalc::reportDelayCalc(Edge *,
|
||||
TimingArc *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
int)
|
||||
{
|
||||
return new string;
|
||||
return "";
|
||||
}
|
||||
|
||||
float
|
||||
|
|
|
|||
|
|
@ -1629,7 +1629,7 @@ GraphDelayCalc1::ceff(Edge *edge,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string *
|
||||
string
|
||||
GraphDelayCalc1::reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
|
|
@ -1643,7 +1643,7 @@ GraphDelayCalc1::reportDelayCalc(Edge *edge,
|
|||
Instance *inst = network_->instance(to_pin);
|
||||
LibertyCell *cell = network_->libertyCell(inst);
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
string *result = new string;
|
||||
string result;
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
const Pvt *pvt = sdc_->pvt(inst, dcalc_ap->constraintMinMax());
|
||||
if (pvt == nullptr)
|
||||
|
|
@ -1668,19 +1668,19 @@ GraphDelayCalc1::reportDelayCalc(Edge *edge,
|
|||
const Slew &to_slew = graph_->slew(to_vertex, to_rf, slew_index);
|
||||
bool from_ideal_clk = clk_network_->isIdealClock(from_vertex->pin());
|
||||
const char *from_slew_annotation = from_ideal_clk ? " (ideal clock)" : nullptr;
|
||||
arc_delay_calc_->reportCheckDelay(cell, arc, from_slew, from_slew_annotation,
|
||||
to_slew, related_out_cap, pvt, dcalc_ap,
|
||||
digits, result);
|
||||
result = arc_delay_calc_->reportCheckDelay(cell, arc, from_slew,
|
||||
from_slew_annotation, to_slew,
|
||||
related_out_cap, pvt, dcalc_ap,
|
||||
digits);
|
||||
}
|
||||
else {
|
||||
Parasitic *to_parasitic =
|
||||
arc_delay_calc_->findParasitic(to_pin, to_rf, dcalc_ap);
|
||||
const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap);
|
||||
float load_cap = loadCap(to_pin, to_parasitic, to_rf, dcalc_ap);
|
||||
arc_delay_calc_->reportGateDelay(cell, arc,
|
||||
from_slew, load_cap, to_parasitic,
|
||||
related_out_cap, pvt, dcalc_ap,
|
||||
digits, result);
|
||||
result = arc_delay_calc_->reportGateDelay(cell, arc,
|
||||
from_slew, load_cap, to_parasitic,
|
||||
related_out_cap, pvt, dcalc_ap, digits);
|
||||
}
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ public:
|
|||
virtual void clear();
|
||||
virtual void findDelays(Level level);
|
||||
virtual void findDelays(Vertex *drvr_vertex);
|
||||
virtual string *reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
virtual string reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
virtual float incrementalDelayTolerance();
|
||||
virtual void setIncrementalDelayTolerance(float tol);
|
||||
virtual void setObserver(DelayCalcObserver *observer);
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ LumpedCapDelayCalc::gateDelay(const LibertyCell *drvr_cell,
|
|||
Slew drvr_slew1;
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
// NaNs cause seg faults during table lookup.
|
||||
if (isnan(load_cap) || isnan(related_out_cap) || isnan(in_slew))
|
||||
if (isnan(load_cap) || isnan(related_out_cap) || isnan(delayAsFloat(in_slew)))
|
||||
report_->error(710, "gate delay input variable is NaN");
|
||||
model->gateDelay(drvr_cell, pvt, in_slew1, load_cap, related_out_cap,
|
||||
pocv_enabled_, gate_delay1, drvr_slew1);
|
||||
|
|
@ -238,7 +238,7 @@ LumpedCapDelayCalc::thresholdLibrary(const Pin *load_pin)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
LumpedCapDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
|
|
@ -247,15 +247,15 @@ LumpedCapDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result)
|
||||
int digits)
|
||||
{
|
||||
GateTimingModel *model = gateModel(arc, dcalc_ap);
|
||||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
model->reportGateDelay(drvr_cell, pvt, in_slew1, load_cap,
|
||||
related_out_cap, false, digits, result);
|
||||
return model->reportGateDelay(drvr_cell, pvt, in_slew1, load_cap,
|
||||
related_out_cap, false, digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -280,7 +280,7 @@ LumpedCapDelayCalc::checkDelay(const LibertyCell *cell,
|
|||
margin = delay_zero;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
LumpedCapDelayCalc::reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
|
|
@ -289,16 +289,16 @@ LumpedCapDelayCalc::reportCheckDelay(const LibertyCell *cell,
|
|||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result)
|
||||
int digits)
|
||||
{
|
||||
CheckTimingModel *model = checkModel(arc, dcalc_ap);
|
||||
if (model) {
|
||||
float from_slew1 = delayAsFloat(from_slew);
|
||||
float to_slew1 = delayAsFloat(to_slew);
|
||||
model->reportCheckDelay(cell, pvt, from_slew1, from_slew_annotation, to_slew1,
|
||||
related_out_cap, false, digits, result);
|
||||
return model->reportCheckDelay(cell, pvt, from_slew1, from_slew_annotation, to_slew1,
|
||||
related_out_cap, false, digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -26,70 +26,68 @@ class LumpedCapDelayCalc : public ArcDelayCalc
|
|||
{
|
||||
public:
|
||||
LumpedCapDelayCalc(StaState *sta);
|
||||
virtual ArcDelayCalc *copy();
|
||||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual ReducedParasiticType reducedParasiticType() const;
|
||||
virtual void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew);
|
||||
virtual void setMultiDrvrSlewFactor(float factor);
|
||||
virtual void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew);
|
||||
virtual void checkDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &margin);
|
||||
virtual float ceff(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
virtual void finishDrvrPin();
|
||||
ArcDelayCalc *copy() override;
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) override;
|
||||
void setMultiDrvrSlewFactor(float) override;
|
||||
float ceff(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew) override;
|
||||
void checkDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &margin) override;
|
||||
string reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
string reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
|
||||
protected:
|
||||
// Find the liberty library to use for logic/slew thresholds.
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ class RCDelayCalc : public LumpedCapDelayCalc
|
|||
{
|
||||
public:
|
||||
RCDelayCalc(StaState *sta);
|
||||
virtual ArcDelayCalc *copy();
|
||||
virtual void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
ArcDelayCalc *copy() override;
|
||||
void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
|
||||
protected:
|
||||
// Helper function for input ports driving dspf parasitic.
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ UnitDelayCalc::ceff(const LibertyCell *,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
UnitDelayCalc::reportGateDelay(const LibertyCell *,
|
||||
const TimingArc *,
|
||||
const Slew &,
|
||||
|
|
@ -106,11 +106,11 @@ UnitDelayCalc::reportGateDelay(const LibertyCell *,
|
|||
float,
|
||||
const Pvt *,
|
||||
const DcalcAnalysisPt *,
|
||||
int,
|
||||
string *result)
|
||||
int)
|
||||
{
|
||||
*result += "Delay = 1.0\n";
|
||||
*result += "Slew = 0.0\n";
|
||||
string result("Delay = 1.0\n");
|
||||
result += "Slew = 0.0\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -127,7 +127,7 @@ UnitDelayCalc::checkDelay(const LibertyCell *,
|
|||
margin = units_->timeUnit()->scale();
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
UnitDelayCalc::reportCheckDelay(const LibertyCell *,
|
||||
const TimingArc *,
|
||||
const Slew &,
|
||||
|
|
@ -136,10 +136,9 @@ UnitDelayCalc::reportCheckDelay(const LibertyCell *,
|
|||
float,
|
||||
const Pvt *,
|
||||
const DcalcAnalysisPt *,
|
||||
int,
|
||||
string *result)
|
||||
int)
|
||||
{
|
||||
*result += "Check = 1.0\n";
|
||||
return "Check = 1.0\n";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -25,70 +25,68 @@ class UnitDelayCalc : public ArcDelayCalc
|
|||
{
|
||||
public:
|
||||
UnitDelayCalc(StaState *sta);
|
||||
virtual ArcDelayCalc *copy();
|
||||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual ReducedParasiticType reducedParasiticType() const;
|
||||
virtual void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew);
|
||||
virtual void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew);
|
||||
virtual void setMultiDrvrSlewFactor(float) {}
|
||||
virtual float ceff(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
virtual void checkDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &margin);
|
||||
virtual void reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result);
|
||||
virtual void finishDrvrPin();
|
||||
ArcDelayCalc *copy() override;
|
||||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
void inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
const Parasitic *parasitic,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void gateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) override;
|
||||
void loadDelay(const Pin *load_pin,
|
||||
// Return values.
|
||||
ArcDelay &wire_delay,
|
||||
Slew &load_slew) override;
|
||||
void setMultiDrvrSlewFactor(float) override {}
|
||||
float ceff(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void checkDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &margin) override;
|
||||
string reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
string reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
};
|
||||
|
||||
ArcDelayCalc *
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
# 3 corners with +/- 10% derating example
|
||||
define_corners ss tt ff
|
||||
read_liberty -corner ss nangate45_slow.lib
|
||||
read_liberty -corner tt nangate45_typ.lib
|
||||
read_liberty -corner ff nangate45_fast.lib
|
||||
read_verilog example1.v
|
||||
link_design top
|
||||
set_timing_derate -early 0.9
|
||||
set_timing_derate -late 1.1
|
||||
create_clock -name clk -period 10 {clk1 clk2 clk3}
|
||||
set_input_delay -clock clk 0 {in1 in2}
|
||||
# report all corners
|
||||
report_checks -path_delay min_max
|
||||
# report typical corner
|
||||
report_checks -corner tt
|
||||
|
|
@ -105,28 +105,26 @@ public:
|
|||
// Return values.
|
||||
ArcDelay &margin) = 0;
|
||||
// Report delay and slew calculation.
|
||||
virtual void reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
// Pass in load_cap or drvr_parasitic.
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result) = 0;
|
||||
virtual string reportGateDelay(const LibertyCell *drvr_cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &in_slew,
|
||||
// Pass in load_cap or drvr_parasitic.
|
||||
float load_cap,
|
||||
const Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) = 0;
|
||||
// Report timing check delay calculation.
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits,
|
||||
string *result) = 0;
|
||||
virtual string reportCheckDelay(const LibertyCell *cell,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
const char *from_slew_annotation,
|
||||
const Slew &to_slew,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) = 0;
|
||||
virtual void finishDrvrPin() = 0;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@ public:
|
|||
// Reset to virgin state.
|
||||
virtual void clear() {}
|
||||
// Returned string is owned by the caller.
|
||||
virtual string *reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
virtual string reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
// Percentage (0.0:1.0) change in delay that causes downstream
|
||||
// delays to be recomputed during incremental delay calculation.
|
||||
virtual float incrementalDelayTolerance();
|
||||
|
|
|
|||
|
|
@ -79,12 +79,11 @@ public:
|
|||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap) const;
|
||||
void reportPower(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
int digits,
|
||||
string *result) const;
|
||||
string reportPower(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
int digits) const;
|
||||
|
||||
protected:
|
||||
void findAxisValues(float in_slew,
|
||||
|
|
|
|||
|
|
@ -1106,7 +1106,7 @@ private:
|
|||
LibertyCell *cell_;
|
||||
};
|
||||
|
||||
const char *
|
||||
string
|
||||
portLibertyToSta(const char *port_name);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -24,28 +24,27 @@ class GateLinearModel : public GateTimingModel
|
|||
{
|
||||
public:
|
||||
GateLinearModel(float intrinsic, float resistance);
|
||||
// gate delay calculation
|
||||
virtual void gateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float load_cap, float in_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// return values
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const;
|
||||
virtual void reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float load_cap,
|
||||
float in_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const;
|
||||
void gateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const override;
|
||||
string reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const override;
|
||||
float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const override;
|
||||
|
||||
protected:
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
|
||||
float intrinsic_;
|
||||
float resistance_;
|
||||
|
|
@ -55,26 +54,25 @@ class CheckLinearModel : public CheckTimingModel
|
|||
{
|
||||
public:
|
||||
explicit CheckLinearModel(float intrinsic);
|
||||
// Timing check margin delay calculation.
|
||||
virtual void checkDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
ArcDelay &margin) const;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
void checkDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const override;
|
||||
string reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const override;
|
||||
|
||||
protected:
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
|
||||
float intrinsic_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,8 +16,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
|
||||
// Return true if name is a bus.
|
||||
bool
|
||||
isBusName(const char *name,
|
||||
|
|
@ -38,7 +42,8 @@ parseBusName(const char *name,
|
|||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &index);
|
||||
// Allow multiple different left/right bus brackets.
|
||||
void
|
||||
|
|
@ -47,7 +52,8 @@ parseBusName(const char *name,
|
|||
const char *brkts_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &index);
|
||||
|
||||
// Parse a bus range, such as BUS[4:0].
|
||||
|
|
@ -59,7 +65,8 @@ parseBusRange(const char *name,
|
|||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to);
|
||||
// brkt_lefts and brkt_rights are corresponding strings of legal
|
||||
|
|
@ -70,12 +77,13 @@ parseBusRange(const char *name,
|
|||
const char *brkts_right,
|
||||
const char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to);
|
||||
|
||||
// Insert escapes before ch1 and ch2 in token.
|
||||
const char *
|
||||
string
|
||||
escapeChars(const char *token,
|
||||
const char ch1,
|
||||
const char ch2,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ public:
|
|||
PatternMatch(const char *pattern);
|
||||
PatternMatch(const char *pattern,
|
||||
const PatternMatch *inherit_from);
|
||||
PatternMatch(const string &pattern,
|
||||
const PatternMatch *inherit_from);
|
||||
bool match(const char *str) const;
|
||||
bool match(const string &str) const;
|
||||
bool matchNoCase(const char *str) const;
|
||||
const char *pattern() const { return pattern_; }
|
||||
bool isRegexp() const { return is_regexp_; }
|
||||
|
|
|
|||
|
|
@ -934,11 +934,11 @@ public:
|
|||
PinSet findGroupPathPins(const char *group_path_name);
|
||||
// Find all required times after updateTiming().
|
||||
void findRequireds();
|
||||
string *reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
string reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
int digits);
|
||||
void writeSdc(const char *filename,
|
||||
// Map hierarchical pins and instances to leaf pins and instances.
|
||||
bool leaf,
|
||||
|
|
|
|||
|
|
@ -58,25 +58,24 @@ public:
|
|||
ReceiverModelPtr receiver_model,
|
||||
OutputWaveforms *output_waveforms);
|
||||
virtual ~GateTableModel();
|
||||
virtual void gateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const;
|
||||
virtual void reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const;
|
||||
void gateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const override;
|
||||
string reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const override;
|
||||
float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const override;
|
||||
|
||||
const TableModel *delayModel() const { return delay_model_; }
|
||||
const TableModel *slewModel() const { return slew_model_; }
|
||||
|
|
@ -92,7 +91,7 @@ protected:
|
|||
const Pvt *pvt,
|
||||
float &slew,
|
||||
float &cap) const;
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
float axisValue(TableAxisPtr axis,
|
||||
float load_cap,
|
||||
float in_slew,
|
||||
|
|
@ -104,16 +103,15 @@ protected:
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap) const;
|
||||
void reportTableLookup(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const;
|
||||
string reportTableLookup(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
int digits) const;
|
||||
void findAxisValues(const TableModel *model,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
|
|
@ -138,23 +136,22 @@ public:
|
|||
explicit CheckTableModel(TableModel *model,
|
||||
TableModel *sigma_models[EarlyLate::index_count]);
|
||||
virtual ~CheckTableModel();
|
||||
virtual void checkDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
void checkDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const override;
|
||||
string reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const override;
|
||||
const TableModel *model() const { return model_; }
|
||||
|
||||
// Check the axes before making the model.
|
||||
|
|
@ -162,7 +159,7 @@ public:
|
|||
static bool checkAxes(const TablePtr table);
|
||||
|
||||
protected:
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
void setIsScaled(bool is_scaled) override;
|
||||
float findValue(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
@ -181,17 +178,16 @@ protected:
|
|||
float load_cap,
|
||||
float in_slew,
|
||||
float related_out_cap) const;
|
||||
void reportTableDelay(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const;
|
||||
string reportTableDelay(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits) const;
|
||||
static bool checkAxis(TableAxisPtr axis);
|
||||
|
||||
TableModel *model_;
|
||||
|
|
@ -227,29 +223,27 @@ public:
|
|||
float value1,
|
||||
float value2,
|
||||
float value3) const;
|
||||
void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const;
|
||||
void report(const Units *units,
|
||||
Report *report) const;
|
||||
string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const;
|
||||
string report(const Units *units,
|
||||
Report *report) const;
|
||||
|
||||
protected:
|
||||
float scaleFactor(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt) const;
|
||||
void reportPvtScaleFactor(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result) const;
|
||||
string reportPvtScaleFactor(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits) const;
|
||||
|
||||
TablePtr table_;
|
||||
TableTemplate *tbl_template_;
|
||||
|
|
@ -285,17 +279,16 @@ public:
|
|||
float axis_value1,
|
||||
float axis_value2,
|
||||
float axis_value3) const;
|
||||
virtual void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const = 0;
|
||||
virtual string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const = 0;
|
||||
virtual void report(const Units *units,
|
||||
Report *report) const = 0;
|
||||
};
|
||||
|
|
@ -305,26 +298,25 @@ class Table0 : public Table
|
|||
{
|
||||
public:
|
||||
Table0(float value);
|
||||
virtual int order() const { return 0; }
|
||||
virtual float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const;
|
||||
virtual float findValue(float axis_value1,
|
||||
float axis_value2,
|
||||
float axis_value3) const;
|
||||
virtual void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual void report(const Units *units,
|
||||
Report *report) const;
|
||||
int order() const override { return 0; }
|
||||
float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const override;
|
||||
float findValue(float axis_value1,
|
||||
float axis_value2,
|
||||
float axis_value3) const override;
|
||||
string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const override;
|
||||
void report(const Units *units,
|
||||
Report *report) const override;
|
||||
using Table::findValue;
|
||||
|
||||
private:
|
||||
|
|
@ -341,35 +333,36 @@ public:
|
|||
virtual ~Table1();
|
||||
Table1(Table1 &&table);
|
||||
Table1 &operator= (Table1 &&table);
|
||||
virtual int order() const { return 1; }
|
||||
virtual TableAxisPtr axis1() const { return axis1_; }
|
||||
virtual float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const;
|
||||
int order() const override { return 1; }
|
||||
TableAxisPtr axis1() const override { return axis1_; }
|
||||
float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const override;
|
||||
float findValue(float value1,
|
||||
float value2,
|
||||
float value3) const override;
|
||||
string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const override;
|
||||
void report(const Units *units,
|
||||
Report *report) const override;
|
||||
|
||||
// Table1 specific functions.
|
||||
float value(size_t index1) const;
|
||||
float findValue(float axis_value1) const;
|
||||
void findValue(float axis_value1,
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &extrapolated) const;
|
||||
float findValue(float axis_value1) const;
|
||||
float findValueClip(float axis_value1,
|
||||
float clip_value) const;
|
||||
virtual float findValue(float value1,
|
||||
float value2,
|
||||
float value3) const;
|
||||
virtual void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual void report(const Units *units,
|
||||
Report *report) const;
|
||||
FloatSeq *values() const { return values_; }
|
||||
using Table::findValue;
|
||||
|
||||
|
|
@ -386,31 +379,33 @@ public:
|
|||
TableAxisPtr axis1,
|
||||
TableAxisPtr axis2);
|
||||
virtual ~Table2();
|
||||
virtual int order() const { return 2; }
|
||||
TableAxisPtr axis1() const { return axis1_; }
|
||||
TableAxisPtr axis2() const { return axis2_; }
|
||||
virtual float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const;
|
||||
int order() const override { return 2; }
|
||||
TableAxisPtr axis1() const override { return axis1_; }
|
||||
TableAxisPtr axis2() const override { return axis2_; }
|
||||
float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const override;
|
||||
float findValue(float value1,
|
||||
float value2,
|
||||
float value3) const override;
|
||||
string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const override;
|
||||
void report(const Units *units,
|
||||
Report *report) const override;
|
||||
|
||||
// Table2 specific functions.
|
||||
float value(size_t axis_index1,
|
||||
size_t axis_index2) const;
|
||||
virtual float findValue(float axis_value1,
|
||||
float axis_value2,
|
||||
float axis_value3) const;
|
||||
FloatTable *values3() { return values_; }
|
||||
virtual void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual void report(const Units *units,
|
||||
Report *report) const;
|
||||
|
||||
using Table::findValue;
|
||||
|
||||
protected:
|
||||
|
|
@ -430,27 +425,28 @@ public:
|
|||
TableAxisPtr axis2,
|
||||
TableAxisPtr axis3);
|
||||
virtual ~Table3() {}
|
||||
virtual int order() const { return 3; }
|
||||
TableAxisPtr axis3() const { return axis3_; }
|
||||
virtual float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const;
|
||||
virtual float findValue(float axis_value1,
|
||||
float axis_value2,
|
||||
float axis_value3) const;
|
||||
virtual void reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual void report(const Units *units,
|
||||
Report *report) const;
|
||||
int order() const override { return 3; }
|
||||
TableAxisPtr axis1() const override { return axis1_; }
|
||||
TableAxisPtr axis2() const override { return axis2_; }
|
||||
TableAxisPtr axis3() const override { return axis3_; }
|
||||
float value(size_t axis_index1,
|
||||
size_t axis_index2,
|
||||
size_t axis_index3) const override;
|
||||
float findValue(float value1,
|
||||
float value2,
|
||||
float value3) const override;
|
||||
string reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float value1,
|
||||
const char *comment1,
|
||||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits) const override;
|
||||
void report(const Units *units,
|
||||
Report *report) const override;
|
||||
using Table::findValue;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -50,14 +50,13 @@ public:
|
|||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const = 0;
|
||||
virtual void reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const = 0;
|
||||
virtual string reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const = 0;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const = 0;
|
||||
};
|
||||
|
|
@ -75,15 +74,14 @@ public:
|
|||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const = 0;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const = 0;
|
||||
virtual string reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits) const = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -16,25 +16,29 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace sta {
|
||||
|
||||
const char *
|
||||
using std::string;
|
||||
|
||||
string
|
||||
instanceVerilogName(const char *sta_name,
|
||||
const char escape);
|
||||
const char *
|
||||
string
|
||||
netVerilogName(const char *sta_name,
|
||||
const char escape);
|
||||
const char *
|
||||
string
|
||||
portVerilogName(const char *sta_name,
|
||||
const char escape);
|
||||
|
||||
const char *
|
||||
string
|
||||
moduleVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
string
|
||||
instanceVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
string
|
||||
netVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
string
|
||||
portVerilogToSta(const char *sta_name);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -139,23 +139,23 @@ InternalPowerModel::power(const LibertyCell *cell,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
InternalPowerModel::reportPower(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
if (model_) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(in_slew, load_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
model_->reportValue("Power", library, cell, pvt,
|
||||
axis_value1, nullptr, axis_value2, axis_value3,
|
||||
library->units()->powerUnit(), digits, result);
|
||||
return model_->reportValue("Power", library, cell, pvt,
|
||||
axis_value1, nullptr, axis_value2, axis_value3,
|
||||
library->units()->powerUnit(), digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@ LibertyLibrary::~LibertyLibrary()
|
|||
stringDelete(supply_name);
|
||||
}
|
||||
delete buffers_;
|
||||
driver_waveform_map_.deleteContents();
|
||||
delete driver_waveform_default_;
|
||||
}
|
||||
|
||||
LibertyCell *
|
||||
|
|
@ -2518,23 +2520,20 @@ LibertyPort::setReceiverModel(ReceiverModelPtr receiver_model)
|
|||
receiver_model_ = receiver_model;
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
portLibertyToSta(const char *port_name)
|
||||
{
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
size_t name_length = strlen(port_name);
|
||||
char *sta_name = makeTmpString(name_length * 2);
|
||||
//char *sta_name = new char[name_length * 2];//makeTmpString(name_length * 2);
|
||||
char *p = sta_name;
|
||||
string sta_name;
|
||||
for (size_t i = 0; i < name_length; i++) {
|
||||
char ch = port_name[i];
|
||||
if (ch == bus_brkt_left
|
||||
|| ch == bus_brkt_right)
|
||||
*p++ = '\\';
|
||||
*p++ = ch;
|
||||
sta_name += '\\';
|
||||
sta_name += ch;
|
||||
}
|
||||
*p++ = '\0';
|
||||
return sta_name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ LibertyPort *
|
|||
LibertyBuilder::makePort(LibertyCell *cell,
|
||||
const char *port_name)
|
||||
{
|
||||
const char *sta_name = portLibertyToSta(port_name);
|
||||
LibertyPort *port = new LibertyPort(cell, sta_name, false, nullptr,
|
||||
string sta_name = portLibertyToSta(port_name);
|
||||
LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), false, nullptr,
|
||||
-1, -1, false, nullptr);
|
||||
cell->addPort(port);
|
||||
return port;
|
||||
|
|
@ -89,12 +89,13 @@ LibertyBuilder::makeBusPortBit(ConcreteLibrary *library,
|
|||
const char *bus_name,
|
||||
int bit_index)
|
||||
{
|
||||
char *bit_name = stringPrintTmp("%s%c%d%c",
|
||||
bus_name,
|
||||
library->busBrktLeft(),
|
||||
bit_index,
|
||||
library->busBrktRight());
|
||||
LibertyPort *port = makePort(cell, bit_name, bit_index);
|
||||
string bit_name;
|
||||
stringPrint(bit_name, "%s%c%d%c",
|
||||
bus_name,
|
||||
library->busBrktLeft(),
|
||||
bit_index,
|
||||
library->busBrktRight());
|
||||
LibertyPort *port = makePort(cell, bit_name.c_str(), bit_index);
|
||||
bus_port->addPortBit(port);
|
||||
cell->addPortBit(port);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -523,38 +523,42 @@ LibertyReader::defineScalingFactorVisitors()
|
|||
if (scaleFactorTypeRiseFallSuffix(type)) {
|
||||
for (auto tr : RiseFall::range()) {
|
||||
const char *tr_name = (tr == RiseFall::rise()) ? "rise":"fall";
|
||||
const char *attr_name = stringPrintTmp("k_%s_%s_%s",
|
||||
pvt_name,
|
||||
type_name,
|
||||
tr_name);
|
||||
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactorSuffix);
|
||||
string attr_name;
|
||||
stringPrint(attr_name, "k_%s_%s_%s",
|
||||
pvt_name,
|
||||
type_name,
|
||||
tr_name);
|
||||
defineAttrVisitor(attr_name.c_str() ,&LibertyReader::visitScaleFactorSuffix);
|
||||
}
|
||||
}
|
||||
else if (scaleFactorTypeRiseFallPrefix(type)) {
|
||||
for (auto tr : RiseFall::range()) {
|
||||
const char *tr_name = (tr == RiseFall::rise()) ? "rise":"fall";
|
||||
const char *attr_name = stringPrintTmp("k_%s_%s_%s",
|
||||
pvt_name,
|
||||
tr_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactorPrefix);
|
||||
string attr_name;
|
||||
stringPrint(attr_name, "k_%s_%s_%s",
|
||||
pvt_name,
|
||||
tr_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactorPrefix);
|
||||
}
|
||||
}
|
||||
else if (scaleFactorTypeLowHighSuffix(type)) {
|
||||
for (auto tr : RiseFall::range()) {
|
||||
const char *tr_name = (tr == RiseFall::rise()) ? "high":"low";
|
||||
const char *attr_name = stringPrintTmp("k_%s_%s_%s",
|
||||
pvt_name,
|
||||
tr_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactorHiLow);
|
||||
string attr_name;
|
||||
stringPrint(attr_name, "k_%s_%s_%s",
|
||||
pvt_name,
|
||||
tr_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactorHiLow);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const char *attr_name = stringPrintTmp("k_%s_%s",
|
||||
pvt_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name,&LibertyReader::visitScaleFactor);
|
||||
string attr_name;
|
||||
stringPrint(attr_name, "k_%s_%s",
|
||||
pvt_name,
|
||||
type_name);
|
||||
defineAttrVisitor(attr_name.c_str(),&LibertyReader::visitScaleFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -770,39 +774,32 @@ LibertyReader::parseUnits(LibertyAttr *attr,
|
|||
float &scale_var,
|
||||
Unit *unit)
|
||||
{
|
||||
const char *unit_str = getAttrString(attr);
|
||||
if (unit_str) {
|
||||
unsigned unit_str_length = strlen(unit_str);
|
||||
|
||||
string units = getAttrString(attr);
|
||||
if (!units.empty()) {
|
||||
// Unit format is <multipler_digits><scale_suffix_char><unit_suffix>.
|
||||
// Find the multiplier digits.
|
||||
char *mult_str = makeTmpString(unit_str_length);
|
||||
const char *s = unit_str;
|
||||
char *m = mult_str;
|
||||
for (; *s; s++) {
|
||||
char ch = *s;
|
||||
if (isdigit(ch))
|
||||
*m++ = ch;
|
||||
else
|
||||
break;
|
||||
}
|
||||
*m = '\0';
|
||||
|
||||
string units = getAttrString(attr);
|
||||
size_t mult_end = units.find_first_not_of("01234567890");
|
||||
float mult = 1.0F;
|
||||
if (*mult_str != '\0') {
|
||||
if (stringEq(mult_str, "1"))
|
||||
string scale_suffix;
|
||||
if (mult_end != units.npos) {
|
||||
string unit_mult = units.substr(0, mult_end);
|
||||
scale_suffix = units.substr(mult_end);
|
||||
if (unit_mult == "1")
|
||||
mult = 1.0F;
|
||||
else if (stringEq(mult_str, "10"))
|
||||
else if (unit_mult == "10")
|
||||
mult = 10.0F;
|
||||
else if (stringEq(mult_str, "100"))
|
||||
else if (unit_mult == "100")
|
||||
mult = 100.0F;
|
||||
else
|
||||
libWarn(38, attr, "unknown unit multiplier %s.", mult_str);
|
||||
libWarn(38, attr, "unknown unit multiplier %s.", unit_mult.c_str());
|
||||
}
|
||||
else
|
||||
scale_suffix = units;
|
||||
|
||||
float scale_mult = 1.0F;
|
||||
if (*s && stringEqual(s + 1, unit_suffix)) {
|
||||
char scale_char = tolower(*s);
|
||||
if (scale_suffix.size() >= 2 && scale_suffix.substr(1) == unit_suffix) {
|
||||
char scale_char = tolower(scale_suffix[0]);
|
||||
if (scale_char == 'k')
|
||||
scale_mult = 1E+3F;
|
||||
else if (scale_char == 'm')
|
||||
|
|
@ -818,8 +815,8 @@ LibertyReader::parseUnits(LibertyAttr *attr,
|
|||
else
|
||||
libWarn(39, attr, "unknown unit scale %c.", scale_char);
|
||||
}
|
||||
else if (!stringEqual(s, unit_suffix))
|
||||
libWarn(40, attr, "unknown unit suffix %s.", s + 1);
|
||||
else if (!stringEqual(scale_suffix.c_str(), unit_suffix))
|
||||
libWarn(40, attr, "unknown unit suffix %s.", scale_suffix.c_str());
|
||||
|
||||
scale_var = scale_mult * mult;
|
||||
unit->setScale(scale_var);
|
||||
|
|
@ -2526,7 +2523,7 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group)
|
|||
cap_axis->findAxisIndex(waveform->cap(), cap_index, cap_exists);
|
||||
if (slew_exists && cap_exists) {
|
||||
size_t index = slew_index * cap_axis->size() + cap_index;
|
||||
current_waveforms[index] = waveform->currents();
|
||||
current_waveforms[index] = waveform->stealCurrents();
|
||||
(*ref_times)[slew_index] = waveform->referenceTime();
|
||||
}
|
||||
else
|
||||
|
|
@ -2539,6 +2536,7 @@ LibertyReader::endOutputCurrentRiseFall(LibertyGroup *group)
|
|||
current_waveforms,
|
||||
ref_time_tbl);
|
||||
timing_->setOutputWaveforms(rf_, output_current);
|
||||
output_currents_.deleteContentsClear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3191,8 +3189,8 @@ libertyReaderFindPort(LibertyCell *cell,
|
|||
char brkt_right = library->busBrktRight();
|
||||
const char escape = '\\';
|
||||
// Pins at top level with bus names have escaped brackets.
|
||||
port_name = escapeChars(port_name, brkt_left, brkt_right, escape);
|
||||
port = cell->findLibertyPort(port_name);
|
||||
string escaped_port_name = escapeChars(port_name, brkt_left, brkt_right, escape);
|
||||
port = cell->findLibertyPort(escaped_port_name.c_str());
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
|
@ -4770,11 +4768,12 @@ LibertyReader::parseFunc(const char *func,
|
|||
const char *attr_name,
|
||||
int line)
|
||||
{
|
||||
const char *error_msg = stringPrintTmp("%s, line %d %s",
|
||||
filename_,
|
||||
line,
|
||||
attr_name);
|
||||
return parseFuncExpr(func, cell_, error_msg, report_);
|
||||
string error_msg;
|
||||
stringPrint(error_msg, "%s, line %d %s",
|
||||
filename_,
|
||||
line,
|
||||
attr_name);
|
||||
return parseFuncExpr(func, cell_, error_msg.c_str(), report_);
|
||||
}
|
||||
|
||||
EarlyLateAll *
|
||||
|
|
@ -5627,7 +5626,6 @@ PortNameBitIterator::PortNameBitIterator(LibertyCell *cell,
|
|||
port_(nullptr),
|
||||
bit_iterator_(nullptr),
|
||||
range_bus_port_(nullptr),
|
||||
range_bus_name_(nullptr),
|
||||
range_name_next_(nullptr),
|
||||
size_(0)
|
||||
{
|
||||
|
|
@ -5648,11 +5646,13 @@ PortNameBitIterator::init(const char *port_name)
|
|||
else {
|
||||
// Check for bus range.
|
||||
LibertyLibrary *library = visitor_->library();
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int from, to;
|
||||
char *bus_name;
|
||||
parseBusRange(port_name, library->busBrktLeft(), library->busBrktRight(),
|
||||
'\\', bus_name, from, to);
|
||||
if (bus_name) {
|
||||
parseBusRange(port_name, library->busBrktLeft(),
|
||||
library->busBrktRight(), '\\',
|
||||
is_bus, bus_name, from, to);
|
||||
if (is_bus) {
|
||||
port = visitor_->findPort(port_name);
|
||||
if (port) {
|
||||
if (port->isBus()) {
|
||||
|
|
@ -5662,7 +5662,6 @@ PortNameBitIterator::init(const char *port_name)
|
|||
range_from_ = from;
|
||||
range_to_ = to;
|
||||
range_bit_ = from;
|
||||
delete [] bus_name;
|
||||
}
|
||||
else
|
||||
visitor_->libWarn(156, line_, "port %s subscript out of range.",
|
||||
|
|
@ -5671,7 +5670,7 @@ PortNameBitIterator::init(const char *port_name)
|
|||
else
|
||||
visitor_->libWarn(157, line_, "port range %s of non-bus port %s.",
|
||||
port_name,
|
||||
bus_name);
|
||||
bus_name.c_str());
|
||||
}
|
||||
else {
|
||||
range_bus_name_ = bus_name;
|
||||
|
|
@ -5689,7 +5688,6 @@ PortNameBitIterator::init(const char *port_name)
|
|||
|
||||
PortNameBitIterator::~PortNameBitIterator()
|
||||
{
|
||||
stringDelete(range_bus_name_);
|
||||
delete bit_iterator_;
|
||||
}
|
||||
|
||||
|
|
@ -5702,7 +5700,7 @@ PortNameBitIterator::hasNext()
|
|||
&& ((range_from_ > range_to_)
|
||||
? range_bit_ >= range_to_
|
||||
: range_bit_ <= range_from_))
|
||||
|| (range_bus_name_
|
||||
|| (!range_bus_name_.empty()
|
||||
&& range_name_next_);
|
||||
}
|
||||
|
||||
|
|
@ -5724,7 +5722,7 @@ PortNameBitIterator::next()
|
|||
range_bit_++;
|
||||
return next;
|
||||
}
|
||||
else if (range_bus_name_) {
|
||||
else if (!range_bus_name_.empty()) {
|
||||
LibertyPort *next = range_name_next_;
|
||||
findRangeBusNameNext();
|
||||
return next;
|
||||
|
|
@ -5740,12 +5738,13 @@ PortNameBitIterator::findRangeBusNameNext()
|
|||
? range_bit_ >= range_to_
|
||||
: range_bit_ <= range_to_) {
|
||||
LibertyLibrary *library = visitor_->library();
|
||||
const char *bus_bit_name = stringPrintTmp("%s%c%d%c",
|
||||
range_bus_name_,
|
||||
library->busBrktLeft(),
|
||||
range_bit_,
|
||||
library->busBrktRight());
|
||||
range_name_next_ = visitor_->findPort(bus_bit_name);
|
||||
string bus_bit_name;
|
||||
stringPrint(bus_bit_name, "%s%c%d%c",
|
||||
range_bus_name_.c_str(),
|
||||
library->busBrktLeft(),
|
||||
range_bit_,
|
||||
library->busBrktRight());
|
||||
range_name_next_ = visitor_->findPort(bus_bit_name.c_str());
|
||||
if (range_name_next_) {
|
||||
if (range_from_ > range_to_)
|
||||
range_bit_--;
|
||||
|
|
@ -5753,7 +5752,7 @@ PortNameBitIterator::findRangeBusNameNext()
|
|||
range_bit_++;
|
||||
}
|
||||
else
|
||||
visitor_->libWarn(159, line_, "port %s not found.", bus_bit_name);
|
||||
visitor_->libWarn(159, line_, "port %s not found.", bus_bit_name.c_str());
|
||||
}
|
||||
else
|
||||
range_name_next_ = nullptr;
|
||||
|
|
@ -5777,4 +5776,12 @@ OutputWaveform::~OutputWaveform()
|
|||
delete currents_;
|
||||
}
|
||||
|
||||
Table1 *
|
||||
OutputWaveform::stealCurrents()
|
||||
{
|
||||
Table1 *currents = currents_;
|
||||
currents_ = nullptr;
|
||||
return currents;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -861,7 +861,7 @@ protected:
|
|||
LibertyPort *port_;
|
||||
LibertyPortMemberIterator *bit_iterator_;
|
||||
LibertyPort *range_bus_port_;
|
||||
const char *range_bus_name_;
|
||||
string range_bus_name_;
|
||||
LibertyPort *range_name_next_;
|
||||
int range_from_;
|
||||
int range_to_;
|
||||
|
|
@ -880,8 +880,9 @@ public:
|
|||
float slew() const { return slew_; }
|
||||
float cap() const { return cap_; }
|
||||
Table1 *currents() const { return currents_; }
|
||||
float referenceTime() const { return reference_time_; }
|
||||
|
||||
Table1 *stealCurrents();
|
||||
float referenceTime() { return reference_time_; }
|
||||
|
||||
private:
|
||||
float slew_;
|
||||
float cap_;
|
||||
|
|
|
|||
|
|
@ -43,30 +43,30 @@ GateLinearModel::gateDelay(const LibertyCell *,
|
|||
drvr_slew = 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
GateLinearModel::reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *,
|
||||
float,
|
||||
float load_cap,
|
||||
float,
|
||||
bool,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
const Units *units = library->units();
|
||||
const Unit *time_unit = units->timeUnit();
|
||||
const Unit *res_unit = units->resistanceUnit();
|
||||
const Unit *cap_unit = units->capacitanceUnit();
|
||||
*result += "Delay = ";
|
||||
*result += time_unit->asString(intrinsic_, digits);
|
||||
*result += " + ";
|
||||
*result += res_unit->asString(resistance_, digits);
|
||||
*result += " * ";
|
||||
*result += cap_unit->asString(load_cap, digits);
|
||||
*result += " = ";
|
||||
string result = "Delay = ";
|
||||
result += time_unit->asString(intrinsic_, digits);
|
||||
result += " + ";
|
||||
result += res_unit->asString(resistance_, digits);
|
||||
result += " * ";
|
||||
result += cap_unit->asString(load_cap, digits);
|
||||
result += " = ";
|
||||
float delay = intrinsic_ + resistance_ * load_cap;
|
||||
*result += time_unit->asString(delay, digits);
|
||||
result += time_unit->asString(delay, digits);
|
||||
return result;
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -98,7 +98,7 @@ CheckLinearModel::checkDelay(const LibertyCell *,
|
|||
margin = intrinsic_;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
CheckLinearModel::reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *,
|
||||
float,
|
||||
|
|
@ -106,14 +106,14 @@ CheckLinearModel::reportCheckDelay(const LibertyCell *cell,
|
|||
float,
|
||||
float,
|
||||
bool,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
const Units *units = library->units();
|
||||
const Unit *time_unit = units->timeUnit();
|
||||
*result += "Check = ";
|
||||
*result += time_unit->asString(intrinsic_, digits);
|
||||
string result = "Check = ";
|
||||
result += time_unit->asString(intrinsic_, digits);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -33,13 +33,12 @@ using std::make_shared;
|
|||
|
||||
static void
|
||||
deleteSigmaModels(TableModel *models[EarlyLate::index_count]);
|
||||
static void
|
||||
static string
|
||||
reportPvt(const LibertyLibrary *library,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result);
|
||||
int digits);
|
||||
static void
|
||||
appendSpaces(string *result,
|
||||
appendSpaces(string &result,
|
||||
int count);
|
||||
|
||||
GateTableModel::GateTableModel(TableModel *delay_model,
|
||||
|
|
@ -136,46 +135,46 @@ GateTableModel::gateDelay(const LibertyCell *cell,
|
|||
drvr_slew = makeDelay(slew, sigma_early, sigma_late);
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
GateTableModel::reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportPvt(library, pvt, digits, result);
|
||||
reportTableLookup("Delay", library, cell, pvt, delay_model_, in_slew,
|
||||
load_cap, related_out_cap, digits, result);
|
||||
string result = reportPvt(library, pvt, digits);
|
||||
result += reportTableLookup("Delay", library, cell, pvt, delay_model_, in_slew,
|
||||
load_cap, related_out_cap, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableLookup("Delay sigma(early)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
result += reportTableLookup("Delay sigma(early)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits);
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableLookup("Delay sigma(late)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
*result += '\n';
|
||||
reportTableLookup("Slew", library, cell, pvt, slew_model_, in_slew,
|
||||
load_cap, related_out_cap, digits, result);
|
||||
result += reportTableLookup("Delay sigma(late)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits);
|
||||
result += '\n';
|
||||
result += reportTableLookup("Slew", library, cell, pvt, slew_model_, in_slew,
|
||||
load_cap, related_out_cap, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableLookup("Slew sigma(early)", library, cell, pvt,
|
||||
result += reportTableLookup("Slew sigma(early)", library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
in_slew, load_cap, related_out_cap, digits);
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableLookup("Slew sigma(late)", library, cell, pvt,
|
||||
result += reportTableLookup("Slew sigma(late)", library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
in_slew, load_cap, related_out_cap, digits);
|
||||
float drvr_slew = findValue(library, cell, pvt, slew_model_, in_slew,
|
||||
load_cap, related_out_cap);
|
||||
if (drvr_slew < 0.0)
|
||||
*result += "Negative slew clipped to 0.0\n";
|
||||
result += "Negative slew clipped to 0.0\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
GateTableModel::reportTableLookup(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
|
|
@ -184,17 +183,17 @@ GateTableModel::reportTableLookup(const char *result_name,
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
if (model) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(model, in_slew, load_cap, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
model->reportValue(result_name, library, cell, pvt,
|
||||
axis_value1, nullptr, axis_value2, axis_value3,
|
||||
library->units()->timeUnit(), digits, result);
|
||||
return model->reportValue(result_name, library, cell, pvt,
|
||||
axis_value1, nullptr, axis_value2, axis_value3,
|
||||
library->units()->timeUnit(), digits);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -470,7 +469,7 @@ CheckTableModel::findValue(const LibertyLibrary *library,
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
CheckTableModel::reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew,
|
||||
|
|
@ -478,26 +477,26 @@ CheckTableModel::reportCheckDelay(const LibertyCell *cell,
|
|||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportTableDelay("Check", library, cell, pvt, model_,
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
string result = reportTableDelay("Check", library, cell, pvt, model_,
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableDelay("Check sigma early", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
result += reportTableDelay("Check sigma early", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableDelay("Check sigma late", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
result += reportTableDelay("Check sigma late", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
CheckTableModel::reportTableDelay(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
|
|
@ -507,18 +506,19 @@ CheckTableModel::reportTableDelay(const char *result_name,
|
|||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
if (model) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
reportPvt(library, pvt, digits, result);
|
||||
model_->reportValue(result_name, library, cell, pvt,
|
||||
axis_value1, from_slew_annotation, axis_value2,
|
||||
axis_value3, library->units()->timeUnit(), digits, result);
|
||||
string result = reportPvt(library, pvt, digits);
|
||||
result += model_->reportValue(result_name, library, cell, pvt,
|
||||
axis_value1, from_slew_annotation, axis_value2,
|
||||
axis_value3, library->units()->timeUnit(), digits);
|
||||
return result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -690,7 +690,7 @@ TableModel::scaleFactor(const LibertyLibrary *library,
|
|||
rf_index_, cell, pvt);
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
TableModel::reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
|
|
@ -700,55 +700,55 @@ TableModel::reportValue(const char *result_name,
|
|||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
table_->reportValue("Table value", library, cell, pvt, value1,
|
||||
comment1, value2, value3, table_unit, digits, result);
|
||||
string result = table_->reportValue("Table value", library, cell, pvt, value1,
|
||||
comment1, value2, value3, table_unit, digits);
|
||||
|
||||
reportPvtScaleFactor(library, cell, pvt, digits, result);
|
||||
result += reportPvtScaleFactor(library, cell, pvt, digits);
|
||||
|
||||
*result += result_name;
|
||||
*result += " = ";
|
||||
*result += table_unit->asString(findValue(library, cell, pvt,
|
||||
result += result_name;
|
||||
result += " = ";
|
||||
result += table_unit->asString(findValue(library, cell, pvt,
|
||||
value1, value2, value3), digits);
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
static string
|
||||
reportPvt(const LibertyLibrary *library,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result)
|
||||
int digits)
|
||||
{
|
||||
if (pvt == nullptr)
|
||||
pvt = library->defaultOperatingConditions();
|
||||
if (pvt) {
|
||||
string pvt_str;
|
||||
stringPrint(pvt_str, "P = %.*f V = %.*f T = %.*f\n",
|
||||
string result;
|
||||
stringPrint(result, "P = %.*f V = %.*f T = %.*f\n",
|
||||
digits, pvt->process(),
|
||||
digits, pvt->voltage(),
|
||||
digits, pvt->temperature());
|
||||
*result += pvt_str;
|
||||
return result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
TableModel::reportPvtScaleFactor(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
if (pvt == nullptr)
|
||||
pvt = library->defaultOperatingConditions();
|
||||
if (pvt) {
|
||||
string scale_str;
|
||||
stringPrint(scale_str, "PVT scale factor = %.*f\n",
|
||||
string result;
|
||||
stringPrint(result, "PVT scale factor = %.*f\n",
|
||||
digits,
|
||||
scaleFactor(library, cell, pvt));
|
||||
*result += scale_str;
|
||||
return result;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -775,7 +775,7 @@ Table0::findValue(float,
|
|||
return value_;
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
Table0::reportValue(const char *result_name,
|
||||
const LibertyLibrary *,
|
||||
const LibertyCell *,
|
||||
|
|
@ -785,15 +785,15 @@ Table0::reportValue(const char *result_name,
|
|||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
*result += result_name;
|
||||
*result += " constant = ";
|
||||
*result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
string result = result_name;
|
||||
result += " constant = ";
|
||||
result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
if (comment1)
|
||||
*result += comment1;
|
||||
*result += '\n';
|
||||
result += comment1;
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -913,7 +913,7 @@ Table1::findValue(float axis_value1,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
Table1::reportValue(const char *result_name, const
|
||||
LibertyLibrary *library,
|
||||
const LibertyCell *,
|
||||
|
|
@ -923,42 +923,41 @@ Table1::reportValue(const char *result_name, const
|
|||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const Units *units = library->units();
|
||||
const Unit *unit1 = axis1_->unit(units);
|
||||
*result += "Table is indexed by\n";
|
||||
*result += " ";
|
||||
*result += axis1_->variableString();
|
||||
*result += " = ";
|
||||
*result += unit1->asString(value1, digits);
|
||||
string result = "Table is indexed by\n ";
|
||||
result += axis1_->variableString();
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
if (comment1)
|
||||
*result += comment1;
|
||||
*result += '\n';
|
||||
result += comment1;
|
||||
result += '\n';
|
||||
|
||||
if (axis1_->size() != 1) {
|
||||
size_t index1 = axis1_->findAxisIndex(value1);
|
||||
*result += " ";
|
||||
*result += unit1->asString(axis1_->axisValue(index1), digits);
|
||||
*result += " ";
|
||||
*result += unit1->asString(axis1_->axisValue(index1 + 1), digits);
|
||||
*result += '\n';
|
||||
result += " ";
|
||||
result += unit1->asString(axis1_->axisValue(index1), digits);
|
||||
result += " ";
|
||||
result += unit1->asString(axis1_->axisValue(index1 + 1), digits);
|
||||
result += '\n';
|
||||
|
||||
*result += " --------------------\n";
|
||||
result += " --------------------\n";
|
||||
|
||||
*result += "| ";
|
||||
*result += table_unit->asString(value(index1), digits);
|
||||
*result += " ";
|
||||
*result += table_unit->asString(value(index1 + 1),
|
||||
result += "| ";
|
||||
result += table_unit->asString(value(index1), digits);
|
||||
result += " ";
|
||||
result += table_unit->asString(value(index1 + 1),
|
||||
digits);
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
}
|
||||
|
||||
*result += result_name;
|
||||
*result += " = ";
|
||||
*result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
*result += '\n';
|
||||
result += result_name;
|
||||
result += " = ";
|
||||
result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1081,7 +1080,7 @@ Table2::findValue(float axis_value1,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
string
|
||||
Table2::reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *,
|
||||
|
|
@ -1091,62 +1090,62 @@ Table2::reportValue(const char *result_name,
|
|||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const Units *units = library->units();
|
||||
const Unit *unit1 = axis1_->unit(units);
|
||||
const Unit *unit2 = axis2_->unit(units);
|
||||
*result += "------- ";
|
||||
*result += axis1_->variableString(),
|
||||
*result += " = ";
|
||||
*result += unit1->asString(value1, digits);
|
||||
string result = "------- ";
|
||||
result += axis1_->variableString(),
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
if (comment1)
|
||||
*result += comment1;
|
||||
*result += '\n';
|
||||
result += comment1;
|
||||
result += '\n';
|
||||
|
||||
*result += "| ";
|
||||
*result += axis2_->variableString();
|
||||
*result += " = ";
|
||||
*result += unit2->asString(value2, digits);
|
||||
*result += '\n';
|
||||
result += "| ";
|
||||
result += axis2_->variableString();
|
||||
result += " = ";
|
||||
result += unit2->asString(value2, digits);
|
||||
result += '\n';
|
||||
|
||||
size_t index1 = axis1_->findAxisIndex(value1);
|
||||
size_t index2 = axis2_->findAxisIndex(value2);
|
||||
*result += "| ";
|
||||
*result += unit2->asString(axis2_->axisValue(index2), digits);
|
||||
result += "| ";
|
||||
result += unit2->asString(axis2_->axisValue(index2), digits);
|
||||
if (axis2_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += unit2->asString(axis2_->axisValue(index2 + 1), digits);
|
||||
result += " ";
|
||||
result += unit2->asString(axis2_->axisValue(index2 + 1), digits);
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += "v --------------------\n";
|
||||
*result += unit1->asString(axis1_->axisValue(index1), digits);
|
||||
*result += " | ";
|
||||
result += "v --------------------\n";
|
||||
result += unit1->asString(axis1_->axisValue(index1), digits);
|
||||
result += " | ";
|
||||
|
||||
*result += table_unit->asString(value(index1, index2), digits);
|
||||
result += table_unit->asString(value(index1, index2), digits);
|
||||
if (axis2_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += table_unit->asString(value(index1, index2 + 1), digits);
|
||||
result += " ";
|
||||
result += table_unit->asString(value(index1, index2 + 1), digits);
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
if (axis1_->size() != 1) {
|
||||
*result += unit1->asString(axis1_->axisValue(index1 + 1), digits);
|
||||
*result += " | ";
|
||||
*result += table_unit->asString(value(index1 + 1, index2), digits);
|
||||
result += unit1->asString(axis1_->axisValue(index1 + 1), digits);
|
||||
result += " | ";
|
||||
result += table_unit->asString(value(index1 + 1, index2), digits);
|
||||
if (axis2_->size() != 1) {
|
||||
*result += " ";
|
||||
*result +=table_unit->asString(value(index1 + 1, index2 + 1),digits);
|
||||
result += " ";
|
||||
result +=table_unit->asString(value(index1 + 1, index2 + 1),digits);
|
||||
}
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += result_name;
|
||||
*result += " = ";
|
||||
*result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
*result += '\n';
|
||||
result += result_name;
|
||||
result += " = ";
|
||||
result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1272,7 +1271,7 @@ Table3::findValue(float axis_value1,
|
|||
// 0.00 0.20 | 0.10 0.20
|
||||
// |/ 0.30 0.32
|
||||
// 0.40 | 0.20 0.30
|
||||
void
|
||||
string
|
||||
Table3::reportValue(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *,
|
||||
|
|
@ -1282,117 +1281,117 @@ Table3::reportValue(const char *result_name,
|
|||
float value2,
|
||||
float value3,
|
||||
const Unit *table_unit,
|
||||
int digits,
|
||||
string *result) const
|
||||
int digits) const
|
||||
{
|
||||
const Units *units = library->units();
|
||||
const Unit *unit1 = axis1_->unit(units);
|
||||
const Unit *unit2 = axis2_->unit(units);
|
||||
const Unit *unit3 = axis3_->unit(units);
|
||||
|
||||
*result += " --------- ";
|
||||
*result += axis1_->variableString(),
|
||||
*result += " = ";
|
||||
*result += unit1->asString(value1, digits);
|
||||
string result = " --------- ";
|
||||
result += axis1_->variableString(),
|
||||
result += " = ";
|
||||
result += unit1->asString(value1, digits);
|
||||
if (comment1)
|
||||
*result += comment1;
|
||||
*result += '\n';
|
||||
result += comment1;
|
||||
result += '\n';
|
||||
|
||||
*result += " | ---- ";
|
||||
*result += axis2_->variableString(),
|
||||
*result += " = ";
|
||||
*result += unit2->asString(value2, digits);
|
||||
*result += '\n';
|
||||
result += " | ---- ";
|
||||
result += axis2_->variableString(),
|
||||
result += " = ";
|
||||
result += unit2->asString(value2, digits);
|
||||
result += '\n';
|
||||
|
||||
*result += " | | ";
|
||||
*result += axis3_->variableString();
|
||||
*result += " = ";
|
||||
*result += unit3->asString(value3, digits);
|
||||
*result += '\n';
|
||||
result += " | | ";
|
||||
result += axis3_->variableString();
|
||||
result += " = ";
|
||||
result += unit3->asString(value3, digits);
|
||||
result += '\n';
|
||||
|
||||
size_t axis_index1 = axis1_->findAxisIndex(value1);
|
||||
size_t axis_index2 = axis2_->findAxisIndex(value2);
|
||||
size_t axis_index3 = axis3_->findAxisIndex(value3);
|
||||
|
||||
*result += " | | ";
|
||||
*result += unit3->asString(axis3_->axisValue(axis_index3), digits);
|
||||
result += " | | ";
|
||||
result += unit3->asString(axis3_->axisValue(axis_index3), digits);
|
||||
if (axis3_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += unit3->asString(axis3_->axisValue(axis_index3 + 1), digits);
|
||||
result += " ";
|
||||
result += unit3->asString(axis3_->axisValue(axis_index3 + 1), digits);
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += " v | --------------------\n";
|
||||
result += " v | --------------------\n";
|
||||
|
||||
if (axis1_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += unit1->asString(axis1_->axisValue(axis_index1+1), digits);
|
||||
*result += " v / ";
|
||||
*result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3),
|
||||
result += " ";
|
||||
result += unit1->asString(axis1_->axisValue(axis_index1+1), digits);
|
||||
result += " v / ";
|
||||
result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3),
|
||||
digits);
|
||||
if (axis3_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3+1),
|
||||
result += " ";
|
||||
result += table_unit->asString(value(axis_index1+1,axis_index2,axis_index3+1),
|
||||
digits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
appendSpaces(result, digits+3);
|
||||
*result += " v / ";
|
||||
result += " v / ";
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += unit1->asString(axis1_->axisValue(axis_index1), digits);
|
||||
*result += " ";
|
||||
*result += unit2->asString(axis2_->axisValue(axis_index2), digits);
|
||||
*result += " | ";
|
||||
*result += table_unit->asString(value(axis_index1, axis_index2, axis_index3), digits);
|
||||
result += unit1->asString(axis1_->axisValue(axis_index1), digits);
|
||||
result += " ";
|
||||
result += unit2->asString(axis2_->axisValue(axis_index2), digits);
|
||||
result += " | ";
|
||||
result += table_unit->asString(value(axis_index1, axis_index2, axis_index3), digits);
|
||||
if (axis3_->size() != 1) {
|
||||
*result += " ";
|
||||
*result += table_unit->asString(value(axis_index1, axis_index2, axis_index3+1),
|
||||
result += " ";
|
||||
result += table_unit->asString(value(axis_index1, axis_index2, axis_index3+1),
|
||||
digits);
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += " |/ ";
|
||||
result += " |/ ";
|
||||
if (axis1_->size() != 1
|
||||
&& axis2_->size() != 1) {
|
||||
*result += table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3),
|
||||
result += table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3),
|
||||
digits);
|
||||
if (axis3_->size() != 1) {
|
||||
*result += " ";
|
||||
*result +=table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3+1),
|
||||
result += " ";
|
||||
result +=table_unit->asString(value(axis_index1+1,axis_index2+1,axis_index3+1),
|
||||
digits);
|
||||
}
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += " ";
|
||||
*result += unit2->asString(axis2_->axisValue(axis_index2 + 1), digits);
|
||||
*result += " | ";
|
||||
result += " ";
|
||||
result += unit2->asString(axis2_->axisValue(axis_index2 + 1), digits);
|
||||
result += " | ";
|
||||
if (axis2_->size() != 1) {
|
||||
*result += table_unit->asString(value(axis_index1, axis_index2+1, axis_index3),
|
||||
digits);
|
||||
result += table_unit->asString(value(axis_index1, axis_index2+1, axis_index3),
|
||||
digits);
|
||||
if (axis3_->size() != 1) {
|
||||
*result += " ";
|
||||
*result +=table_unit->asString(value(axis_index1, axis_index2+1,axis_index3+1),
|
||||
digits);
|
||||
result += " ";
|
||||
result +=table_unit->asString(value(axis_index1, axis_index2+1,axis_index3+1),
|
||||
digits);
|
||||
}
|
||||
}
|
||||
*result += '\n';
|
||||
result += '\n';
|
||||
|
||||
*result += result_name;
|
||||
*result += " = ";
|
||||
*result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
*result += '\n';
|
||||
result += result_name;
|
||||
result += " = ";
|
||||
result += table_unit->asString(findValue(value1, value2, value3), digits);
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
appendSpaces(string *result,
|
||||
appendSpaces(string &result,
|
||||
int count)
|
||||
{
|
||||
while (count--)
|
||||
*result += ' ';
|
||||
result += ' ';
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::map;
|
||||
|
||||
static constexpr char escape_ = '\\';
|
||||
|
||||
ConcreteLibrary::ConcreteLibrary(const char *name,
|
||||
|
|
@ -381,7 +383,7 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
{
|
||||
const char bus_brkts_left[2]{bus_brkt_left, '\0'};
|
||||
const char bus_brkts_right[2]{bus_brkt_right, '\0'};
|
||||
BusPortMap port_map;
|
||||
map<string, BusPort*> port_map;
|
||||
// Find ungrouped bus ports.
|
||||
// Remove bus bit ports from the ports_ vector during the scan by
|
||||
// keeping an index to the next insertion index and skipping over
|
||||
|
|
@ -390,19 +392,21 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
ports_.clear();
|
||||
for (ConcretePort *port : ports) {
|
||||
const char *port_name = port->name();
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(port_name, bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name, index);
|
||||
if (bus_name) {
|
||||
is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
if (!port->isBusBit()) {
|
||||
BusPort *bus_port = port_map.findKey(bus_name);
|
||||
if (bus_port)
|
||||
stringDelete(bus_name);
|
||||
else {
|
||||
bus_port = new BusPort(bus_name, index, port->direction());
|
||||
auto name_bus_port = port_map.find(bus_name);
|
||||
BusPort *bus_port;
|
||||
if (name_bus_port == port_map.end()) {
|
||||
bus_port = new BusPort(bus_name.c_str(), index, port->direction());
|
||||
port_map[bus_name] = bus_port;
|
||||
}
|
||||
else
|
||||
bus_port = name_bus_port->second;
|
||||
bus_port->pushMember(port);
|
||||
}
|
||||
else
|
||||
|
|
@ -413,47 +417,45 @@ ConcreteCell::groupBusPorts(const char bus_brkt_left,
|
|||
}
|
||||
|
||||
// Make the bus ports.
|
||||
BusPortMap::Iterator bus_iter(port_map);
|
||||
while (bus_iter.hasNext()) {
|
||||
BusPort *bus_port = bus_iter.next();
|
||||
const char *bus_name = bus_port->name();
|
||||
bool msb_first = port_msb_first(bus_name);
|
||||
for (auto name_bus : port_map) {
|
||||
const string &bus_name = name_bus.first;
|
||||
BusPort *bus_port = name_bus.second;
|
||||
bool msb_first = port_msb_first(bus_name.c_str());
|
||||
ConcretePortSeq *members = bus_port->members();
|
||||
sort(members, [&](ConcretePort *port1,
|
||||
ConcretePort *port2) {
|
||||
char *bus_name;
|
||||
int index1, index2;
|
||||
parseBusName(port1->name(), bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name, index1);
|
||||
stringDelete(bus_name);
|
||||
parseBusName(port2->name(), bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name, index2);
|
||||
stringDelete(bus_name);
|
||||
return msb_first ? index1 > index2 : index1 < index2;
|
||||
});
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index1, index2;
|
||||
parseBusName(port1->name(), bus_brkts_left, bus_brkts_right, escape_,
|
||||
is_bus, bus_name, index1);
|
||||
parseBusName(port2->name(), bus_brkts_left, bus_brkts_right, escape_,
|
||||
is_bus, bus_name, index2);
|
||||
return msb_first ? index1 > index2 : index1 < index2;
|
||||
});
|
||||
|
||||
char *bus_name1;
|
||||
bool is_bus1;
|
||||
string bus_name1;
|
||||
int from_index, to_index;
|
||||
parseBusName((*members)[0]->name(),
|
||||
bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name1, from_index);
|
||||
stringDelete(bus_name1);
|
||||
is_bus1, bus_name1, from_index);
|
||||
parseBusName((*members)[members->size() - 1]->name(),
|
||||
bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name1, to_index);
|
||||
stringDelete(bus_name1);
|
||||
is_bus1, bus_name1, to_index);
|
||||
|
||||
ConcretePort *port = makeBusPort(bus_name, from_index, to_index, members);
|
||||
ConcretePort *port = makeBusPort(bus_name.c_str(), from_index,
|
||||
to_index, members);
|
||||
port->setDirection(bus_port->direction());
|
||||
delete bus_port;
|
||||
|
||||
for (ConcretePort *port : *members) {
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(port->name(), bus_brkts_left, bus_brkts_right, escape_,
|
||||
bus_name, index);
|
||||
is_bus, bus_name, index);
|
||||
port->setBusBitIndex(index);
|
||||
stringDelete(bus_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,12 +51,14 @@ parseBusName(const char *name,
|
|||
const char brkt_right,
|
||||
const char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &index)
|
||||
{
|
||||
const char brkts_left[2] = {brkt_left, '\0'};
|
||||
const char brkts_right[2] = {brkt_right, '\0'};
|
||||
parseBusName(name, brkts_left, brkts_right, escape, bus_name, index);
|
||||
parseBusName(name, brkts_left, brkts_right, escape,
|
||||
is_bus, bus_name, index);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -65,10 +67,11 @@ parseBusName(const char *name,
|
|||
const char *brkts_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &index)
|
||||
{
|
||||
bus_name = nullptr;
|
||||
is_bus = false;
|
||||
size_t len = strlen(name);
|
||||
// Shortest bus name is a[0].
|
||||
if (len >= 4
|
||||
|
|
@ -81,10 +84,9 @@ parseBusName(const char *name,
|
|||
char brkt_left = brkts_left[brkt_index];
|
||||
const char *left = strrchr(name, brkt_left);
|
||||
if (left) {
|
||||
is_bus = true;
|
||||
size_t bus_name_len = left - name;
|
||||
bus_name = new char[bus_name_len + 1];
|
||||
strncpy(bus_name, name, bus_name_len);
|
||||
bus_name[bus_name_len] = '\0';
|
||||
bus_name.append(name, bus_name_len);
|
||||
// Simple bus subscript.
|
||||
index = atoi(left + 1);
|
||||
}
|
||||
|
|
@ -98,13 +100,15 @@ parseBusRange(const char *name,
|
|||
const char brkt_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to)
|
||||
{
|
||||
const char brkts_left[2] = {brkt_left, '\0'};
|
||||
const char brkts_right[2] = {brkt_right, '\0'};
|
||||
parseBusRange(name, brkts_left, brkts_right, escape, bus_name, from, to);
|
||||
parseBusRange(name, brkts_left, brkts_right, escape,
|
||||
is_bus, bus_name, from, to);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -113,11 +117,12 @@ parseBusRange(const char *name,
|
|||
const char *brkts_right,
|
||||
char escape,
|
||||
// Return values.
|
||||
char *&bus_name,
|
||||
bool &is_bus,
|
||||
string &bus_name,
|
||||
int &from,
|
||||
int &to)
|
||||
{
|
||||
bus_name = nullptr;
|
||||
is_bus = false;
|
||||
size_t len = strlen(name);
|
||||
// Shortest bus range is a[1:0].
|
||||
if (len >= 6
|
||||
|
|
@ -134,10 +139,8 @@ parseBusRange(const char *name,
|
|||
const char range_sep = ':';
|
||||
const char *range = strchr(name, range_sep);
|
||||
if (range) {
|
||||
size_t bus_name_len = left - name;
|
||||
bus_name = new char[bus_name_len + 1];
|
||||
strncpy(bus_name, name, bus_name_len);
|
||||
bus_name[bus_name_len] = '\0';
|
||||
is_bus = true;
|
||||
bus_name.append(name, left - name);
|
||||
// No need to terminate bus subscript because atoi stops
|
||||
// scanning at first non-digit character.
|
||||
from = atoi(left + 1);
|
||||
|
|
@ -148,54 +151,32 @@ parseBusRange(const char *name,
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
escapeChars(const char *token,
|
||||
const char ch1,
|
||||
const char ch2,
|
||||
const char escape)
|
||||
{
|
||||
int result_length = 0;
|
||||
bool need_escapes = false;
|
||||
string escaped;
|
||||
for (const char *s = token; *s; s++) {
|
||||
char ch = *s;
|
||||
if (ch == escape) {
|
||||
char next_ch = s[1];
|
||||
// Make sure we don't skip the null if escape is the last char.
|
||||
if (next_ch != '\0')
|
||||
result_length++;
|
||||
if (next_ch != '\0') {
|
||||
escaped += ch;
|
||||
escaped += next_ch;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
else if (ch == ch1 || ch == ch2) {
|
||||
result_length++;
|
||||
need_escapes = true;
|
||||
escaped += escape;
|
||||
escaped += ch;
|
||||
}
|
||||
result_length++;
|
||||
else
|
||||
escaped += ch;
|
||||
}
|
||||
if (need_escapes) {
|
||||
char *result = makeTmpString(result_length + 1);
|
||||
char *r = result;
|
||||
for (const char *s = token; *s; s++) {
|
||||
char ch = *s;
|
||||
if (ch == escape) {
|
||||
char next_ch = s[1];
|
||||
// Make sure we don't skip the null if escape is the last char.
|
||||
if (next_ch != '\0') {
|
||||
*r++ = ch;
|
||||
*r++ = next_ch;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
else if (ch == ch1 || ch == ch2) {
|
||||
*r++ = escape;
|
||||
*r++ = ch;
|
||||
}
|
||||
else
|
||||
*r++ = ch;
|
||||
}
|
||||
*r++ = '\0';
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return token;
|
||||
return escaped;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
static const char *
|
||||
static string
|
||||
escapeDividers(const char *token,
|
||||
const Network *network);
|
||||
static const char *
|
||||
static string
|
||||
escapeBrackets(const char *token,
|
||||
const Network *network);
|
||||
|
||||
|
|
@ -631,21 +631,22 @@ SdcNetwork::findPort(const Cell *cell,
|
|||
Port *port = network_->findPort(cell, name);
|
||||
if (port == nullptr) {
|
||||
// Look for matches after escaping brackets.
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(name, '[', ']', pathEscape(), bus_name, index);
|
||||
if (bus_name) {
|
||||
const char *escaped1 = escapeBrackets(name, this);
|
||||
port = network_->findPort(cell, escaped1);
|
||||
if (port == nullptr
|
||||
&& bus_name[strlen(bus_name) - 1] == ']') {
|
||||
parseBusName(name, '[', ']', pathEscape(), is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(name, this);
|
||||
port = network_->findPort(cell, escaped1.c_str());
|
||||
if (port == nullptr) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
const char *escaped2 = stringPrintTmp("%s[%d]",
|
||||
escapeBrackets(bus_name, this),
|
||||
index);
|
||||
port = network_->findPort(cell, escaped2);
|
||||
string escaped2;
|
||||
string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
stringPrint(escaped2, "%s[%d]",
|
||||
escaped_bus_name.c_str(),
|
||||
index);
|
||||
port = network_->findPort(cell, escaped2.c_str());
|
||||
}
|
||||
stringDelete(bus_name);
|
||||
}
|
||||
}
|
||||
return port;
|
||||
|
|
@ -658,23 +659,25 @@ SdcNetwork::findPortsMatching(const Cell *cell,
|
|||
PortSeq matches = network_->findPortsMatching(cell, pattern);
|
||||
if (matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(pattern->pattern(), '[', ']', pathEscape(), bus_name, index);
|
||||
if (bus_name) {
|
||||
const char *escaped1 = escapeBrackets(pattern->pattern(), this);
|
||||
PatternMatch escaped_pattern1(escaped1, pattern);
|
||||
parseBusName(pattern->pattern(), '[', ']', pathEscape(),
|
||||
is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(pattern->pattern(), this);
|
||||
PatternMatch escaped_pattern1(escaped1.c_str(), pattern);
|
||||
matches = network_->findPortsMatching(cell, &escaped_pattern1);
|
||||
if (matches.empty()
|
||||
&& bus_name[strlen(bus_name) - 1] == ']') {
|
||||
if (matches.empty()) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
const char *escaped2 = stringPrintTmp("%s[%d]",
|
||||
escapeBrackets(bus_name, this),
|
||||
index);
|
||||
PatternMatch escaped_pattern2(escaped2, pattern);
|
||||
string escaped2;
|
||||
string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
stringPrint(escaped2, "%s[%d]",
|
||||
escaped_bus_name.c_str(),
|
||||
index);
|
||||
PatternMatch escaped_pattern2(escaped2.c_str(), pattern);
|
||||
matches = network_->findPortsMatching(cell, &escaped_pattern2);
|
||||
}
|
||||
stringDelete(bus_name);
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
|
|
@ -739,8 +742,10 @@ SdcNetwork::findInstance(const char *path_name) const
|
|||
if (parent == nullptr)
|
||||
parent = network_->topInstance();
|
||||
Instance *child = findChild(parent, child_name);
|
||||
if (child == nullptr)
|
||||
child = findChild(parent, escapeDividers(child_name, this));
|
||||
if (child == nullptr) {
|
||||
string escaped_name = escapeDividers(child_name, this);
|
||||
child = findChild(parent, escaped_name.c_str());
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
|
|
@ -774,8 +779,8 @@ SdcNetwork::findChild(const Instance *parent,
|
|||
{
|
||||
Instance *child = network_->findChild(parent, name);
|
||||
if (child == nullptr) {
|
||||
const char *escaped = escapeBrackets(name, this);
|
||||
child = network_->findChild(parent, escaped);
|
||||
string escaped = escapeBrackets(name, this);
|
||||
child = network_->findChild(parent, escaped.c_str());
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
|
@ -799,8 +804,8 @@ SdcNetwork::findNet(const Instance *instance,
|
|||
{
|
||||
Net *net = network_->findNet(instance, net_name);
|
||||
if (net == nullptr) {
|
||||
const char *net_name_ = escapeBrackets(net_name, this);
|
||||
net = network_->findNet(instance, net_name_);
|
||||
string net_name1 = escapeBrackets(net_name, this);
|
||||
net = network_->findNet(instance, net_name1.c_str());
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
|
@ -829,14 +834,13 @@ SdcNetwork::findInstNetsMatching(const Instance *instance,
|
|||
network_->findInstNetsMatching(instance, pattern, matches);
|
||||
if (matches.empty()) {
|
||||
// Look for matches after escaping path dividers.
|
||||
const PatternMatch escaped_dividers(escapeDividers(pattern->pattern(),
|
||||
this),
|
||||
pattern);
|
||||
string escaped_pattern = escapeDividers(pattern->pattern(), this);
|
||||
const PatternMatch escaped_dividers(escaped_pattern.c_str(), pattern);
|
||||
network_->findInstNetsMatching(instance, &escaped_dividers, matches);
|
||||
if (matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
const PatternMatch escaped_brkts(escapeBrackets(pattern->pattern(),this),
|
||||
pattern);
|
||||
string escaped_pattern2 = escapeBrackets(pattern->pattern(),this);
|
||||
const PatternMatch escaped_brkts(escaped_pattern2.c_str(), pattern);
|
||||
network_->findInstNetsMatching(instance, &escaped_brkts, matches);
|
||||
}
|
||||
}
|
||||
|
|
@ -862,21 +866,21 @@ SdcNetwork::findPin(const Instance *instance,
|
|||
Pin *pin = network_->findPin(instance, port_name);
|
||||
if (pin == nullptr) {
|
||||
// Look for match after escaping brackets.
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(port_name, '[', ']', pathEscape(), bus_name, index);
|
||||
if (bus_name) {
|
||||
const char *escaped1 = escapeBrackets(port_name, this);
|
||||
pin = network_->findPin(instance, escaped1);
|
||||
if (pin == nullptr
|
||||
&& bus_name[strlen(bus_name) - 1] == ']') {
|
||||
parseBusName(port_name, '[', ']', pathEscape(),
|
||||
is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string escaped1 = escapeBrackets(port_name, this);
|
||||
pin = network_->findPin(instance, escaped1.c_str());
|
||||
if (pin == nullptr) {
|
||||
// Try escaping base foo\[0\][1]
|
||||
const char *escaped2 = stringPrintTmp("%s[%d]",
|
||||
escapeBrackets(bus_name, this),
|
||||
index);
|
||||
pin = network_->findPin(instance, escaped2);
|
||||
string escaped_bus_name = escapeBrackets(bus_name.c_str(), this);
|
||||
string escaped2;
|
||||
stringPrint(escaped2, "%s[%d]", escaped_bus_name.c_str(), index);
|
||||
pin = network_->findPin(instance, escaped2.c_str());
|
||||
}
|
||||
stringDelete(bus_name);
|
||||
}
|
||||
}
|
||||
return pin;
|
||||
|
|
@ -967,16 +971,16 @@ SdcNetwork::makeInstance(LibertyCell *cell,
|
|||
const char *name,
|
||||
Instance *parent)
|
||||
{
|
||||
const char *escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeInstance(cell, escaped_name, parent);
|
||||
string escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeInstance(cell, escaped_name.c_str(), parent);
|
||||
}
|
||||
|
||||
Net *
|
||||
SdcNetwork::makeNet(const char *name,
|
||||
Instance *parent)
|
||||
{
|
||||
const char *escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeNet(escaped_name, parent);
|
||||
string escaped_name = escapeDividers(name, this);
|
||||
return network_edit_->makeNet(escaped_name.c_str(), parent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1154,10 +1158,9 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
found_match |= visit_tail(parent, &tail_pattern);
|
||||
if (!found_match && has_brkts) {
|
||||
// Look for matches after escaping brackets.
|
||||
char *escaped_path = stringCopy(escapeBrackets(inst_path, this));
|
||||
string escaped_path = escapeBrackets(inst_path, this);
|
||||
const PatternMatch escaped_tail(escaped_path, pattern);
|
||||
found_match |= visit_tail(parent, &escaped_tail);
|
||||
stringDelete(escaped_path);
|
||||
}
|
||||
}
|
||||
stringDelete(inst_path);
|
||||
|
|
@ -1166,7 +1169,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *
|
||||
static string
|
||||
escapeDividers(const char *token,
|
||||
const Network *network)
|
||||
{
|
||||
|
|
@ -1174,7 +1177,7 @@ escapeDividers(const char *token,
|
|||
network->pathEscape());
|
||||
}
|
||||
|
||||
static const char *
|
||||
static string
|
||||
escapeBrackets(const char *token,
|
||||
const Network *network)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,72 +23,63 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
static const char *
|
||||
static string
|
||||
staToVerilog(const char *sta_name,
|
||||
const char escape);
|
||||
static const char *
|
||||
static string
|
||||
staToVerilog2(const char *sta_name,
|
||||
const char escape);
|
||||
static const char *
|
||||
static string
|
||||
verilogToSta(const char *verilog_name);
|
||||
static inline void
|
||||
vstringAppend(char *&str,
|
||||
char *&str_end,
|
||||
char *&insert,
|
||||
char ch);
|
||||
|
||||
const char *
|
||||
string
|
||||
instanceVerilogName(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
return staToVerilog(sta_name, escape);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
netVerilogName(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(sta_name, '[', ']', escape, bus_name, index);
|
||||
if (bus_name) {
|
||||
const char *vname = stringPrintTmp("%s[%d]",
|
||||
staToVerilog(bus_name, escape),
|
||||
index);
|
||||
stringDelete(bus_name);
|
||||
parseBusName(sta_name, '[', ']', escape, is_bus, bus_name, index);
|
||||
if (is_bus) {
|
||||
string bus_vname = staToVerilog(bus_name.c_str(), escape);
|
||||
string vname;
|
||||
stringPrint(vname, "%s[%d]", bus_vname.c_str(), index);
|
||||
return vname;
|
||||
}
|
||||
else
|
||||
return staToVerilog2(sta_name, escape);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
portVerilogName(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
return staToVerilog2(sta_name, escape);
|
||||
}
|
||||
|
||||
static const char *
|
||||
static string
|
||||
staToVerilog(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
size_t verilog_name_length = strlen(sta_name) + 3;
|
||||
char *verilog_name = makeTmpString(verilog_name_length);
|
||||
char *verilog_name_end = &verilog_name[verilog_name_length];
|
||||
char *v = verilog_name;
|
||||
// Assume the name has to be escaped and start copying while scanning.
|
||||
string escaped_name = "\\";
|
||||
bool escaped = false;
|
||||
*v++ = '\\';
|
||||
for (const char *s = sta_name; *s ; s++) {
|
||||
char ch = s[0];
|
||||
if (ch == escape) {
|
||||
char next_ch = s[1];
|
||||
if (next_ch == escape) {
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
vstringAppend(verilog_name, verilog_name_end, v, next_ch);
|
||||
escaped_name += ch;
|
||||
escaped_name += next_ch;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
|
|
@ -98,20 +89,19 @@ staToVerilog(const char *sta_name,
|
|||
else {
|
||||
if ((!(isalnum(ch) || ch == '_')))
|
||||
escaped = true;
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
escaped_name += ch;
|
||||
}
|
||||
}
|
||||
if (escaped) {
|
||||
// Add a terminating space.
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ' ');
|
||||
vstringAppend(verilog_name, verilog_name_end, v, '\0');
|
||||
return verilog_name;
|
||||
escaped_name += ' ';
|
||||
return escaped_name;
|
||||
}
|
||||
else
|
||||
return sta_name;
|
||||
return string(sta_name);
|
||||
}
|
||||
|
||||
static const char *
|
||||
static string
|
||||
staToVerilog2(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
|
|
@ -119,20 +109,16 @@ staToVerilog2(const char *sta_name,
|
|||
constexpr char bus_brkt_right = ']';
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
size_t verilog_name_length = strlen(sta_name) + 3;
|
||||
char *verilog_name = makeTmpString(verilog_name_length);
|
||||
char *verilog_name_end = &verilog_name[verilog_name_length];
|
||||
char *v = verilog_name;
|
||||
string escaped_name = "\\";
|
||||
// Assume the name has to be escaped and start copying while scanning.
|
||||
bool escaped = false;
|
||||
*v++ = '\\';
|
||||
for (const char *s = sta_name; *s ; s++) {
|
||||
char ch = s[0];
|
||||
if (ch == escape) {
|
||||
char next_ch = s[1];
|
||||
if (next_ch == escape) {
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
vstringAppend(verilog_name, verilog_name_end, v, next_ch);
|
||||
escaped_name += ch;
|
||||
escaped_name += next_ch;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
|
|
@ -144,46 +130,45 @@ staToVerilog2(const char *sta_name,
|
|||
if ((!(isalnum(ch) || ch == '_') && !is_brkt)
|
||||
|| is_brkt)
|
||||
escaped = true;
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
escaped_name += ch;
|
||||
}
|
||||
}
|
||||
if (escaped) {
|
||||
// Add a terminating space.
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ' ');
|
||||
vstringAppend(verilog_name, verilog_name_end, v, '\0');
|
||||
return verilog_name;
|
||||
escaped_name += ' ';
|
||||
return escaped_name;
|
||||
}
|
||||
else
|
||||
return sta_name;
|
||||
return string(sta_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *
|
||||
string
|
||||
moduleVerilogToSta(const char *module_name)
|
||||
{
|
||||
return verilogToSta(module_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
instanceVerilogToSta(const char *inst_name)
|
||||
{
|
||||
return verilogToSta(inst_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
netVerilogToSta(const char *net_name)
|
||||
{
|
||||
return verilogToSta(net_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
portVerilogToSta(const char *port_name)
|
||||
{
|
||||
return verilogToSta(port_name);
|
||||
}
|
||||
|
||||
static const char *
|
||||
static string
|
||||
verilogToSta(const char *verilog_name)
|
||||
{
|
||||
if (verilog_name && verilog_name[0] == '\\') {
|
||||
|
|
@ -197,11 +182,7 @@ verilogToSta(const char *verilog_name)
|
|||
size_t verilog_name_length = strlen(verilog_name);
|
||||
if (verilog_name[verilog_name_length - 1] == ' ')
|
||||
verilog_name_length--;
|
||||
// +1 for \0, +2 for escaping brackets.
|
||||
size_t sta_name_length = verilog_name_length + 1;
|
||||
char *sta_name = makeTmpString(sta_name_length);
|
||||
char *sta_name_end = &sta_name[sta_name_length];
|
||||
char *s = sta_name;
|
||||
string sta_name;
|
||||
for (size_t i = 0; i < verilog_name_length; i++) {
|
||||
char ch = verilog_name[i];
|
||||
if (ch == bus_brkt_left
|
||||
|
|
@ -209,33 +190,13 @@ verilogToSta(const char *verilog_name)
|
|||
|| ch == divider
|
||||
|| ch == escape)
|
||||
// Escape bus brackets, dividers and escapes.
|
||||
vstringAppend(sta_name, sta_name_end, s, escape);
|
||||
vstringAppend(sta_name, sta_name_end, s, ch);
|
||||
sta_name += escape;
|
||||
sta_name += ch;
|
||||
}
|
||||
vstringAppend(sta_name, sta_name_end, s, '\0');
|
||||
return sta_name;
|
||||
}
|
||||
else
|
||||
return verilog_name;
|
||||
}
|
||||
|
||||
// Append ch to str at insert. Resize str if necessary.
|
||||
static inline void
|
||||
vstringAppend(char *&str,
|
||||
char *&str_end,
|
||||
char *&insert,
|
||||
char ch)
|
||||
{
|
||||
if (insert == str_end) {
|
||||
size_t length = str_end - str;
|
||||
size_t length2 = length * 2;
|
||||
char *new_str = makeTmpString(length2);
|
||||
strncpy(new_str, str, length);
|
||||
str = new_str;
|
||||
str_end = &str[length2];
|
||||
insert = &str[length];
|
||||
}
|
||||
*insert++ = ch;
|
||||
return string(verilog_name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -321,6 +321,7 @@ PropActivityVisitor::PropActivityVisitor(Power *power,
|
|||
BfsFwdIterator *bfs) :
|
||||
StaState(power),
|
||||
visited_regs_(network_),
|
||||
max_change_(0.0),
|
||||
power_(power),
|
||||
bfs_(bfs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,14 +131,15 @@ ReadVcdActivities::setVarActivity(VcdVar *var,
|
|||
string &var_name,
|
||||
const VcdValues &var_values)
|
||||
{
|
||||
const char *sta_name = netVerilogToSta(var_name.c_str());
|
||||
string sta_name = netVerilogToSta(var_name.c_str());
|
||||
if (var->width() == 1)
|
||||
setVarActivity(sta_name, var_values, 0);
|
||||
setVarActivity(sta_name.c_str(), var_values, 0);
|
||||
else {
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int from, to;
|
||||
parseBusRange(sta_name, '[', ']', '\\',
|
||||
bus_name, from, to);
|
||||
parseBusRange(sta_name.c_str(), '[', ']', '\\',
|
||||
is_bus, bus_name, from, to);
|
||||
int value_bit = 0;
|
||||
if (to < from) {
|
||||
for (int bus_bit = to; bus_bit <= from; bus_bit++) {
|
||||
|
|
@ -160,7 +161,6 @@ ReadVcdActivities::setVarActivity(VcdVar *var,
|
|||
value_bit++;
|
||||
}
|
||||
}
|
||||
stringDelete(bus_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,10 @@ celltype:
|
|||
;
|
||||
|
||||
cell_instance:
|
||||
'(' INSTANCE ')' { sta::sdf_reader->setInstance(NULL); }
|
||||
| '(' INSTANCE '*' ')' { sta::sdf_reader->setInstanceWildcard(); }
|
||||
'(' INSTANCE ')'
|
||||
{ sta::sdf_reader->setInstance(NULL); }
|
||||
| '(' INSTANCE '*' ')'
|
||||
{ sta::sdf_reader->setInstanceWildcard(); }
|
||||
| '(' INSTANCE path ')'
|
||||
{ sta::sdf_reader->setInstance($3); }
|
||||
;
|
||||
|
|
@ -266,7 +268,10 @@ port:
|
|||
ID
|
||||
{ $$ = sta::sdf_reader->unescaped($1); }
|
||||
| ID '[' DNUMBER ']'
|
||||
{ $$ = sta::stringPrint("%s[%d]", sta::sdf_reader->unescaped($1), $3); }
|
||||
{ const char *bus_name = sta::sdf_reader->unescaped($1);
|
||||
$$ = sta::stringPrint("%s[%d]", bus_name, $3);
|
||||
sta::stringDelete(bus_name);
|
||||
}
|
||||
;
|
||||
|
||||
port_instance:
|
||||
|
|
@ -292,7 +297,7 @@ port_tchk:
|
|||
| '(' COND EXPR_ID_CLOSE
|
||||
{ $$ = sta::sdf_reader->makeCondPortSpec($3); }
|
||||
| '(' COND EXPR_OPEN port_transition port_instance ')' ')'
|
||||
{ $$ = sta::sdf_reader->makePortSpec($4, $5, $3); sta::stringDelete($3); }
|
||||
{ $$ = sta::sdf_reader->makePortSpec($4, $5, $3); }
|
||||
;
|
||||
|
||||
value:
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ SdfReader::interconnect(const char *from_pin_name,
|
|||
sdfWarn(186, "pin %s not found.", to_pin_name);
|
||||
}
|
||||
}
|
||||
stringDelete(from_pin_name);
|
||||
stringDelete(to_pin_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -234,6 +236,7 @@ SdfReader::port(const char *to_pin_name,
|
|||
}
|
||||
}
|
||||
}
|
||||
stringDelete(to_pin_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -312,6 +315,7 @@ SdfReader::setInstance(const char *instance_name)
|
|||
}
|
||||
else
|
||||
instance_ = nullptr;
|
||||
stringDelete(instance_name);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -399,6 +403,7 @@ SdfReader::iopath(SdfPortSpec *from_edge,
|
|||
}
|
||||
}
|
||||
}
|
||||
stringDelete(to_port_name);
|
||||
deletePortSpec(from_edge);
|
||||
deleteTripleSeq(triples);
|
||||
stringDelete(cond);
|
||||
|
|
@ -688,6 +693,7 @@ SdfReader::device(const char *to_port_name,
|
|||
setDevicePinDelays(to_pin, triples);
|
||||
}
|
||||
}
|
||||
stringDelete(to_port_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -822,7 +828,10 @@ SdfReader::makePortSpec(Transition *tr,
|
|||
const char *port,
|
||||
const char *cond)
|
||||
{
|
||||
return new SdfPortSpec(tr, port, cond);
|
||||
SdfPortSpec *port_spec = new SdfPortSpec(tr, port, cond);
|
||||
stringDelete(port);
|
||||
stringDelete(cond);
|
||||
return port_spec;
|
||||
}
|
||||
|
||||
SdfPortSpec *
|
||||
|
|
@ -837,9 +846,9 @@ SdfReader::makeCondPortSpec(const char *cond_port)
|
|||
auto cond_end = cond_port1.find_last_not_of(" ", port_idx);
|
||||
if (cond_end != cond_port1.npos) {
|
||||
string cond1 = cond_port1.substr(0, cond_end + 1);
|
||||
SdfPortSpec *port_spec = makePortSpec(Transition::riseFall(),
|
||||
port1.c_str(),
|
||||
cond1.c_str());
|
||||
SdfPortSpec *port_spec = new SdfPortSpec(Transition::riseFall(),
|
||||
port1.c_str(),
|
||||
cond1.c_str());
|
||||
stringDelete(cond_port);
|
||||
return port_spec;
|
||||
}
|
||||
|
|
@ -919,7 +928,7 @@ SdfReader::unescaped(const char *token)
|
|||
{
|
||||
char path_escape = network_->pathEscape();
|
||||
char path_divider = network_->pathDivider();
|
||||
char *unescaped = makeTmpString(strlen(token) + 1);
|
||||
char *unescaped = new char[strlen(token) + 1];
|
||||
char *u = unescaped;
|
||||
size_t token_length = strlen(token);
|
||||
|
||||
|
|
@ -962,10 +971,12 @@ char *
|
|||
SdfReader::makePath(const char *head,
|
||||
const char *tail)
|
||||
{
|
||||
char *path = stringPrintTmp("%s%c%s",
|
||||
head,
|
||||
network_->pathDivider(),
|
||||
tail);
|
||||
char *path = stringPrint("%s%c%s",
|
||||
head,
|
||||
network_->pathDivider(),
|
||||
tail);
|
||||
sta::stringDelete(head);
|
||||
sta::stringDelete(tail);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
|
|||
105
sdf/SdfWriter.cc
105
sdf/SdfWriter.cc
|
|
@ -100,10 +100,10 @@ protected:
|
|||
void writeSdfTriple(float min,
|
||||
float max);
|
||||
void writeSdfDelay(double delay);
|
||||
char *sdfPortName(const Pin *pin);
|
||||
char *sdfPathName(const Pin *pin);
|
||||
char *sdfPathName(const Instance *inst);
|
||||
char *sdfName(const Instance *inst);
|
||||
string sdfPortName(const Pin *pin);
|
||||
string sdfPathName(const Pin *pin);
|
||||
string sdfPathName(const Instance *inst);
|
||||
string sdfName(const Instance *inst);
|
||||
|
||||
private:
|
||||
char sdf_divider_;
|
||||
|
|
@ -310,9 +310,11 @@ SdfWriter::writeInterconnectFromPin(Pin *drvr_pin)
|
|||
Edge *edge = edge_iter.next();
|
||||
if (edge->isWire()) {
|
||||
Pin *load_pin = edge->to(graph_)->pin();
|
||||
string drvr_pin_name = sdfPathName(drvr_pin);
|
||||
string load_pin_name = sdfPathName(load_pin);
|
||||
gzprintf(stream_, " (INTERCONNECT %s %s ",
|
||||
sdfPathName(drvr_pin),
|
||||
sdfPathName(load_pin));
|
||||
drvr_pin_name.c_str(),
|
||||
load_pin_name.c_str());
|
||||
writeArcDelays(edge);
|
||||
gzprintf(stream_, ")\n");
|
||||
}
|
||||
|
|
@ -340,7 +342,8 @@ SdfWriter::writeInstHeader(const Instance *inst)
|
|||
{
|
||||
gzprintf(stream_, " (CELL\n");
|
||||
gzprintf(stream_, " (CELLTYPE \"%s\")\n", network_->cellName(inst));
|
||||
gzprintf(stream_, " (INSTANCE %s)\n", sdfPathName(inst));
|
||||
string inst_name = sdfPathName(inst);
|
||||
gzprintf(stream_, " (INSTANCE %s)\n", inst_name.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -384,9 +387,11 @@ SdfWriter::writeIopaths(const Instance *inst,
|
|||
gzprintf(stream_, " (COND %s\n", sdf_cond);
|
||||
gzprintf(stream_, " ");
|
||||
}
|
||||
gzprintf(stream_, " (IOPATH %s %s ",
|
||||
sdfPortName(from_pin),
|
||||
sdfPortName(to_pin));
|
||||
string from_pin_name = sdfPortName(from_pin);
|
||||
string to_pin_name = sdfPortName(to_pin);
|
||||
gzprintf(stream_, " (IOPATH %s %s ",
|
||||
from_pin_name.c_str(),
|
||||
to_pin_name.c_str());
|
||||
writeArcDelays(edge);
|
||||
if (sdf_cond)
|
||||
gzprintf(stream_, ")");
|
||||
|
|
@ -651,12 +656,14 @@ SdfWriter::writeCheck(Edge *edge,
|
|||
if (sdf_cond_start)
|
||||
gzprintf(stream_, "(COND %s ", sdf_cond_start);
|
||||
|
||||
if (use_data_edge)
|
||||
string to_pin_name = sdfPortName(to_pin);
|
||||
if (use_data_edge) {
|
||||
gzprintf(stream_, "(%s %s)",
|
||||
sdfEdge(arc->toEdge()),
|
||||
sdfPortName(to_pin));
|
||||
to_pin_name.c_str());
|
||||
}
|
||||
else
|
||||
gzprintf(stream_, "%s", sdfPortName(to_pin));
|
||||
gzprintf(stream_, "%s", to_pin_name.c_str());
|
||||
|
||||
if (sdf_cond_start)
|
||||
gzprintf(stream_, ")");
|
||||
|
|
@ -666,12 +673,13 @@ SdfWriter::writeCheck(Edge *edge,
|
|||
if (sdf_cond_end)
|
||||
gzprintf(stream_, "(COND %s ", sdf_cond_end);
|
||||
|
||||
string from_pin_name = sdfPortName(from_pin);
|
||||
if (use_clk_edge)
|
||||
gzprintf(stream_, "(%s %s)",
|
||||
sdfEdge(arc->fromEdge()),
|
||||
sdfPortName(from_pin));
|
||||
from_pin_name.c_str());
|
||||
else
|
||||
gzprintf(stream_, "%s", sdfPortName(from_pin));
|
||||
gzprintf(stream_, "%s", from_pin_name.c_str());
|
||||
|
||||
if (sdf_cond_end)
|
||||
gzprintf(stream_, ")");
|
||||
|
|
@ -691,9 +699,10 @@ SdfWriter::writeWidthCheck(const Pin *pin,
|
|||
float min_width,
|
||||
float max_width)
|
||||
{
|
||||
string pin_name = sdfPortName(pin);
|
||||
gzprintf(stream_, " (WIDTH (%s %s) ",
|
||||
sdfEdge(hi_low->asTransition()),
|
||||
sdfPortName(pin));
|
||||
pin_name.c_str());
|
||||
writeSdfTriple(min_width, max_width);
|
||||
gzprintf(stream_, ")\n");
|
||||
}
|
||||
|
|
@ -702,8 +711,8 @@ void
|
|||
SdfWriter::writePeriodCheck(const Pin *pin,
|
||||
float min_period)
|
||||
{
|
||||
gzprintf(stream_, " (PERIOD %s ",
|
||||
sdfPortName(pin));
|
||||
string pin_name = sdfPortName(pin);
|
||||
gzprintf(stream_, " (PERIOD %s ", pin_name.c_str());
|
||||
writeSdfTriple(min_period, min_period);
|
||||
gzprintf(stream_, ")\n");
|
||||
}
|
||||
|
|
@ -720,81 +729,68 @@ SdfWriter::sdfEdge(const Transition *tr)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
char *
|
||||
string
|
||||
SdfWriter::sdfPathName(const Pin *pin)
|
||||
{
|
||||
Instance *inst = network_->instance(pin);
|
||||
if (network_->isTopInstance(inst))
|
||||
return sdfPortName(pin);
|
||||
else {
|
||||
char *inst_path = sdfPathName(inst);
|
||||
const char *port_name = sdfPortName(pin);
|
||||
size_t length = strlen(inst_path) + 1 + strlen(port_name) + 1;
|
||||
char *sdf_name = makeTmpString(length);
|
||||
snprintf(sdf_name, length, "%s%c%s", inst_path, sdf_divider_, port_name);
|
||||
string inst_path = sdfPathName(inst);
|
||||
string port_name = sdfPortName(pin);
|
||||
string sdf_name = inst_path;
|
||||
sdf_name += sdf_divider_;
|
||||
sdf_name += port_name;
|
||||
return sdf_name;
|
||||
}
|
||||
}
|
||||
|
||||
// Based on Network::pathName.
|
||||
char *
|
||||
string
|
||||
SdfWriter::sdfPathName(const Instance *instance)
|
||||
{
|
||||
InstanceSeq inst_path;
|
||||
network_->path(instance, inst_path);
|
||||
size_t name_length = 0;
|
||||
InstanceSeq::Iterator path_iter1(inst_path);
|
||||
while (path_iter1.hasNext()) {
|
||||
const Instance *inst = path_iter1.next();
|
||||
name_length += strlen(sdfName(inst)) + 1;
|
||||
}
|
||||
char *path_name = makeTmpString(name_length);
|
||||
char *path_ptr = path_name;
|
||||
// Top instance has null string name, so terminate the string here.
|
||||
*path_name = '\0';
|
||||
while (inst_path.size()) {
|
||||
string path_name;
|
||||
while (!inst_path.empty()) {
|
||||
const Instance *inst = inst_path.back();
|
||||
const char *inst_name = sdfName(inst);
|
||||
strcpy(path_ptr, inst_name);
|
||||
path_ptr += strlen(inst_name);
|
||||
string inst_name = sdfName(inst);
|
||||
path_name += inst_name;
|
||||
inst_path.pop_back();
|
||||
if (inst_path.size())
|
||||
*path_ptr++ = sdf_divider_;
|
||||
*path_ptr = '\0';
|
||||
if (!inst_path.empty())
|
||||
path_name += sdf_divider_;
|
||||
}
|
||||
return path_name;
|
||||
}
|
||||
|
||||
// Escape for non-alpha numeric characters.
|
||||
char *
|
||||
string
|
||||
SdfWriter::sdfName(const Instance *inst)
|
||||
{
|
||||
const char *name = network_->name(inst);
|
||||
char *sdf_name = makeTmpString(strlen(name) * 2 + 1);
|
||||
string sdf_name;
|
||||
const char *p = name;
|
||||
char *s = sdf_name;
|
||||
while (*p) {
|
||||
char ch = *p;
|
||||
// Ignore sta escapes.
|
||||
if (ch != network_escape_) {
|
||||
if (!(isalnum(ch) || ch == '_'))
|
||||
// Insert escape.
|
||||
*s++ = sdf_escape_;
|
||||
*s++ = ch;
|
||||
sdf_name += sdf_escape_;
|
||||
sdf_name += ch;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*s = '\0';
|
||||
return sdf_name;
|
||||
}
|
||||
|
||||
char *
|
||||
string
|
||||
SdfWriter::sdfPortName(const Pin *pin)
|
||||
{
|
||||
const char *name = network_->portName(pin);
|
||||
size_t name_length = strlen(name);
|
||||
char *sdf_name = makeTmpString(name_length * 2 + 1);
|
||||
char *s = sdf_name;
|
||||
string sdf_name;
|
||||
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
|
|
@ -809,18 +805,17 @@ SdfWriter::sdfPortName(const Pin *pin)
|
|||
char ch = name[i];
|
||||
if (ch == network_escape_) {
|
||||
// Copy escape and escaped char.
|
||||
*s++ = sdf_escape_;
|
||||
*s++ = name[++i];
|
||||
sdf_name += sdf_escape_;
|
||||
sdf_name += name[++i];
|
||||
}
|
||||
else {
|
||||
if (!(isalnum(ch) || ch == '_')
|
||||
&& !(i >= bus_index && (ch == bus_brkt_right || ch == bus_brkt_left)))
|
||||
// Insert escape.
|
||||
*s++ = sdf_escape_;
|
||||
*s++ = ch;
|
||||
sdf_name += sdf_escape_;
|
||||
sdf_name += ch;
|
||||
}
|
||||
}
|
||||
*s = '\0';
|
||||
return sdf_name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,34 +113,35 @@ ClkInfo::asString(const StaState *sta) const
|
|||
{
|
||||
Network *network = sta->network();
|
||||
Corners *corners = sta->corners();
|
||||
string str;
|
||||
string result;
|
||||
|
||||
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
|
||||
str += stringPrintTmp("%s/%d ",
|
||||
path_ap->pathMinMax()->asString(),
|
||||
path_ap_index_);
|
||||
result += path_ap->pathMinMax()->asString();
|
||||
result += "/";
|
||||
result += std::to_string(path_ap_index_);
|
||||
|
||||
if (clk_edge_)
|
||||
str += clk_edge_->name();
|
||||
result += clk_edge_->name();
|
||||
else
|
||||
str += "unclocked";
|
||||
result += "unclocked";
|
||||
|
||||
if (clk_src_) {
|
||||
str += " clk_src ";
|
||||
str += network->pathName(clk_src_);
|
||||
result += " clk_src ";
|
||||
result += network->pathName(clk_src_);
|
||||
}
|
||||
|
||||
if (!crpr_clk_path_.isNull()) {
|
||||
const Pin *crpr_clk_pin = crpr_clk_path_.vertex(sta)->pin();
|
||||
str += " crpr_pin ";
|
||||
str += network->pathName(crpr_clk_pin);
|
||||
result += " crpr_pin ";
|
||||
result += network->pathName(crpr_clk_pin);
|
||||
}
|
||||
|
||||
if (is_gen_clk_src_path_)
|
||||
str += " genclk";
|
||||
result += " genclk";
|
||||
|
||||
char *result = makeTmpString(str.size() + 1);
|
||||
strcpy(result, str.c_str());
|
||||
return result;
|
||||
char *tmp = makeTmpString(result.size() + 1);
|
||||
strcpy(tmp, result.c_str());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const Clock *
|
||||
|
|
|
|||
|
|
@ -558,13 +558,14 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin,
|
|||
Slew in_slew = graph_->slew(gate_in_vertex,
|
||||
drvr_arc->fromEdge()->asRiseFall(),
|
||||
dcalc_ap->index());
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
TimingModel *drvr_model = drvr_arc->cornerArc(lib_index)->model(op_cond);
|
||||
GateTableModel *drvr_gate_model = dynamic_cast<GateTableModel*>(drvr_model);
|
||||
if (drvr_gate_model) {
|
||||
float output_load_cap = graph_delay_calc_->loadCap(output_pin, dcalc_ap);
|
||||
ArcDelay drvr_self_delay;
|
||||
Slew drvr_self_slew;
|
||||
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew,
|
||||
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew1,
|
||||
output_load_cap, 0.0, false,
|
||||
drvr_self_delay, drvr_self_slew);
|
||||
|
||||
|
|
@ -579,12 +580,13 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin,
|
|||
// get slew from driver input pin
|
||||
ArcDelay gate_delay;
|
||||
Slew gate_slew;
|
||||
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew,
|
||||
drvr_gate_model->gateDelay(drvr_cell, pvt, in_slew1,
|
||||
load_cap, 0.0, false,
|
||||
gate_delay, gate_slew);
|
||||
// Remove the self delay driving the output pin net load cap.
|
||||
load_values->push_back(delay + gate_delay - drvr_self_delay);
|
||||
slew_values->push_back(gate_slew);
|
||||
load_values->push_back(delayAsFloat(delay + gate_delay
|
||||
- drvr_self_delay));
|
||||
slew_values->push_back(delayAsFloat(gate_slew));
|
||||
}
|
||||
|
||||
FloatSeq *axis_values = new FloatSeq(*drvr_axis_values);
|
||||
|
|
|
|||
|
|
@ -1028,7 +1028,9 @@ getProperty(Edge *edge,
|
|||
auto graph = sta->graph();
|
||||
const char *from = edge->from(graph)->name(network);
|
||||
const char *to = edge->to(graph)->name(network);
|
||||
return PropertyValue(stringPrintTmp("%s -> %s", from, to));
|
||||
string full_name;
|
||||
stringPrint(full_name, "%s -> %s", from, to);
|
||||
return PropertyValue(full_name);
|
||||
}
|
||||
if (stringEqual(property, "delay_min_fall"))
|
||||
return edgeDelayProperty(edge, RiseFall::fall(), MinMax::min(), sta);
|
||||
|
|
|
|||
|
|
@ -2657,7 +2657,7 @@ Sta::endpointViolationCount(const MinMax *min_max)
|
|||
{
|
||||
int violations = 0;
|
||||
for (Vertex *end : *search_->endpoints()) {
|
||||
if (vertexSlack(end, min_max) < 0.0)
|
||||
if (delayLess(vertexSlack(end, min_max), 0.0, this))
|
||||
violations++;
|
||||
}
|
||||
return violations;
|
||||
|
|
@ -2815,7 +2815,8 @@ Sta::pinArrival(const Pin *pin,
|
|||
if (bidirect_vertex) {
|
||||
Arrival arrival1 = vertexArrival(bidirect_vertex, rf, clk_edge_wildcard,
|
||||
nullptr, min_max);
|
||||
arrival = min_max->minMax(arrival, arrival1);
|
||||
if (delayLess(arrival1, arrival, this))
|
||||
arrival = arrival1;
|
||||
}
|
||||
return arrival;
|
||||
}
|
||||
|
|
@ -3256,7 +3257,7 @@ Sta::worstSlack(const Corner *corner,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
string *
|
||||
string
|
||||
Sta::reportDelayCalc(Edge *edge,
|
||||
TimingArc *arc,
|
||||
const Corner *corner,
|
||||
|
|
|
|||
|
|
@ -94,83 +94,84 @@ Tag::asString(bool report_index,
|
|||
{
|
||||
const Network *network = sta->network();
|
||||
const Corners *corners = sta->corners();
|
||||
string str;
|
||||
string result;
|
||||
|
||||
if (report_index)
|
||||
str += stringPrintTmp("%4d ", index_);
|
||||
result += std::to_string(index_);
|
||||
|
||||
if (report_rf_min_max) {
|
||||
const RiseFall *rf = transition();
|
||||
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
|
||||
str += stringPrintTmp("%s %s/%d ",
|
||||
rf->asString(),
|
||||
path_ap->pathMinMax()->asString(),
|
||||
path_ap_index_);
|
||||
result += rf->asString();
|
||||
result += " ";
|
||||
result += path_ap->pathMinMax()->asString();
|
||||
result += "/";
|
||||
result += std::to_string(path_ap_index_);
|
||||
}
|
||||
|
||||
const ClockEdge *clk_edge = clkEdge();
|
||||
if (clk_edge)
|
||||
str += clk_edge->name();
|
||||
result += clk_edge->name();
|
||||
else
|
||||
str += "unclocked";
|
||||
result += "unclocked";
|
||||
|
||||
bool is_genclk_src = clk_info_->isGenClkSrcPath();
|
||||
if (is_clk_ || is_genclk_src) {
|
||||
str += " (";
|
||||
result += " (";
|
||||
if (is_clk_) {
|
||||
str += "clock";
|
||||
result += "clock";
|
||||
if (clk_info_->isPropagated())
|
||||
str += " prop";
|
||||
result += " prop";
|
||||
else
|
||||
str += " ideal";
|
||||
result += " ideal";
|
||||
if (is_genclk_src)
|
||||
str += " ";
|
||||
result += " ";
|
||||
}
|
||||
if (clk_info_->isGenClkSrcPath())
|
||||
str += "genclk";
|
||||
str += ")";
|
||||
result += "genclk";
|
||||
result += ")";
|
||||
}
|
||||
|
||||
const Pin *clk_src = clkSrc();
|
||||
if (clk_src) {
|
||||
str += " clk_src ";
|
||||
str += network->pathName(clk_src);
|
||||
result += " clk_src ";
|
||||
result += network->pathName(clk_src);
|
||||
}
|
||||
|
||||
const PathVertex crpr_clk_path(clk_info_->crprClkPath(), sta);
|
||||
if (!crpr_clk_path.isNull()) {
|
||||
str += " crpr_pin ";
|
||||
str += network->pathName(crpr_clk_path.pin(sta));
|
||||
result += " crpr_pin ";
|
||||
result += network->pathName(crpr_clk_path.pin(sta));
|
||||
}
|
||||
|
||||
if (input_delay_) {
|
||||
str += " input ";
|
||||
str += network->pathName(input_delay_->pin());
|
||||
result += " input ";
|
||||
result += network->pathName(input_delay_->pin());
|
||||
}
|
||||
|
||||
if (is_segment_start_)
|
||||
str += " segment_start";
|
||||
result += " segment_start";
|
||||
|
||||
if (states_) {
|
||||
for (ExceptionState *state : *states_) {
|
||||
ExceptionPath *exception = state->exception();
|
||||
str += " ";
|
||||
str += exception->asString(network);
|
||||
result += " ";
|
||||
result += exception->asString(network);
|
||||
if (state->nextThru()) {
|
||||
str += " (next thru ";
|
||||
str += state->nextThru()->asString(network);
|
||||
str += ")";
|
||||
result += " (next thru ";
|
||||
result += state->nextThru()->asString(network);
|
||||
result += ")";
|
||||
}
|
||||
else {
|
||||
if (exception->thrus() != nullptr)
|
||||
str += " (thrus complete)";
|
||||
result += " (thrus complete)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *result = makeTmpString(str.size() + 1);
|
||||
strcpy(result, str.c_str());
|
||||
return result;
|
||||
char *tmp = makeTmpString(result.size() + 1);
|
||||
strcpy(tmp, result.c_str());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const RiseFall *
|
||||
|
|
|
|||
|
|
@ -289,13 +289,13 @@ proc report_wrt_clk { vertex what clk clk_rf } {
|
|||
}
|
||||
}
|
||||
|
||||
proc rise_fall_short_name { tr } {
|
||||
if { $tr eq "rise" } {
|
||||
proc rise_fall_short_name { rf } {
|
||||
if { $rf == "rise" } {
|
||||
return [rise_short_name]
|
||||
} elseif { $tr eq "fall" } {
|
||||
} elseif { $rf == "fall" } {
|
||||
return [fall_short_name]
|
||||
} else {
|
||||
error "unknown transition name $tr"
|
||||
error "unknown transition name $rf"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -402,6 +402,13 @@ using namespace sta;
|
|||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// String that is deleted after crossing over to tcland.
|
||||
%typemap(out) string {
|
||||
string &str = $1;
|
||||
// String is volatile because it is deleted.
|
||||
Tcl_SetResult(interp, const_cast<char*>(str.c_str()), TCL_VOLATILE);
|
||||
}
|
||||
|
||||
// String that is deleted after crossing over to tcland.
|
||||
%typemap(out) TmpString* {
|
||||
string *str = $1;
|
||||
|
|
@ -5953,7 +5960,7 @@ requireds_clk(const RiseFall *rf,
|
|||
clk_edge = clk->edge(clk_rf);
|
||||
for (auto path_ap : sta->corners()->pathAnalysisPts()) {
|
||||
requireds.push_back(delayAsFloat(sta->vertexRequired(self, rf, clk_edge,
|
||||
path_ap)));
|
||||
path_ap)));
|
||||
}
|
||||
return requireds;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ proc parse_args {} {
|
|||
}
|
||||
|
||||
proc expand_tests { argv } {
|
||||
global test_groups
|
||||
global test_groups errors
|
||||
|
||||
set tests {}
|
||||
foreach arg $argv {
|
||||
|
|
@ -111,7 +111,8 @@ proc expand_tests { argv } {
|
|||
lappend tests $arg
|
||||
} else {
|
||||
puts "Error: test $arg not found."
|
||||
}
|
||||
incr errors(no_cmd)
|
||||
}
|
||||
}
|
||||
return $tests
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,18 @@ PatternMatch::PatternMatch(const char *pattern,
|
|||
compileRegexp();
|
||||
}
|
||||
|
||||
PatternMatch::PatternMatch(const string &pattern,
|
||||
const PatternMatch *inherit_from) :
|
||||
pattern_(pattern.c_str()),
|
||||
is_regexp_(inherit_from->is_regexp_),
|
||||
nocase_(inherit_from->nocase_),
|
||||
interp_(inherit_from->interp_),
|
||||
regexp_(nullptr)
|
||||
{
|
||||
if (is_regexp_)
|
||||
compileRegexp();
|
||||
}
|
||||
|
||||
void
|
||||
PatternMatch::compileRegexp()
|
||||
{
|
||||
|
|
@ -89,6 +101,12 @@ PatternMatch::hasWildcards() const
|
|||
return patternWildcards(pattern_);
|
||||
}
|
||||
|
||||
bool
|
||||
PatternMatch::match(const string &str) const
|
||||
{
|
||||
return match(str.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
PatternMatch::match(const char *str) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ inst_named_pins:
|
|||
inst_named_pin:
|
||||
// Scalar port.
|
||||
'.' ID '(' ')'
|
||||
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalarNet($2, NULL); }
|
||||
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalarNet($2); }
|
||||
| '.' ID '(' ID ')'
|
||||
{ $$ = sta::verilog_reader->makeNetNamedPortRefScalarNet($2, $4); }
|
||||
| '.' ID '(' ID '[' INT ']' ')'
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ namespace sta {
|
|||
VerilogReader *verilog_reader;
|
||||
static const char *unconnected_net_name = reinterpret_cast<const char*>(1);
|
||||
|
||||
static const char *
|
||||
verilogBusBitNameTmp(const char *bus_name,
|
||||
int index);
|
||||
static string
|
||||
verilogBusBitName(const char *bus_name,
|
||||
int index);
|
||||
static int
|
||||
hierarchyLevel(Net *net,
|
||||
Network *network);
|
||||
|
|
@ -255,17 +255,18 @@ VerilogReader::makeModule(const char *module_vname,
|
|||
VerilogStmtSeq *stmts,
|
||||
int line)
|
||||
{
|
||||
const char *module_name = moduleVerilogToSta(module_vname);
|
||||
Cell *cell = network_->findCell(library_, module_name);
|
||||
string module_name = moduleVerilogToSta(module_vname);
|
||||
Cell *cell = network_->findCell(library_, module_name.c_str());
|
||||
if (cell) {
|
||||
VerilogModule *module = module_map_[cell];
|
||||
delete module;
|
||||
module_map_.erase(cell);
|
||||
network_->deleteCell(cell);
|
||||
}
|
||||
VerilogModule *module = new VerilogModule(module_name, ports, stmts,
|
||||
VerilogModule *module = new VerilogModule(module_name.c_str(),
|
||||
ports, stmts,
|
||||
filename_, line, this);
|
||||
cell = network_->makeCell(library_, module_name, false, filename_);
|
||||
cell = network_->makeCell(library_, module_name.c_str(), false, filename_);
|
||||
module_map_[cell] = module;
|
||||
makeCellPorts(cell, module, ports);
|
||||
module_count_++;
|
||||
|
|
@ -300,26 +301,25 @@ VerilogReader::makeCellPorts(Cell *cell,
|
|||
VerilogModule *module,
|
||||
VerilogNetSeq *ports)
|
||||
{
|
||||
StringSet port_names;
|
||||
set<string> port_names;
|
||||
for (VerilogNet *mod_port : *ports) {
|
||||
const char *port_name = mod_port->name();
|
||||
if (port_names.findKey(port_name) == nullptr) {
|
||||
port_names.insert(stringCopy(port_name));
|
||||
const string &port_name = mod_port->name();
|
||||
if (port_names.find(port_name) == port_names.end()) {
|
||||
port_names.insert(port_name);
|
||||
if (mod_port->isNamed()) {
|
||||
if (mod_port->isNamedPortRef())
|
||||
makeNamedPortRefCellPorts(cell, module, mod_port, port_names);
|
||||
else
|
||||
makeCellPort(cell, module, mod_port->name());
|
||||
makeCellPort(cell, module, mod_port->name().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
warn(165, module->filename(), module->line(),
|
||||
"module %s repeated port name %s.",
|
||||
module->name(),
|
||||
port_name);
|
||||
port_name.c_str());
|
||||
}
|
||||
checkModuleDcls(module, port_names);
|
||||
deleteContents(&port_names);
|
||||
}
|
||||
|
||||
Port *
|
||||
|
|
@ -351,25 +351,25 @@ void
|
|||
VerilogReader::makeNamedPortRefCellPorts(Cell *cell,
|
||||
VerilogModule *module,
|
||||
VerilogNet *mod_port,
|
||||
StringSet &port_names)
|
||||
set<string> &port_names)
|
||||
{
|
||||
PortSeq *member_ports = new PortSeq;
|
||||
VerilogNetNameIterator *net_name_iter = mod_port->nameIterator(module,this);
|
||||
while (net_name_iter->hasNext()) {
|
||||
const char *net_name = net_name_iter->next();
|
||||
port_names.insert(stringCopy(net_name));
|
||||
port_names.insert(net_name);
|
||||
Port *port = makeCellPort(cell, module, net_name);
|
||||
member_ports->push_back(port);
|
||||
}
|
||||
delete net_name_iter;
|
||||
// Note that the bundle does NOT have a port declaration.
|
||||
network_->makeBundlePort(cell, mod_port->name(), member_ports);
|
||||
network_->makeBundlePort(cell, mod_port->name().c_str(), member_ports);
|
||||
}
|
||||
|
||||
// Make sure each declaration appears in the module port list.
|
||||
void
|
||||
VerilogReader::checkModuleDcls(VerilogModule *module,
|
||||
StringSet &port_names)
|
||||
set<string> &port_names)
|
||||
{
|
||||
VerilogDclMap::ConstIterator dcl_iter(module->declarationMap());
|
||||
while (dcl_iter.hasNext()) {
|
||||
|
|
@ -380,7 +380,7 @@ VerilogReader::checkModuleDcls(VerilogModule *module,
|
|||
if (dir->isInput()
|
||||
|| dir->isOutput()
|
||||
|| dir->isBidirect()) {
|
||||
if (port_names.findKey(port_name) == nullptr)
|
||||
if (port_names.find(port_name) == port_names.end())
|
||||
linkWarn(197, module->filename(), module->line(),
|
||||
"module %s declared signal %s is not in the port list.",
|
||||
module->name(),
|
||||
|
|
@ -457,10 +457,10 @@ VerilogDclArg *
|
|||
VerilogReader::makeDclArg(const char *net_vname)
|
||||
{
|
||||
dcl_arg_count_++;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogDclArg *dcl =new VerilogDclArg(net_name);
|
||||
stringDelete(net_vname);
|
||||
return dcl;
|
||||
string net_name = netVerilogToSta(net_vname);
|
||||
VerilogDclArg *dcl =new VerilogDclArg(net_name.c_str());
|
||||
stringDelete(net_vname);
|
||||
return dcl;
|
||||
}
|
||||
|
||||
VerilogDclArg *
|
||||
|
|
@ -478,8 +478,9 @@ VerilogReader::makeNetPartSelect(const char *net_vname,
|
|||
net_part_select_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_bus_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPartSelect *select = new VerilogNetPartSelect(net_name, from_index,
|
||||
string net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPartSelect *select = new VerilogNetPartSelect(net_name.c_str(),
|
||||
from_index,
|
||||
to_index);
|
||||
stringDelete(net_vname);
|
||||
return select;
|
||||
|
|
@ -498,8 +499,8 @@ VerilogReader::makeNetScalar(const char *net_vname)
|
|||
net_scalar_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_scalar_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetScalar *scalar = new VerilogNetScalar(net_name);
|
||||
string net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetScalar *scalar = new VerilogNetScalar(net_name.c_str());
|
||||
stringDelete(net_vname);
|
||||
return scalar;
|
||||
}
|
||||
|
|
@ -511,8 +512,8 @@ VerilogReader::makeNetBitSelect(const char *net_vname,
|
|||
net_bit_select_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_bus_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetBitSelect *select = new VerilogNetBitSelect(net_name, index);
|
||||
string net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetBitSelect *select = new VerilogNetBitSelect(net_name.c_str(), index);
|
||||
stringDelete(net_vname);
|
||||
return select;
|
||||
}
|
||||
|
|
@ -532,9 +533,9 @@ VerilogReader::makeModuleInst(const char *module_vname,
|
|||
VerilogNetSeq *pins,
|
||||
const int line)
|
||||
{
|
||||
const char *module_name = moduleVerilogToSta(module_vname);
|
||||
const char *inst_name = instanceVerilogToSta(inst_vname);
|
||||
Cell *cell = network_->findAnyCell(module_name);
|
||||
string module_name = moduleVerilogToSta(module_vname);
|
||||
string inst_name = instanceVerilogToSta(inst_vname);
|
||||
Cell *cell = network_->findAnyCell(module_name.c_str());
|
||||
LibertyCell *liberty_cell = nullptr;
|
||||
if (cell)
|
||||
liberty_cell = network_->libertyCell(cell);
|
||||
|
|
@ -549,7 +550,7 @@ VerilogReader::makeModuleInst(const char *module_vname,
|
|||
for (VerilogNet *vnet : *pins) {
|
||||
VerilogNetPortRefScalarNet *vpin =
|
||||
dynamic_cast<VerilogNetPortRefScalarNet*>(vnet);
|
||||
const char *port_name = vpin->name();
|
||||
const char *port_name = vpin->name().c_str();
|
||||
const char *net_name = vpin->netName();
|
||||
// Steal the net name string.
|
||||
vpin->setNetName(nullptr);
|
||||
|
|
@ -569,11 +570,11 @@ VerilogReader::makeModuleInst(const char *module_vname,
|
|||
delete vpin;
|
||||
net_port_ref_scalar_net_count_--;
|
||||
}
|
||||
VerilogInst *inst = new VerilogLibertyInst(liberty_cell, inst_name,
|
||||
VerilogInst *inst = new VerilogLibertyInst(liberty_cell, inst_name.c_str(),
|
||||
net_names, line);
|
||||
delete pins;
|
||||
if (report_stmt_stats_) {
|
||||
inst_names_ += strlen(inst_name) + 1;
|
||||
inst_names_ += inst_name.size() + 1;
|
||||
inst_lib_count_++;
|
||||
inst_lib_net_arrays_ += port_count;
|
||||
}
|
||||
|
|
@ -582,10 +583,12 @@ VerilogReader::makeModuleInst(const char *module_vname,
|
|||
return inst;
|
||||
}
|
||||
else {
|
||||
VerilogInst *inst = new VerilogModuleInst(module_name, inst_name, pins, line);
|
||||
VerilogInst *inst = new VerilogModuleInst(module_name.c_str(),
|
||||
inst_name.c_str(),
|
||||
pins, line);
|
||||
if (report_stmt_stats_) {
|
||||
inst_module_names_ += strlen(module_name) + 1;
|
||||
inst_names_ += strlen(inst_name) + 1;
|
||||
inst_module_names_ += module_name.size() + 1;
|
||||
inst_names_ += inst_name.size() + 1;
|
||||
inst_mod_count_++;
|
||||
}
|
||||
stringDelete(module_vname);
|
||||
|
|
@ -602,7 +605,7 @@ VerilogReader::hasScalarNamedPortRefs(LibertyCell *liberty_cell,
|
|||
&& pins->size() > 0
|
||||
&& (*pins)[0]->isNamedPortRef()) {
|
||||
for (VerilogNet *vpin : *pins) {
|
||||
const char *port_name = vpin->name();
|
||||
const char *port_name = vpin->name().c_str();
|
||||
LibertyPort *port = liberty_cell->findLibertyPort(port_name);
|
||||
if (port) {
|
||||
if (!(port->size() == 1
|
||||
|
|
@ -618,6 +621,18 @@ VerilogReader::hasScalarNamedPortRefs(LibertyCell *liberty_cell,
|
|||
return false;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefScalarNet(const char *port_vname)
|
||||
{
|
||||
net_port_ref_scalar_net_count_++;
|
||||
if (report_stmt_stats_)
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str());
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefScalarNet(const char *port_vname,
|
||||
const char *net_vname)
|
||||
|
|
@ -628,9 +643,10 @@ VerilogReader::makeNetNamedPortRefScalarNet(const char *port_vname,
|
|||
net_scalar_names_ += strlen(net_vname) + 1;
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
}
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
string net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str(),
|
||||
net_name.c_str());
|
||||
stringDelete(port_vname);
|
||||
stringDelete(net_vname);
|
||||
return ref;
|
||||
|
|
@ -642,14 +658,15 @@ VerilogReader::makeNetNamedPortRefBitSelect(const char *port_vname,
|
|||
int index)
|
||||
{
|
||||
net_port_ref_scalar_net_count_++;
|
||||
const char *bus_name = portVerilogToSta(bus_vname);
|
||||
const char *net_name = verilogBusBitNameTmp(bus_name, index);
|
||||
string bus_name = portVerilogToSta(bus_vname);
|
||||
string net_name = verilogBusBitName(bus_name.c_str(), index);
|
||||
if (report_stmt_stats_) {
|
||||
net_scalar_names_ += strlen(net_name) + 1;
|
||||
net_scalar_names_ += net_name.length() + 1;
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
}
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name.c_str(),
|
||||
net_name.c_str());
|
||||
stringDelete(port_vname);
|
||||
stringDelete(bus_vname);
|
||||
return ref;
|
||||
|
|
@ -662,8 +679,8 @@ VerilogReader::makeNetNamedPortRefScalar(const char *port_vname,
|
|||
net_port_ref_scalar_count_++;
|
||||
if (report_stmt_stats_)
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalar(port_name, net);
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalar(port_name.c_str(), net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -674,8 +691,9 @@ VerilogReader::makeNetNamedPortRefBit(const char *port_vname,
|
|||
VerilogNet *net)
|
||||
{
|
||||
net_port_ref_bit_count_++;
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefBit(port_name, index, net);
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefBit(port_name.c_str(),
|
||||
index, net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -687,8 +705,9 @@ VerilogReader::makeNetNamedPortRefPart(const char *port_vname,
|
|||
VerilogNet *net)
|
||||
{
|
||||
net_port_ref_part_count_++;
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefPart(port_name, from_index,
|
||||
string port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefPart(port_name.c_str(),
|
||||
from_index,
|
||||
to_index, net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
|
|
@ -776,20 +795,20 @@ VerilogReader::warn(int id,
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
VerilogReader::verilogName(VerilogModuleInst *mod_inst)
|
||||
{
|
||||
return sta::instanceVerilogName(mod_inst->instanceName(),
|
||||
network_->pathEscape());
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
VerilogReader::instanceVerilogName(const char *inst_name)
|
||||
{
|
||||
return sta::netVerilogName(inst_name, network_->pathEscape());
|
||||
}
|
||||
|
||||
const char *
|
||||
string
|
||||
VerilogReader::netVerilogName(const char *net_name)
|
||||
{
|
||||
return sta::netVerilogName(net_name, network_->pathEscape());
|
||||
|
|
@ -862,11 +881,13 @@ VerilogModule::parseDcl(VerilogDcl *dcl,
|
|||
// supply0/supply1 dcl can be used as modifier for
|
||||
// input/output/inout dcls.
|
||||
dcl_map_[net_name] = dcl;
|
||||
else if (!dcl->direction()->isInternal())
|
||||
else if (!dcl->direction()->isInternal()) {
|
||||
string net_vname = reader->netVerilogName(net_name);
|
||||
reader->warn(18, filename_, dcl->line(),
|
||||
"signal %s previously declared on line %d.",
|
||||
reader->netVerilogName(net_name),
|
||||
net_vname.c_str(),
|
||||
existing_dcl->line());
|
||||
}
|
||||
}
|
||||
else
|
||||
dcl_map_[net_name] = dcl;
|
||||
|
|
@ -890,9 +911,10 @@ VerilogModule::checkInstanceName(VerilogInst *inst,
|
|||
stringDelete(replacement_name);
|
||||
replacement_name = stringPrint("%s_%d", inst_name, i);
|
||||
} while (inst_names.findKey(replacement_name));
|
||||
string inst_vname = reader->instanceVerilogName(inst_name);
|
||||
reader->warn(19, filename_, inst->line(),
|
||||
"instance name %s duplicated - renamed to %s.",
|
||||
reader->instanceVerilogName(inst_name),
|
||||
inst_vname.c_str(),
|
||||
replacement_name);
|
||||
inst_name = replacement_name;
|
||||
inst->setInstanceName(inst_name);
|
||||
|
|
@ -1078,7 +1100,7 @@ VerilogDclArg::netName()
|
|||
if (net_name_)
|
||||
return net_name_;
|
||||
else if (assign_)
|
||||
return assign_->lhs()->name();
|
||||
return assign_->lhs()->name().c_str();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -1112,6 +1134,7 @@ class VerilogOneNetNameIterator : public VerilogNetNameIterator
|
|||
{
|
||||
public:
|
||||
explicit VerilogOneNetNameIterator(const char *name);
|
||||
explicit VerilogOneNetNameIterator(string name);
|
||||
virtual bool hasNext();
|
||||
virtual const char *next();
|
||||
|
||||
|
|
@ -1152,6 +1175,7 @@ protected:
|
|||
int from_index_;
|
||||
int to_index_;
|
||||
int index_;
|
||||
string bit_name_;
|
||||
};
|
||||
|
||||
VerilogBusNetNameIterator::VerilogBusNetNameIterator(const char *bus_name,
|
||||
|
|
@ -1176,19 +1200,21 @@ VerilogBusNetNameIterator::hasNext()
|
|||
const char *
|
||||
VerilogBusNetNameIterator::next()
|
||||
{
|
||||
const char *bit_name = verilogBusBitNameTmp(bus_name_, index_);
|
||||
bit_name_ = verilogBusBitName(bus_name_, index_);
|
||||
if (to_index_ > from_index_)
|
||||
index_++;
|
||||
else
|
||||
index_--;
|
||||
return bit_name;
|
||||
return bit_name_.c_str();
|
||||
}
|
||||
|
||||
static const char *
|
||||
verilogBusBitNameTmp(const char *bus_name,
|
||||
int index)
|
||||
static string
|
||||
verilogBusBitName(const char *bus_name,
|
||||
int index)
|
||||
{
|
||||
return stringPrintTmp("%s[%d]", bus_name, index);
|
||||
string bus_bit_name;
|
||||
stringPrint(bus_bit_name, "%s[%d]", bus_name, index);
|
||||
return bus_bit_name;
|
||||
}
|
||||
|
||||
class VerilogConstantNetNameIterator : public VerilogNetNameIterator
|
||||
|
|
@ -1291,21 +1317,27 @@ VerilogNetConcatNameIterator::next()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
const string VerilogNetUnnamed::null_;
|
||||
|
||||
VerilogNetNamed::VerilogNetNamed(const char *name) :
|
||||
VerilogNet(),
|
||||
name_(stringCopy(name))
|
||||
name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
VerilogNetNamed::VerilogNetNamed(const string &name) :
|
||||
VerilogNet(),
|
||||
name_(name)
|
||||
{
|
||||
}
|
||||
|
||||
VerilogNetNamed::~VerilogNetNamed()
|
||||
{
|
||||
stringDelete(name_);
|
||||
}
|
||||
|
||||
void
|
||||
VerilogNetNamed::setName(const char *name)
|
||||
{
|
||||
stringDelete(name_);
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
|
|
@ -1329,7 +1361,7 @@ verilogNetScalarSize(const char *name,
|
|||
int
|
||||
VerilogNetScalar::size(VerilogModule *module)
|
||||
{
|
||||
return verilogNetScalarSize(name_, module);
|
||||
return verilogNetScalarSize(name_.c_str(), module);
|
||||
}
|
||||
|
||||
static VerilogNetNameIterator *
|
||||
|
|
@ -1354,22 +1386,16 @@ VerilogNetNameIterator *
|
|||
VerilogNetScalar::nameIterator(VerilogModule *module,
|
||||
VerilogReader *)
|
||||
{
|
||||
return verilogNetScalarNameIterator(name_, module);
|
||||
return verilogNetScalarNameIterator(name_.c_str(), module);
|
||||
}
|
||||
|
||||
VerilogNetBitSelect::VerilogNetBitSelect(const char *name,
|
||||
int index) :
|
||||
VerilogNetNamed(name),
|
||||
VerilogNetNamed(verilogBusBitName(name, index)),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
VerilogNetBitSelect::name()
|
||||
{
|
||||
return verilogBusBitNameTmp(name_, index_);
|
||||
}
|
||||
|
||||
int
|
||||
VerilogNetBitSelect::size(VerilogModule *)
|
||||
{
|
||||
|
|
@ -1380,7 +1406,7 @@ VerilogNetNameIterator *
|
|||
VerilogNetBitSelect::nameIterator(VerilogModule *,
|
||||
VerilogReader *)
|
||||
{
|
||||
return new VerilogOneNetNameIterator(verilogBusBitNameTmp(name_, index_));
|
||||
return new VerilogOneNetNameIterator(name_.c_str());
|
||||
}
|
||||
|
||||
VerilogNetPartSelect::VerilogNetPartSelect(const char *name,
|
||||
|
|
@ -1405,7 +1431,7 @@ VerilogNetNameIterator *
|
|||
VerilogNetPartSelect::nameIterator(VerilogModule *,
|
||||
VerilogReader *)
|
||||
{
|
||||
return new VerilogBusNetNameIterator(name_, from_index_, to_index_);
|
||||
return new VerilogBusNetNameIterator(name_.c_str(), from_index_, to_index_);
|
||||
}
|
||||
|
||||
VerilogNetConstant::VerilogNetConstant(const char *constant,
|
||||
|
|
@ -1583,6 +1609,12 @@ VerilogNetPortRef::VerilogNetPortRef(const char *name) :
|
|||
{
|
||||
}
|
||||
|
||||
VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const char *name) :
|
||||
VerilogNetPortRef(name),
|
||||
net_name_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const char *name,
|
||||
const char *net_name) :
|
||||
VerilogNetPortRef(name),
|
||||
|
|
@ -1651,16 +1683,10 @@ VerilogNetPortRefBit::VerilogNetPortRefBit(const char *name,
|
|||
int index,
|
||||
VerilogNet *net) :
|
||||
VerilogNetPortRefScalar(name, net),
|
||||
index_(index)
|
||||
bit_name_(verilogBusBitName(name, index))
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
VerilogNetPortRefBit::name()
|
||||
{
|
||||
return verilogBusBitNameTmp(name_, index_);
|
||||
}
|
||||
|
||||
VerilogNetPortRefPart::VerilogNetPortRefPart(const char *name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
|
|
@ -1670,8 +1696,8 @@ VerilogNetPortRefPart::VerilogNetPortRefPart(const char *name,
|
|||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
VerilogNetPortRefPart::name()
|
||||
const string &
|
||||
VerilogNetPortRefPart::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
|
@ -1813,18 +1839,19 @@ VerilogReader::makeModuleInstNetwork(VerilogModuleInst *mod_inst,
|
|||
const char *module_name = mod_inst->moduleName();
|
||||
Cell *cell = network_->findAnyCell(module_name);
|
||||
if (cell == nullptr) {
|
||||
string inst_vname = verilogName(mod_inst);
|
||||
if (make_black_boxes) {
|
||||
cell = makeBlackBox(mod_inst, parent_module);
|
||||
linkWarn(198, parent_module->filename(), mod_inst->line(),
|
||||
"module %s not found. Creating black box for %s.",
|
||||
mod_inst->moduleName(),
|
||||
verilogName(mod_inst));
|
||||
inst_vname.c_str());
|
||||
}
|
||||
else
|
||||
linkError(199, parent_module->filename(), mod_inst->line(),
|
||||
"module %s not found for instance %s.",
|
||||
mod_inst->moduleName(),
|
||||
verilogName(mod_inst));
|
||||
inst_vname.c_str());
|
||||
}
|
||||
if (cell) {
|
||||
LibertyCell *lib_cell = network_->libertyCell(cell);
|
||||
|
|
@ -1868,20 +1895,22 @@ VerilogReader::makeNamedInstPins(Cell *cell,
|
|||
VerilogBindingTbl *parent_bindings,
|
||||
bool is_leaf)
|
||||
{
|
||||
string inst_vname = verilogName(mod_inst);
|
||||
VerilogNetSeq::Iterator pin_iter(mod_inst->pins());
|
||||
while (pin_iter.hasNext()) {
|
||||
VerilogNetPortRef *vpin = dynamic_cast<VerilogNetPortRef*>(pin_iter.next());
|
||||
const char *port_name = vpin->name();
|
||||
const char *port_name = vpin->name().c_str();
|
||||
Port *port = network_->findPort(cell, port_name);
|
||||
if (port) {
|
||||
if (vpin->hasNet()
|
||||
&& network_->size(port) != vpin->size(parent_module))
|
||||
&& network_->size(port) != vpin->size(parent_module)) {
|
||||
linkWarn(200, parent_module->filename(), mod_inst->line(),
|
||||
"instance %s port %s size %d does not match net size %d.",
|
||||
verilogName(mod_inst),
|
||||
inst_vname.c_str(),
|
||||
network_->name(port),
|
||||
network_->size(port),
|
||||
vpin->size(parent_module));
|
||||
}
|
||||
else {
|
||||
VerilogNetNameIterator *net_name_iter =
|
||||
vpin->nameIterator(parent_module, this);
|
||||
|
|
@ -1907,11 +1936,12 @@ VerilogReader::makeNamedInstPins(Cell *cell,
|
|||
if (lib_cell)
|
||||
pg_port = lib_cell->findPgPort(port_name);
|
||||
// Do not warn about connections to pg ports (which are ignored).
|
||||
if (pg_port == nullptr)
|
||||
if (pg_port == nullptr) {
|
||||
linkWarn(201, parent_module->filename(), mod_inst->line(),
|
||||
"instance %s port %s not found.",
|
||||
verilogName(mod_inst),
|
||||
inst_vname.c_str(),
|
||||
port_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1931,13 +1961,15 @@ VerilogReader::makeOrderedInstPins(Cell *cell,
|
|||
while (pin_iter.hasNext() && port_iter->hasNext()) {
|
||||
VerilogNet *net = pin_iter.next();
|
||||
Port *port = port_iter->next();
|
||||
if (network_->size(port) != net->size(parent_module))
|
||||
if (network_->size(port) != net->size(parent_module)) {
|
||||
string inst_vname = verilogName(mod_inst);
|
||||
linkWarn(202, parent_module->filename(), mod_inst->line(),
|
||||
"instance %s port %s size %d does not match net size %d.",
|
||||
verilogName(mod_inst),
|
||||
inst_vname.c_str(),
|
||||
network_->name(port),
|
||||
network_->size(port),
|
||||
net->size(parent_module));
|
||||
}
|
||||
else {
|
||||
VerilogNetNameIterator *net_name_iter=net->nameIterator(parent_module,
|
||||
this);
|
||||
|
|
@ -2027,9 +2059,8 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
|
|||
if (dcl && dcl->isBus()) {
|
||||
VerilogDclBus *dcl_bus = dynamic_cast<VerilogDclBus *>(dcl);
|
||||
// Bus is only 1 bit wide.
|
||||
const char *bus_name = verilogBusBitNameTmp(net_name,
|
||||
dcl_bus->fromIndex());
|
||||
net = parent_bindings->ensureNetBinding(bus_name, parent, network_);
|
||||
string bus_name = verilogBusBitName(net_name, dcl_bus->fromIndex());
|
||||
net = parent_bindings->ensureNetBinding(bus_name.c_str(), parent, network_);
|
||||
}
|
||||
else
|
||||
net = parent_bindings->ensureNetBinding(net_name, parent, network_);
|
||||
|
|
@ -2066,7 +2097,7 @@ VerilogReader::makeBlackBoxNamedPorts(Cell *cell,
|
|||
VerilogNetSeq::Iterator pin_iter(mod_inst->pins());
|
||||
while (pin_iter.hasNext()) {
|
||||
VerilogNetNamed *vpin = dynamic_cast<VerilogNetNamed*>(pin_iter.next());
|
||||
const char *port_name = vpin->name();
|
||||
const char *port_name = vpin->name().c_str();
|
||||
size_t size = vpin->size(parent_module);
|
||||
Port *port = (size == 1)
|
||||
? network_->makePort(cell, port_name)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ VerilogParse_error(const char *msg);
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::string;
|
||||
using std::set;
|
||||
|
||||
class Debug;
|
||||
class Report;
|
||||
class VerilogReader;
|
||||
|
|
@ -117,6 +120,7 @@ public:
|
|||
VerilogNet *rhs,
|
||||
int line);
|
||||
VerilogNetScalar *makeNetScalar(const char *name);
|
||||
VerilogNetPortRef *makeNetNamedPortRefScalarNet(const char *port_vname);
|
||||
VerilogNetPortRef *makeNetNamedPortRefScalarNet(const char *port_name,
|
||||
const char *net_name);
|
||||
VerilogNetPortRef *makeNetNamedPortRefBitSelect(const char *port_name,
|
||||
|
|
@ -160,11 +164,11 @@ public:
|
|||
void reportStmtCounts();
|
||||
const char *constant10Max() const { return constant10_max_; }
|
||||
size_t constant10MaxLength() const { return constant10_max_length_; }
|
||||
const char *
|
||||
string
|
||||
verilogName(VerilogModuleInst *inst);
|
||||
const char *
|
||||
string
|
||||
instanceVerilogName(const char *inst_name);
|
||||
const char *
|
||||
string
|
||||
netVerilogName(const char *net_name);
|
||||
|
||||
protected:
|
||||
|
|
@ -178,9 +182,9 @@ protected:
|
|||
void makeNamedPortRefCellPorts(Cell *cell,
|
||||
VerilogModule *module,
|
||||
VerilogNet *mod_port,
|
||||
StringSet &port_names);
|
||||
set<string> &port_names);
|
||||
void checkModuleDcls(VerilogModule *module,
|
||||
StringSet &port_names);
|
||||
set<string> &port_names);
|
||||
void makeModuleInstBody(VerilogModule *module,
|
||||
Instance *inst,
|
||||
VerilogBindingTbl *bindings,
|
||||
|
|
@ -488,8 +492,8 @@ class VerilogNet
|
|||
public:
|
||||
VerilogNet() {}
|
||||
virtual ~VerilogNet() {}
|
||||
virtual bool isNamed() = 0;
|
||||
virtual const char *name() = 0;
|
||||
virtual bool isNamed() const = 0;
|
||||
virtual const string &name() const = 0;
|
||||
virtual bool isNamedPortRef() { return false; }
|
||||
virtual bool isNamedPortRefScalarNet() const { return false; }
|
||||
virtual int size(VerilogModule *module) = 0;
|
||||
|
|
@ -503,23 +507,27 @@ class VerilogNetUnnamed : public VerilogNet
|
|||
{
|
||||
public:
|
||||
VerilogNetUnnamed() {}
|
||||
virtual bool isNamed() { return false; }
|
||||
virtual const char *name() { return nullptr; }
|
||||
bool isNamed() const override { return false; }
|
||||
const string &name() const override { return null_; }
|
||||
|
||||
private:
|
||||
static const string null_;
|
||||
};
|
||||
|
||||
class VerilogNetNamed : public VerilogNet
|
||||
{
|
||||
public:
|
||||
explicit VerilogNetNamed(const char *name);
|
||||
explicit VerilogNetNamed(const string &name);
|
||||
virtual ~VerilogNetNamed();
|
||||
virtual bool isNamed() { return true; }
|
||||
bool isNamed() const override { return true; }
|
||||
virtual bool isScalar() const = 0;
|
||||
virtual const char *name() { return name_; }
|
||||
const char *baseName() { return name_; }
|
||||
const string &name() const override { return name_; }
|
||||
const string baseName() const { return name_; }
|
||||
void setName(const char *name);
|
||||
|
||||
protected:
|
||||
const char *name_;
|
||||
string name_;
|
||||
};
|
||||
|
||||
// Named net reference, which could be the name of a scalar or bus signal.
|
||||
|
|
@ -538,7 +546,6 @@ class VerilogNetBitSelect : public VerilogNetNamed
|
|||
public:
|
||||
VerilogNetBitSelect(const char *name,
|
||||
int index);
|
||||
virtual const char *name();
|
||||
int index() { return index_; }
|
||||
virtual bool isScalar() const { return false; }
|
||||
virtual int size(VerilogModule *module);
|
||||
|
|
@ -620,6 +627,7 @@ public:
|
|||
class VerilogNetPortRefScalarNet : public VerilogNetPortRef
|
||||
{
|
||||
public:
|
||||
VerilogNetPortRefScalarNet(const char *name);
|
||||
VerilogNetPortRefScalarNet(const char *name,
|
||||
const char *net_name);
|
||||
virtual ~VerilogNetPortRefScalarNet();
|
||||
|
|
@ -658,10 +666,10 @@ public:
|
|||
VerilogNetPortRefBit(const char *name,
|
||||
int index,
|
||||
VerilogNet *net);
|
||||
virtual const char *name();
|
||||
const string &name() const override { return bit_name_; }
|
||||
|
||||
private:
|
||||
int index_;
|
||||
string bit_name_;
|
||||
};
|
||||
|
||||
class VerilogNetPortRefPart : public VerilogNetPortRefBit
|
||||
|
|
@ -671,7 +679,7 @@ public:
|
|||
int from_index,
|
||||
int to_index,
|
||||
VerilogNet *net);
|
||||
virtual const char *name();
|
||||
const string &name() const override;
|
||||
int toIndex() const { return to_index_; }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -159,8 +159,9 @@ VerilogWriter::writePorts(Cell *cell)
|
|||
|| !network_->direction(port)->isPowerGround()) {
|
||||
if (!first)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, "%s", portVerilogName(network_->name(port),
|
||||
network_->pathEscape()));
|
||||
string verillg_name = portVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
fprintf(stream_, "%s", verillg_name.c_str());
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -177,8 +178,8 @@ VerilogWriter::writePortDcls(Cell *cell)
|
|||
PortDirection *dir = network_->direction(port);
|
||||
if (include_pwr_gnd_
|
||||
|| !network_->direction(port)->isPowerGround()) {
|
||||
const char *port_name = portVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
string port_vname = portVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
const char *vtype = verilogPortDir(dir);
|
||||
if (vtype) {
|
||||
fprintf(stream_, " %s", vtype);
|
||||
|
|
@ -186,14 +187,14 @@ VerilogWriter::writePortDcls(Cell *cell)
|
|||
fprintf(stream_, " [%d:%d]",
|
||||
network_->fromIndex(port),
|
||||
network_->toIndex(port));
|
||||
fprintf(stream_, " %s;\n", port_name);
|
||||
fprintf(stream_, " %s;\n", port_vname.c_str());
|
||||
if (dir->isTristate()) {
|
||||
fprintf(stream_, " tri");
|
||||
if (network_->isBus(port))
|
||||
fprintf(stream_, " [%d:%d]",
|
||||
network_->fromIndex(port),
|
||||
network_->toIndex(port));
|
||||
fprintf(stream_, " %s;\n", port_name);
|
||||
fprintf(stream_, " %s;\n", port_vname.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -238,16 +239,18 @@ VerilogWriter::writeWireDcls(Instance *inst)
|
|||
const char *net_name = network_->name(net);
|
||||
if (network_->findPort(cell, net_name) == nullptr) {
|
||||
if (isBusName(net_name, '[', ']', escape)) {
|
||||
char *bus_name;
|
||||
bool is_bus;
|
||||
string bus_name;
|
||||
int index;
|
||||
parseBusName(net_name, '[', ']', escape, bus_name, index);
|
||||
BusIndexRange &range = bus_ranges[bus_name];
|
||||
parseBusName(net_name, '[', ']', escape, is_bus, bus_name, index);
|
||||
BusIndexRange &range = bus_ranges[bus_name.c_str()];
|
||||
range.first = max(range.first, index);
|
||||
range.second = min(range.second, index);
|
||||
}
|
||||
else
|
||||
fprintf(stream_, " wire %s;\n",
|
||||
netVerilogName(net_name, network_->pathEscape()));;
|
||||
else {
|
||||
string net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
fprintf(stream_, " wire %s;\n", net_vname.c_str());;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete net_iter;
|
||||
|
|
@ -255,10 +258,11 @@ VerilogWriter::writeWireDcls(Instance *inst)
|
|||
for (auto name_range : bus_ranges) {
|
||||
const char *bus_name = name_range.first;
|
||||
const BusIndexRange &range = name_range.second;
|
||||
string net_vname = netVerilogName(bus_name, network_->pathEscape());
|
||||
fprintf(stream_, " wire [%d:%d] %s;\n",
|
||||
range.first,
|
||||
range.second,
|
||||
netVerilogName(bus_name, network_->pathEscape()));;
|
||||
net_vname.c_str());;
|
||||
}
|
||||
|
||||
// Wire net dcls for writeInstBusPinBit.
|
||||
|
|
@ -297,11 +301,10 @@ VerilogWriter::writeChild(Instance *child)
|
|||
Cell *child_cell = network_->cell(child);
|
||||
if (!remove_cells_.hasKey(child_cell)) {
|
||||
const char *child_name = network_->name(child);
|
||||
const char *child_vname = instanceVerilogName(child_name,
|
||||
network_->pathEscape());
|
||||
string child_vname = instanceVerilogName(child_name, network_->pathEscape());
|
||||
fprintf(stream_, " %s %s (",
|
||||
network_->name(child_cell),
|
||||
child_vname);
|
||||
child_vname.c_str());
|
||||
bool first_port = true;
|
||||
CellPortIterator *port_iter = network_->portIterator(child_cell);
|
||||
while (port_iter->hasNext()) {
|
||||
|
|
@ -329,14 +332,14 @@ VerilogWriter::writeInstPin(Instance *inst,
|
|||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
const char *net_name = network_->name(net);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
string net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
if (!first_port)
|
||||
fprintf(stream_, ",\n ");
|
||||
const char *port_name = portVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
string port_vname = portVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
fprintf(stream_, ".%s(%s)",
|
||||
port_name,
|
||||
net_vname);
|
||||
port_vname.c_str(),
|
||||
net_vname.c_str());
|
||||
first_port = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -382,19 +385,17 @@ VerilogWriter::writeInstBusPinBit(Instance *inst,
|
|||
bool &first_member)
|
||||
{
|
||||
Pin *pin = network_->findPin(inst, port);
|
||||
const char *net_name = nullptr;
|
||||
if (pin) {
|
||||
Net *net = network_->net(pin);
|
||||
if (net)
|
||||
net_name = network_->name(net);
|
||||
}
|
||||
if (net_name == nullptr)
|
||||
Net *net = pin ? network_->net(pin) : nullptr;
|
||||
string net_name;
|
||||
if (net)
|
||||
net_name = network_->name(net);
|
||||
else
|
||||
// There is no verilog syntax to "skip" a bit in the concatentation.
|
||||
net_name = stringPrintTmp("_NC%d", unconnected_net_index_++);
|
||||
const char *net_vname = netVerilogName(net_name, network_->pathEscape());
|
||||
stringPrint(net_name, "_NC%d", unconnected_net_index_++);
|
||||
string net_vname = netVerilogName(net_name.c_str(), network_->pathEscape());
|
||||
if (!first_member)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, "%s", net_vname);
|
||||
fprintf(stream_, "%s", net_vname.c_str());
|
||||
first_member = false;
|
||||
}
|
||||
|
||||
|
|
@ -414,11 +415,13 @@ VerilogWriter::writeAssigns(Instance *inst)
|
|||
&& network_->direction(port)->isAnyOutput()
|
||||
&& !stringEqual(network_->name(port), network_->name(net))) {
|
||||
// Port name is different from net name.
|
||||
string port_vname = netVerilogName(network_->name(port),
|
||||
network_->pathEscape());
|
||||
string net_vname = netVerilogName(network_->name(net),
|
||||
network_->pathEscape());
|
||||
fprintf(stream_, " assign %s = %s;\n",
|
||||
netVerilogName(network_->name(port),
|
||||
network_->pathEscape()),
|
||||
netVerilogName(network_->name(net),
|
||||
network_->pathEscape()));
|
||||
port_vname.c_str(),
|
||||
net_vname.c_str());
|
||||
}
|
||||
}
|
||||
delete pin_iter;
|
||||
|
|
|
|||
Loading…
Reference in New Issue