Merge remote-tracking branch 'parallax/master'
Remove local changes. Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
c70c0f3d2a
|
|
@ -29,7 +29,7 @@ project(STA VERSION 2.6.0
|
|||
)
|
||||
|
||||
option(CUDD_DIR "CUDD BDD package directory")
|
||||
option(USE_TCL_READLINE "Use TCL readliine package" ON)
|
||||
option(USE_TCL_READLINE "Use TCL readline package" ON)
|
||||
option(USE_SANITIZE "Compile with santize address enabled")
|
||||
|
||||
# Turn on to debug compiler args.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ using sta::evalTclInit;
|
|||
using sta::sourceTclFile;
|
||||
using sta::parseThreadsArg;
|
||||
using sta::tcl_inits;
|
||||
using sta::is_regular_file;
|
||||
|
||||
// Swig uses C linkage for init functions.
|
||||
extern "C" {
|
||||
|
|
@ -133,7 +134,7 @@ staTclAppInit(int argc,
|
|||
string init_path = home;
|
||||
init_path += "/";
|
||||
init_path += init_filename;
|
||||
if (std::filesystem::is_regular_file(init_path.c_str()))
|
||||
if (is_regular_file(init_path.c_str()))
|
||||
sourceTclFile(init_path.c_str(), true, true, interp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -462,10 +462,12 @@ public:
|
|||
bool &exists) const;
|
||||
bool leakagePowerExists() const { return leakage_power_exists_; }
|
||||
|
||||
const SequentialSeq &sequentials() const { return sequentials_; }
|
||||
// Register, Latch or Statetable.
|
||||
bool hasSequentials() const;
|
||||
const SequentialSeq &sequentials() const { return sequentials_; }
|
||||
// Find the sequential with the output connected to an (internal) port.
|
||||
Sequential *outputPortSequential(LibertyPort *port);
|
||||
const Statetable *statetable() const { return statetable_; }
|
||||
|
||||
// Find bus declaration local to this cell.
|
||||
BusDcl *findBusDcl(const char *name) const;
|
||||
|
|
@ -502,6 +504,9 @@ public:
|
|||
LogicValue clr_preset_out_inv,
|
||||
LibertyPort *output,
|
||||
LibertyPort *output_inv);
|
||||
void makeStatetable(LibertyPortSeq &input_ports,
|
||||
LibertyPortSeq &internal_ports,
|
||||
StatetableRows &table);
|
||||
void addBusDcl(BusDcl *bus_dcl);
|
||||
// Add scaled cell after it is complete.
|
||||
void addScaledCell(OperatingConditions *op_cond,
|
||||
|
|
@ -600,6 +605,7 @@ protected:
|
|||
LeakagePowerSeq leakage_powers_;
|
||||
SequentialSeq sequentials_;
|
||||
PortToSequentialMap port_to_seq_map_;
|
||||
Statetable *statetable_;
|
||||
BusDclMap bus_dcls_;
|
||||
ModeDefMap mode_defs_;
|
||||
ScaleFactors *scale_factors_;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::vector;
|
||||
|
||||
class Units;
|
||||
class Unit;
|
||||
class LibertyLibrary;
|
||||
|
|
@ -58,6 +60,8 @@ class Transition;
|
|||
class RiseFall;
|
||||
class RiseFallBoth;
|
||||
class ReceiverModel;
|
||||
class Statetable;
|
||||
class StatetableRow;
|
||||
|
||||
typedef Vector<LibertyLibrary*> LibertyLibrarySeq;
|
||||
typedef Vector<LibertyCell*> LibertyCellSeq;
|
||||
|
|
@ -71,6 +75,7 @@ typedef std::shared_ptr<Table> TablePtr;
|
|||
typedef std::shared_ptr<TimingArcAttrs> TimingArcAttrsPtr;
|
||||
typedef std::shared_ptr<TableAxis> TableAxisPtr;
|
||||
typedef std::shared_ptr<ReceiverModel> ReceiverModelPtr;
|
||||
typedef vector<StatetableRow> StatetableRows;
|
||||
|
||||
enum class ScaleFactorType : unsigned {
|
||||
pin_cap,
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ public:
|
|||
virtual const PathVertex *dataClkPath() const { return nullptr; }
|
||||
virtual int setupDefaultCycles() const { return 1; }
|
||||
virtual Delay clkSkew(const StaState *sta);
|
||||
virtual bool ignoreClkLatency(const StaState * /* sta */) const { return false; }
|
||||
|
||||
static bool less(const PathEnd *path_end1,
|
||||
const PathEnd *path_end2,
|
||||
|
|
@ -206,6 +207,9 @@ protected:
|
|||
PathDelay *path_delay,
|
||||
Arrival src_clk_arrival,
|
||||
const StaState *sta);
|
||||
static bool ignoreClkLatency(const PathRef &path,
|
||||
PathDelay *path_delay,
|
||||
const StaState *sta);
|
||||
PathRef path_;
|
||||
};
|
||||
|
||||
|
|
@ -384,6 +388,7 @@ public:
|
|||
Crpr &crpr_diff,
|
||||
Delay &max_borrow,
|
||||
bool &borrow_limit_exists) const;
|
||||
virtual bool ignoreClkLatency(const StaState *sta) const;
|
||||
|
||||
protected:
|
||||
PathEndLatchCheck(Path *path,
|
||||
|
|
@ -569,6 +574,7 @@ public:
|
|||
virtual int exceptPathCmp(const PathEnd *path_end,
|
||||
const StaState *sta) const;
|
||||
bool hasOutputDelay() const { return output_delay_ != nullptr; }
|
||||
virtual bool ignoreClkLatency(const StaState *sta) const;
|
||||
|
||||
protected:
|
||||
PathEndPathDelay(PathDelay *path_delay,
|
||||
|
|
|
|||
|
|
@ -155,18 +155,6 @@ public:
|
|||
Arrival pathClkPathArrival(const Path *path) const;
|
||||
|
||||
PathGroup *pathGroup(const PathEnd *path_end) const;
|
||||
void updatePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
PathGroupNameSet *group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
bool removal,
|
||||
bool clk_gating_setup,
|
||||
bool clk_gating_hold);
|
||||
void deletePathGroups();
|
||||
virtual ExceptionPath *exceptionTo(ExceptionPathType type,
|
||||
const Path *path,
|
||||
|
|
@ -523,18 +511,18 @@ protected:
|
|||
void tnsDecr(Vertex *vertex,
|
||||
PathAPIndex path_ap_index);
|
||||
void tnsNotifyBefore(Vertex *vertex);
|
||||
PathGroups *makePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
PathGroupNameSet *group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
bool removal,
|
||||
bool clk_gating_setup,
|
||||
bool clk_gating_hold);
|
||||
void makePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
PathGroupNameSet *group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
bool removal,
|
||||
bool clk_gating_setup,
|
||||
bool clk_gating_hold);
|
||||
bool matchesFilterTo(Path *path,
|
||||
const ClockEdge *to_clk_edge) const;
|
||||
PathRef pathClkPathArrival1(const Path *path) const;
|
||||
|
|
|
|||
|
|
@ -16,11 +16,42 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
enum class StateInputValue {
|
||||
low,
|
||||
high,
|
||||
dont_care,
|
||||
low_high,
|
||||
high_low,
|
||||
rise,
|
||||
fall,
|
||||
not_rise,
|
||||
not_fall
|
||||
};
|
||||
|
||||
enum class StateInternalValue {
|
||||
low,
|
||||
high,
|
||||
unspecified,
|
||||
low_high,
|
||||
high_low,
|
||||
unknown,
|
||||
hold
|
||||
};
|
||||
|
||||
class StatetableRow;
|
||||
|
||||
using std::vector;
|
||||
|
||||
typedef vector<StateInputValue> StateInputValues;
|
||||
typedef vector<StateInternalValue> StateInternalValues;
|
||||
|
||||
// Register/Latch
|
||||
class Sequential
|
||||
{
|
||||
|
|
@ -63,8 +94,41 @@ protected:
|
|||
LibertyPort *output_;
|
||||
LibertyPort *output_inv_;
|
||||
|
||||
private:
|
||||
friend class LibertyCell;
|
||||
};
|
||||
|
||||
class Statetable
|
||||
{
|
||||
public:
|
||||
const LibertyPortSeq &inputPorts() const { return input_ports_; }
|
||||
const LibertyPortSeq &internalPorts() const { return internal_ports_; }
|
||||
const StatetableRows &table() const { return table_; }
|
||||
|
||||
protected:
|
||||
Statetable(LibertyPortSeq &input_ports,
|
||||
LibertyPortSeq &internal_ports,
|
||||
StatetableRows &table);
|
||||
LibertyPortSeq input_ports_;
|
||||
LibertyPortSeq internal_ports_;
|
||||
StatetableRows table_;
|
||||
|
||||
friend class LibertyCell;
|
||||
};
|
||||
|
||||
class StatetableRow
|
||||
{
|
||||
public:
|
||||
StatetableRow(StateInputValues &input_values,
|
||||
StateInternalValues ¤t_values,
|
||||
StateInternalValues &next_values);
|
||||
const StateInputValues &inputValues() const { return input_values_; }
|
||||
const StateInternalValues ¤tValues() const { return current_values_; }
|
||||
const StateInternalValues &nextValues() const { return next_values_; }
|
||||
|
||||
private:
|
||||
StateInputValues input_values_;
|
||||
StateInternalValues current_values_;
|
||||
StateInternalValues next_values_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -38,6 +38,24 @@ hashCellPorts(const LibertyCell *cell);
|
|||
static unsigned
|
||||
hashCellSequentials(const LibertyCell *cell);
|
||||
static unsigned
|
||||
hashSequential(const Sequential *seq);
|
||||
bool
|
||||
equivCellStatetables(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2);
|
||||
static bool
|
||||
equivCellPortSeq(const LibertyPortSeq &ports1,
|
||||
const LibertyPortSeq &ports2);
|
||||
static bool
|
||||
equivStatetableRows(const StatetableRows &table1,
|
||||
const StatetableRows &table2);
|
||||
static bool
|
||||
equivStatetableRow(const StatetableRow &row1,
|
||||
const StatetableRow &row2);
|
||||
static unsigned
|
||||
hashStatetable(const Statetable *statetable);
|
||||
static unsigned
|
||||
hashStatetableRow(const StatetableRow &row);
|
||||
static unsigned
|
||||
hashFuncExpr(const FuncExpr *expr);
|
||||
static unsigned
|
||||
hashPort(const LibertyPort *port);
|
||||
|
|
@ -221,16 +239,61 @@ static unsigned
|
|||
hashCellSequentials(const LibertyCell *cell)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
for (Sequential *seq : cell->sequentials()) {
|
||||
hash += hashFuncExpr(seq->clock()) * 3;
|
||||
hash += hashFuncExpr(seq->data()) * 5;
|
||||
hash += hashPort(seq->output()) * 7;
|
||||
hash += hashPort(seq->outputInv()) * 9;
|
||||
hash += hashFuncExpr(seq->clear()) * 11;
|
||||
hash += hashFuncExpr(seq->preset()) * 13;
|
||||
hash += int(seq->clearPresetOutput()) * 17;
|
||||
hash += int(seq->clearPresetOutputInv()) * 19;
|
||||
}
|
||||
for (const Sequential *seq : cell->sequentials())
|
||||
hash += hashSequential(seq);
|
||||
const Statetable *statetable = cell->statetable();
|
||||
if (statetable)
|
||||
hash += hashStatetable(statetable);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
hashSequential(const Sequential *seq)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
hash += seq->isRegister() * 3;
|
||||
hash += hashFuncExpr(seq->clock()) * 5;
|
||||
hash += hashFuncExpr(seq->data()) * 7;
|
||||
hash += hashPort(seq->output()) * 9;
|
||||
hash += hashPort(seq->outputInv()) * 11;
|
||||
hash += hashFuncExpr(seq->clear()) * 13;
|
||||
hash += hashFuncExpr(seq->preset()) * 17;
|
||||
hash += int(seq->clearPresetOutput()) * 19;
|
||||
hash += int(seq->clearPresetOutputInv()) * 23;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
hashStatetable(const Statetable *statetable)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
unsigned hash_ports = 0;
|
||||
for (LibertyPort *input_port : statetable->inputPorts())
|
||||
hash_ports += hashPort(input_port);
|
||||
hash += hash_ports * 3;
|
||||
|
||||
hash_ports = 0;
|
||||
for (LibertyPort *internal_port : statetable->internalPorts())
|
||||
hash_ports += hashPort(internal_port);
|
||||
hash += hash_ports * 5;
|
||||
|
||||
unsigned hash_rows = 0;
|
||||
for (const StatetableRow &row : statetable->table())
|
||||
hash_rows += hashStatetableRow(row);
|
||||
hash += hash_rows * 7;
|
||||
return hash;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
hashStatetableRow(const StatetableRow &row)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
for (StateInputValue input_value : row.inputValues())
|
||||
hash += static_cast<int>(input_value) * 9;
|
||||
for (StateInternalValue current_value : row.currentValues())
|
||||
hash += static_cast<int>(current_value) * 11;
|
||||
for (StateInternalValue next_value : row.nextValues())
|
||||
hash += static_cast<int>(next_value) * 13;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -261,6 +324,7 @@ equivCells(const LibertyCell *cell1,
|
|||
return equivCellPortsAndFuncs(cell1, cell2)
|
||||
&& equivCellPgPorts(cell1, cell2)
|
||||
&& equivCellSequentials(cell1, cell2)
|
||||
&& equivCellStatetables(cell1, cell2)
|
||||
&& equivCellTimingArcSets(cell1, cell2);
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +413,102 @@ equivCellSequentials(const LibertyCell *cell1,
|
|||
return seq_itr1 == seqs1.end() && seq_itr2 == seqs2.end();
|
||||
}
|
||||
|
||||
bool
|
||||
equivCellStatetables(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2)
|
||||
|
||||
{
|
||||
const Statetable *statetable1 = cell1->statetable();
|
||||
const Statetable *statetable2 = cell2->statetable();
|
||||
return (statetable1 == nullptr && statetable2 == nullptr)
|
||||
|| (statetable1 && statetable2
|
||||
&& equivCellPortSeq(statetable1->inputPorts(), statetable2->inputPorts())
|
||||
&& equivCellPortSeq(statetable1->internalPorts(), statetable2->internalPorts())
|
||||
&& equivStatetableRows(statetable1->table(), statetable2->table()));
|
||||
}
|
||||
|
||||
static bool
|
||||
equivCellPortSeq(const LibertyPortSeq &ports1,
|
||||
const LibertyPortSeq &ports2)
|
||||
{
|
||||
if (ports1.size() != ports2.size())
|
||||
return false;
|
||||
|
||||
auto port_itr1 = ports1.begin();
|
||||
auto port_itr2 = ports2.begin();
|
||||
for (;
|
||||
port_itr1 != ports1.end() && port_itr2 != ports2.end();
|
||||
port_itr1++, port_itr2++) {
|
||||
const LibertyPort *port1 = *port_itr1;
|
||||
const LibertyPort *port2 = *port_itr2;
|
||||
if (!LibertyPort::equiv(port1, port2))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
equivStatetableRows(const StatetableRows &table1,
|
||||
const StatetableRows &table2)
|
||||
{
|
||||
if (table1.size() != table2.size())
|
||||
return false;
|
||||
|
||||
auto row_itr1 = table1.begin();
|
||||
auto row_itr2 = table2.begin();
|
||||
for (;
|
||||
row_itr1 != table1.end() && row_itr2 != table2.end();
|
||||
row_itr1++, row_itr2++) {
|
||||
const StatetableRow &row1 = *row_itr1;
|
||||
const StatetableRow &row2 = *row_itr2;
|
||||
if (!equivStatetableRow(row1, row2))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
equivStatetableRow(const StatetableRow &row1,
|
||||
const StatetableRow &row2)
|
||||
{
|
||||
const StateInputValues &input_values1 = row1.inputValues();
|
||||
const StateInputValues &input_values2 = row2.inputValues();
|
||||
if (input_values1.size() != input_values2.size())
|
||||
return false;
|
||||
for (auto input_itr1 = input_values1.begin(),
|
||||
input_itr2 = input_values2.begin();
|
||||
input_itr1 != input_values1.end() && input_itr2 != input_values2.end();
|
||||
input_itr1++, input_itr2++) {
|
||||
if (*input_itr1 != *input_itr2)
|
||||
return false;
|
||||
}
|
||||
|
||||
const StateInternalValues ¤t_values1 = row1.currentValues();
|
||||
const StateInternalValues ¤t_values2 = row2.currentValues();
|
||||
if (current_values1.size() != current_values2.size())
|
||||
return false;
|
||||
for (auto current_itr1 = current_values1.begin(),
|
||||
current_itr2 = current_values2.begin();
|
||||
current_itr1 != current_values1.end() && current_itr2 != current_values2.end();
|
||||
current_itr1++, current_itr2++) {
|
||||
if (*current_itr1 != *current_itr2)
|
||||
return false;
|
||||
}
|
||||
|
||||
const StateInternalValues &next_values1 = row1.nextValues();
|
||||
const StateInternalValues &next_values2 = row2.nextValues();
|
||||
if (next_values1.size() != next_values2.size())
|
||||
return false;
|
||||
for (auto next_itr1 = next_values1.begin(),
|
||||
next_itr2 = next_values2.begin();
|
||||
next_itr1 != next_values1.end() && next_itr2 != next_values2.end();
|
||||
next_itr1++, next_itr2++) {
|
||||
if (*next_itr1 != *next_itr2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
equivCellTimingArcSets(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2)
|
||||
|
|
|
|||
|
|
@ -930,6 +930,7 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
|
|||
interface_timing_(false),
|
||||
clock_gate_type_(ClockGateType::none),
|
||||
has_infered_reg_timing_arcs_(false),
|
||||
statetable_(nullptr),
|
||||
scale_factors_(nullptr),
|
||||
test_cell_(nullptr),
|
||||
ocv_arc_depth_(0.0),
|
||||
|
|
@ -958,6 +959,7 @@ LibertyCell::~LibertyCell()
|
|||
leakage_powers_.deleteContents();
|
||||
|
||||
sequentials_.deleteContents();
|
||||
delete statetable_;
|
||||
bus_dcls_.deleteContents();
|
||||
scaled_cells_.deleteContents();
|
||||
|
||||
|
|
@ -1511,7 +1513,16 @@ LibertyCell::outputPortSequential(LibertyPort *port)
|
|||
bool
|
||||
LibertyCell::hasSequentials() const
|
||||
{
|
||||
return !sequentials_.empty();
|
||||
return !sequentials_.empty()
|
||||
|| statetable_ != nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::makeStatetable(LibertyPortSeq &input_ports,
|
||||
LibertyPortSeq &internal_ports,
|
||||
StatetableRows &table)
|
||||
{
|
||||
statetable_ = new Statetable(input_ports, internal_ports, table);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "EnumNameMap.hh"
|
||||
#include "Report.hh"
|
||||
#include "Debug.hh"
|
||||
#include "TokenParser.hh"
|
||||
|
|
@ -45,6 +46,7 @@ extern int LibertyParse_debug;
|
|||
namespace sta {
|
||||
|
||||
using std::make_shared;
|
||||
using std::string;
|
||||
|
||||
static void
|
||||
scaleFloats(FloatSeq *floats,
|
||||
|
|
@ -121,6 +123,7 @@ LibertyReader::readLibertyFile(const char *filename,
|
|||
in_bus_ = false;
|
||||
in_bundle_ = false;
|
||||
sequential_ = nullptr;
|
||||
statetable_ = nullptr;
|
||||
timing_ = nullptr;
|
||||
internal_power_ = nullptr;
|
||||
leakage_power_ = nullptr;
|
||||
|
|
@ -375,6 +378,11 @@ LibertyReader::defineVisitors()
|
|||
defineAttrVisitor("clear_preset_var1", &LibertyReader::visitClrPresetVar1);
|
||||
defineAttrVisitor("clear_preset_var2", &LibertyReader::visitClrPresetVar2);
|
||||
|
||||
// Statetable
|
||||
defineGroupVisitor("statetable", &LibertyReader::beginStatetable,
|
||||
&LibertyReader::endStatetable);
|
||||
defineAttrVisitor("table", &LibertyReader::visitTable);
|
||||
|
||||
defineGroupVisitor("timing", &LibertyReader::beginTiming,
|
||||
&LibertyReader::endTiming);
|
||||
defineAttrVisitor("related_pin", &LibertyReader::visitRelatedPin);
|
||||
|
|
@ -1904,6 +1912,7 @@ LibertyReader::endCell(LibertyGroup *group)
|
|||
// Sequentials and leakage powers reference expressions outside of port definitions
|
||||
// so they do not require LibertyFunc's.
|
||||
makeCellSequentials();
|
||||
makeStatetable();
|
||||
// Parse functions defined inside of port groups that reference other ports
|
||||
// and replace the references with the parsed expressions.
|
||||
parseCellFuncs();
|
||||
|
|
@ -2126,6 +2135,37 @@ LibertyReader::checkLatchEnableSense(FuncExpr *enable_func,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
LibertyReader::makeStatetable()
|
||||
{
|
||||
if (statetable_) {
|
||||
LibertyPortSeq input_ports;
|
||||
for (const string &input : statetable_->inputPorts()) {
|
||||
LibertyPort *port = cell_->findLibertyPort(input.c_str());
|
||||
if (port)
|
||||
input_ports.push_back(port);
|
||||
else
|
||||
libWarn(0000, statetable_->line(), "statetable input port %s not found.",
|
||||
input.c_str());
|
||||
}
|
||||
LibertyPortSeq internal_ports;
|
||||
for (const string &internal : statetable_->internalPorts()) {
|
||||
LibertyPort *port = cell_->findLibertyPort(internal.c_str());
|
||||
if (port)
|
||||
internal_ports.push_back(port);
|
||||
else
|
||||
libWarn(0000, statetable_->line(), "statetable internal port %s not found.",
|
||||
internal.c_str());
|
||||
}
|
||||
cell_->makeStatetable(input_ports, internal_ports, statetable_->table());
|
||||
statetable_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
LibertyReader::makeLeakagePowers()
|
||||
{
|
||||
|
|
@ -3928,6 +3968,134 @@ LibertyReader::visitClrPresetVar2(LibertyAttr *attr)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
LibertyReader::beginStatetable(LibertyGroup *group)
|
||||
{
|
||||
if (cell_) {
|
||||
const char *input_ports_arg = group->firstName();
|
||||
StdStringSeq input_ports;
|
||||
if (input_ports_arg)
|
||||
input_ports = parseTokenList(input_ports_arg, ' ');
|
||||
|
||||
const char *internal_ports_arg = group->secondName();
|
||||
StdStringSeq internal_ports;
|
||||
if (internal_ports_arg)
|
||||
internal_ports = parseTokenList(internal_ports_arg, ' ');
|
||||
statetable_ = new StatetableGroup(input_ports, internal_ports, group->line());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::visitTable(LibertyAttr *attr)
|
||||
{
|
||||
if (statetable_) {
|
||||
const char *table_str = getAttrString(attr);
|
||||
StdStringSeq table_rows = parseTokenList(table_str, ',');
|
||||
size_t input_count = statetable_->inputPorts().size();
|
||||
size_t internal_count = statetable_->internalPorts().size();
|
||||
for (string row : table_rows) {
|
||||
StdStringSeq row_groups = parseTokenList(row.c_str(), ':');
|
||||
if (row_groups.size() != 3) {
|
||||
libWarn(0000, attr, "table row must have 3 groups separated by ':'.");
|
||||
break;
|
||||
}
|
||||
StdStringSeq inputs = parseTokenList(row_groups[0].c_str(), ' ');
|
||||
if (inputs.size() != input_count) {
|
||||
libWarn(0000, attr, "table row has %zu input values but %zu are required.",
|
||||
inputs.size(),
|
||||
input_count);
|
||||
break;
|
||||
}
|
||||
StdStringSeq currents = parseTokenList(row_groups[1].c_str(), ' ');
|
||||
if (currents.size() != internal_count) {
|
||||
libWarn(0000, attr, "table row has %zu current values but %zu are required.",
|
||||
currents.size(),
|
||||
internal_count);
|
||||
break;
|
||||
}
|
||||
StdStringSeq nexts = parseTokenList(row_groups[2].c_str(), ' ');
|
||||
if (nexts.size() != internal_count) {
|
||||
libWarn(0000, attr, "table row has %zu next values but %zu are required.",
|
||||
nexts.size(),
|
||||
internal_count);
|
||||
break;
|
||||
}
|
||||
|
||||
StateInputValues input_values = parseStateInputValues(inputs, attr);
|
||||
StateInternalValues current_values=parseStateInternalValues(currents,attr);
|
||||
StateInternalValues next_values = parseStateInternalValues(nexts, attr);
|
||||
statetable_->addRow(input_values, current_values, next_values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static EnumNameMap<StateInputValue> state_input_value_name_map =
|
||||
{{StateInputValue::low, "L"},
|
||||
{StateInputValue::high, "H"},
|
||||
{StateInputValue::dont_care, "-"},
|
||||
{StateInputValue::low_high, "L/H"},
|
||||
{StateInputValue::high_low, "H/L"},
|
||||
{StateInputValue::rise, "R"},
|
||||
{StateInputValue::fall, "F"},
|
||||
{StateInputValue::not_rise, "~R"},
|
||||
{StateInputValue::not_fall, "~F"}
|
||||
};
|
||||
|
||||
static EnumNameMap<StateInternalValue> state_internal_value_name_map =
|
||||
{{StateInternalValue::low, "L"},
|
||||
{StateInternalValue::high, "H"},
|
||||
{StateInternalValue::unspecified, "-"},
|
||||
{StateInternalValue::low_high, "L/H"},
|
||||
{StateInternalValue::high_low, "H/L"},
|
||||
{StateInternalValue::unknown, "X"},
|
||||
{StateInternalValue::hold, "N"}
|
||||
};
|
||||
|
||||
StateInputValues
|
||||
LibertyReader::parseStateInputValues(StdStringSeq &inputs,
|
||||
LibertyAttr *attr)
|
||||
{
|
||||
StateInputValues input_values;
|
||||
for (string input : inputs) {
|
||||
bool exists;
|
||||
StateInputValue value;
|
||||
state_input_value_name_map.find(input.c_str(), value, exists);
|
||||
if (!exists) {
|
||||
libWarn(0000, attr, "table input value '%s' not recognized.",
|
||||
input.c_str());
|
||||
value = StateInputValue::dont_care;
|
||||
}
|
||||
input_values.push_back(value);
|
||||
}
|
||||
return input_values;
|
||||
}
|
||||
|
||||
StateInternalValues
|
||||
LibertyReader::parseStateInternalValues(StdStringSeq &states,
|
||||
LibertyAttr *attr)
|
||||
{
|
||||
StateInternalValues state_values;
|
||||
for (string state : states) {
|
||||
bool exists;
|
||||
StateInternalValue value;
|
||||
state_internal_value_name_map.find(state.c_str(), value, exists);
|
||||
if (!exists) {
|
||||
libWarn(0000, attr, "table internal value '%s' not recognized.",
|
||||
state.c_str());
|
||||
value = StateInternalValue::unknown;
|
||||
}
|
||||
state_values.push_back(value);
|
||||
}
|
||||
return state_values;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::endStatetable(LibertyGroup *)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
LibertyReader::beginTiming(LibertyGroup *group)
|
||||
{
|
||||
|
|
@ -3996,6 +4164,24 @@ LibertyReader::parseNameList(const char *name_list)
|
|||
return names;
|
||||
}
|
||||
|
||||
StdStringSeq
|
||||
LibertyReader::parseTokenList(const char *token_str,
|
||||
const char separator)
|
||||
{
|
||||
StdStringSeq tokens;
|
||||
// Parse space separated list of names.
|
||||
char separators[2] = {separator, '\0'};
|
||||
TokenParser parser(token_str, separators);
|
||||
while (parser.hasNext()) {
|
||||
char *token = parser.next();
|
||||
// Skip extra spaces.
|
||||
if (token[0] != '\0') {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::visitRelatedBusPins(LibertyAttr *attr)
|
||||
{
|
||||
|
|
@ -5471,6 +5657,25 @@ SequentialGroup::setClrPresetVar2(LogicValue var)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
StatetableGroup::StatetableGroup(StdStringSeq &input_ports,
|
||||
StdStringSeq &internal_ports,
|
||||
int line) :
|
||||
input_ports_(input_ports),
|
||||
internal_ports_(internal_ports),
|
||||
line_(line)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
StatetableGroup::addRow(StateInputValues &input_values,
|
||||
StateInternalValues ¤t_values,
|
||||
StateInternalValues &next_values)
|
||||
{
|
||||
table_.emplace_back(input_values, current_values, next_values);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
RelatedPortGroup::RelatedPortGroup(int line) :
|
||||
related_port_names_(nullptr),
|
||||
line_(line)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "Vector.hh"
|
||||
#include "Map.hh"
|
||||
|
|
@ -27,6 +28,7 @@
|
|||
#include "InternalPower.hh"
|
||||
#include "LeakagePower.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "Sequential.hh"
|
||||
#include "LibertyParser.hh"
|
||||
#include "LibertyReader.hh"
|
||||
#include "NetworkClass.hh"
|
||||
|
|
@ -38,6 +40,7 @@ class LibertyReader;
|
|||
class LibertyFunc;
|
||||
class PortGroup;
|
||||
class SequentialGroup;
|
||||
class StatetableGroup;
|
||||
class RelatedPortGroup;
|
||||
class TimingGroup;
|
||||
class InternalPowerGroup;
|
||||
|
|
@ -47,6 +50,8 @@ class TimingArcBuilder;
|
|||
class LibertyAttr;
|
||||
class OutputWaveform;
|
||||
|
||||
using std::vector;
|
||||
|
||||
typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr);
|
||||
typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group);
|
||||
typedef Map<const char*,LibraryAttrVisitor,CharPtrLess> LibraryAttrMap;
|
||||
|
|
@ -59,6 +64,7 @@ typedef Vector<InternalPowerGroup*> InternalPowerGroupSeq;
|
|||
typedef Vector<LeakagePowerGroup*> LeakagePowerGroupSeq;
|
||||
typedef void (LibertyPort::*LibertyPortBoolSetter)(bool value);
|
||||
typedef Vector<OutputWaveform*> OutputWaveformSeq;
|
||||
typedef vector<string> StdStringSeq;
|
||||
|
||||
class LibertyReader : public LibertyGroupVisitor
|
||||
{
|
||||
|
|
@ -164,6 +170,7 @@ public:
|
|||
virtual void makeInternalPowers(PortGroup *port_group);
|
||||
virtual void makeCellSequentials();
|
||||
virtual void makeCellSequential(SequentialGroup *seq);
|
||||
virtual void makeStatetable();
|
||||
virtual void makeLeakagePowers();
|
||||
virtual void parseCellFuncs();
|
||||
virtual void makeLibertyFunc(const char *expr,
|
||||
|
|
@ -302,6 +309,10 @@ public:
|
|||
virtual void visitClrPresetVar1(LibertyAttr *attr);
|
||||
virtual void visitClrPresetVar2(LibertyAttr *attr);
|
||||
|
||||
virtual void beginStatetable(LibertyGroup *group);
|
||||
virtual void endStatetable(LibertyGroup *group);
|
||||
virtual void visitTable(LibertyAttr *attr);
|
||||
|
||||
virtual void beginTiming(LibertyGroup *group);
|
||||
virtual void endTiming(LibertyGroup *group);
|
||||
virtual void visitRelatedPin(LibertyAttr *attr);
|
||||
|
|
@ -502,12 +513,19 @@ protected:
|
|||
void makeTableAxis(int index);
|
||||
|
||||
StringSeq *parseNameList(const char *name_list);
|
||||
StdStringSeq parseTokenList(const char *token_str,
|
||||
const char separator);
|
||||
LibertyPort *findPort(const char *port_name);
|
||||
LibertyPort *findPort(LibertyCell *cell,
|
||||
const char *port_name);
|
||||
float defaultCap(LibertyPort *port);
|
||||
virtual void visitVariable(LibertyVariable *var);
|
||||
void visitPorts(std::function<void (LibertyPort *port)> func);
|
||||
StateInputValues parseStateInputValues(StdStringSeq &inputs,
|
||||
LibertyAttr *attr);
|
||||
StateInternalValues parseStateInternalValues(StdStringSeq &states,
|
||||
LibertyAttr *attr);
|
||||
|
||||
const char *getAttrString(LibertyAttr *attr);
|
||||
void getAttrInt(LibertyAttr *attr,
|
||||
// Return values.
|
||||
|
|
@ -610,6 +628,7 @@ protected:
|
|||
bool type_bit_to_exists_;
|
||||
SequentialGroup *sequential_;
|
||||
SequentialGroupSeq cell_sequentials_;
|
||||
StatetableGroup *statetable_;
|
||||
TimingGroup *timing_;
|
||||
InternalPowerGroup *internal_power_;
|
||||
LeakagePowerGroup *leakage_power_;
|
||||
|
|
@ -703,6 +722,24 @@ private:
|
|||
int line_;
|
||||
};
|
||||
|
||||
// Liberty group with related_pins group attribute.
|
||||
class RelatedPortGroup
|
||||
{
|
||||
public:
|
||||
explicit RelatedPortGroup(int line);
|
||||
virtual ~RelatedPortGroup();
|
||||
int line() const { return line_; }
|
||||
StringSeq *relatedPortNames() const { return related_port_names_; }
|
||||
void setRelatedPortNames(StringSeq *names);
|
||||
bool isOneToOne() const { return is_one_to_one_; }
|
||||
void setIsOneToOne(bool one);
|
||||
|
||||
protected:
|
||||
StringSeq *related_port_names_;
|
||||
bool is_one_to_one_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
class SequentialGroup
|
||||
{
|
||||
public:
|
||||
|
|
@ -747,21 +784,24 @@ protected:
|
|||
int line_;
|
||||
};
|
||||
|
||||
// Liberty group with related_pins group attribute.
|
||||
class RelatedPortGroup
|
||||
class StatetableGroup
|
||||
{
|
||||
public:
|
||||
explicit RelatedPortGroup(int line);
|
||||
virtual ~RelatedPortGroup();
|
||||
StatetableGroup(StdStringSeq &input_ports,
|
||||
StdStringSeq &internal_ports,
|
||||
int line);
|
||||
const StdStringSeq &inputPorts() const { return input_ports_; }
|
||||
const StdStringSeq &internalPorts() const { return internal_ports_; }
|
||||
void addRow(StateInputValues &input_values,
|
||||
StateInternalValues ¤t_values,
|
||||
StateInternalValues &next_values);
|
||||
StatetableRows &table() { return table_; }
|
||||
int line() const { return line_; }
|
||||
StringSeq *relatedPortNames() const { return related_port_names_; }
|
||||
void setRelatedPortNames(StringSeq *names);
|
||||
bool isOneToOne() const { return is_one_to_one_; }
|
||||
void setIsOneToOne(bool one);
|
||||
|
||||
protected:
|
||||
StringSeq *related_port_names_;
|
||||
bool is_one_to_one_;
|
||||
private:
|
||||
StdStringSeq input_ports_;
|
||||
StdStringSeq internal_ports_;
|
||||
StatetableRows table_;
|
||||
int line_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,4 +53,24 @@ Sequential::~Sequential()
|
|||
preset_->deleteSubexprs();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Statetable::Statetable(LibertyPortSeq &input_ports,
|
||||
LibertyPortSeq &internal_ports,
|
||||
StatetableRows &table) :
|
||||
input_ports_(input_ports),
|
||||
internal_ports_(internal_ports),
|
||||
table_(table)
|
||||
{
|
||||
}
|
||||
|
||||
StatetableRow::StatetableRow(StateInputValues &input_values,
|
||||
StateInternalValues ¤t_values,
|
||||
StateInternalValues &next_values) :
|
||||
input_values_(input_values),
|
||||
current_values_(current_values),
|
||||
next_values_(next_values)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -244,10 +244,10 @@ Power::power(const Corner *corner,
|
|||
macro.incr(inst_power);
|
||||
else if (cell->isPad())
|
||||
pad.incr(inst_power);
|
||||
else if (cell->hasSequentials())
|
||||
sequential.incr(inst_power);
|
||||
else if (inClockNetwork(inst))
|
||||
clock.incr(inst_power);
|
||||
else if (cell->hasSequentials())
|
||||
sequential.incr(inst_power);
|
||||
else
|
||||
combinational.incr(inst_power);
|
||||
total.incr(inst_power);
|
||||
|
|
|
|||
|
|
@ -4371,7 +4371,8 @@ Sdc::findMatchingExceptionsFirstThru(ExceptionPath *exception,
|
|||
findMatchingExceptionsInsts(exception, thru->instances(),
|
||||
first_thru_inst_exceptions_,
|
||||
matches);
|
||||
if (!first_thru_net_exceptions_.empty()) {
|
||||
if (!first_thru_net_exceptions_.empty()
|
||||
&& thru->nets()) {
|
||||
for (const Net *net : *thru->nets()) {
|
||||
// Potential matches includes exceptions that match net that are not
|
||||
// the first exception point.
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ BfsIterator::remove(Vertex *vertex)
|
|||
Level level = vertex->level();
|
||||
if (vertex->bfsInQueue(bfs_index_)
|
||||
&& static_cast<Level>(queue_.size()) > level) {
|
||||
for (Vertex *v : queue_[level]) {
|
||||
for (Vertex *&v : queue_[level]) {
|
||||
if (v == vertex) {
|
||||
v = nullptr;
|
||||
vertex->setBfsInQueue(bfs_index_, false);
|
||||
|
|
|
|||
|
|
@ -1070,7 +1070,7 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
|
|||
clk_path_ = enable_path;
|
||||
Search *search = sta->search();
|
||||
// Same as PathEndPathDelay::findRequired.
|
||||
if (path_delay_ && path_delay_->ignoreClkLatency())
|
||||
if (path_delay_ && ignoreClkLatency(sta))
|
||||
src_clk_arrival_ = search->pathClkPathArrival(&path_);
|
||||
}
|
||||
|
||||
|
|
@ -1081,7 +1081,7 @@ PathEndLatchCheck::PathEndLatchCheck(Path *path,
|
|||
PathVertex *disable_path,
|
||||
MultiCyclePath *mcp,
|
||||
PathDelay *path_delay,
|
||||
Delay src_clk_arrival,
|
||||
Delay src_clk_arrival,
|
||||
Crpr crpr,
|
||||
bool crpr_valid) :
|
||||
PathEndCheck(path, check_arc, check_edge, clk_path, mcp, crpr, crpr_valid),
|
||||
|
|
@ -1221,7 +1221,7 @@ PathEndLatchCheck::latchBorrowInfo(const StaState *sta,
|
|||
Latches *latches = sta->latches();
|
||||
latches->latchBorrowInfo(path_.path(), targetClkPath(), latchDisable(),
|
||||
margin(sta),
|
||||
path_delay_ && path_delay_->ignoreClkLatency(),
|
||||
path_delay_ && ignoreClkLatency(sta),
|
||||
nom_pulse_width, open_latency,
|
||||
latency_diff, open_uncertainty,
|
||||
open_crpr, crpr_diff, max_borrow,
|
||||
|
|
@ -1269,6 +1269,12 @@ PathEndLatchCheck::exceptPathCmp(const PathEnd *path_end,
|
|||
return cmp;
|
||||
}
|
||||
|
||||
bool
|
||||
PathEndLatchCheck::ignoreClkLatency(const StaState *sta) const
|
||||
{
|
||||
return PathEnd::ignoreClkLatency(path_, path_delay_, sta);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
PathEndOutputDelay::PathEndOutputDelay(OutputDelay *output_delay,
|
||||
|
|
@ -1802,7 +1808,7 @@ PathEndPathDelay::typeName() const
|
|||
void
|
||||
PathEndPathDelay::findSrcClkArrival(const StaState *sta)
|
||||
{
|
||||
if (path_delay_->ignoreClkLatency()) {
|
||||
if (ignoreClkLatency(sta)) {
|
||||
Search *search = sta->search();
|
||||
src_clk_arrival_ = search->pathClkPathArrival(&path_);
|
||||
}
|
||||
|
|
@ -1873,7 +1879,7 @@ PathEnd::pathDelaySrcClkOffset(const PathRef &path,
|
|||
float offset = 0.0;
|
||||
const ClockEdge *clk_edge = path.clkEdge(sta);
|
||||
if (clk_edge) {
|
||||
if (path_delay->ignoreClkLatency())
|
||||
if (ignoreClkLatency(path, path_delay, sta))
|
||||
offset = -delayAsFloat(src_clk_arrival);
|
||||
else
|
||||
// Arrival includes src clock edge time that is not counted in the
|
||||
|
|
@ -1883,6 +1889,14 @@ PathEnd::pathDelaySrcClkOffset(const PathRef &path,
|
|||
return offset;
|
||||
}
|
||||
|
||||
bool
|
||||
PathEnd::ignoreClkLatency(const PathRef &path,
|
||||
PathDelay *path_delay,
|
||||
const StaState *sta)
|
||||
{
|
||||
return path_delay->ignoreClkLatency() && !path.isClock(sta);
|
||||
}
|
||||
|
||||
const ClockEdge *
|
||||
PathEndPathDelay::targetClkEdge(const StaState *sta) const
|
||||
{
|
||||
|
|
@ -1927,7 +1941,7 @@ Required
|
|||
PathEndPathDelay::requiredTime(const StaState *sta) const
|
||||
{
|
||||
float delay = path_delay_->delay();
|
||||
if (path_delay_->ignoreClkLatency()) {
|
||||
if (ignoreClkLatency(sta)) {
|
||||
if (minMax(sta) == MinMax::max())
|
||||
return src_clk_arrival_ + delay - margin(sta);
|
||||
else
|
||||
|
|
@ -1943,6 +1957,12 @@ PathEndPathDelay::requiredTime(const StaState *sta) const
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PathEndPathDelay::ignoreClkLatency(const StaState *sta) const
|
||||
{
|
||||
return PathEnd::ignoreClkLatency(path_, path_delay_, sta);
|
||||
}
|
||||
|
||||
int
|
||||
PathEndPathDelay::exceptPathCmp(const PathEnd *path_end,
|
||||
const StaState *sta) const
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ ReportPath::reportFull(const PathEndPathDelay *end)
|
|||
// Based on reportSrcPathArrival.
|
||||
reportBlankLine();
|
||||
PathDelay *path_delay = end->pathDelay();
|
||||
if (path_delay->ignoreClkLatency()) {
|
||||
if (end->ignoreClkLatency(this)) {
|
||||
// Based on reportSrcPath.
|
||||
reportPathHeader();
|
||||
reportPath3(end->path(), expanded, false, false, 0.0,
|
||||
|
|
|
|||
|
|
@ -452,11 +452,11 @@ Search::findPathEnds(ExceptionFrom *from,
|
|||
recovery = removal = false;
|
||||
if (!sdc_->gatedClkChecksEnabled())
|
||||
clk_gating_setup = clk_gating_hold = false;
|
||||
updatePathGroups(group_count, endpoint_count, unique_pins,
|
||||
slack_min, slack_max,
|
||||
group_names, setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold);
|
||||
makePathGroups(group_count, endpoint_count, unique_pins,
|
||||
slack_min, slack_max,
|
||||
group_names, setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold);
|
||||
ensureDownstreamClkPins();
|
||||
PathEndSeq path_ends = path_groups_->makePathEnds(to, unconstrained_paths_,
|
||||
corner, min_max,
|
||||
|
|
@ -3973,7 +3973,7 @@ Search::wnsSlack(Vertex *vertex,
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PathGroups *
|
||||
void
|
||||
Search::makePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
|
|
@ -3987,14 +3987,14 @@ Search::makePathGroups(int group_count,
|
|||
bool clk_gating_setup,
|
||||
bool clk_gating_hold)
|
||||
{
|
||||
return new PathGroups(group_count, endpoint_count, unique_pins,
|
||||
slack_min, slack_max,
|
||||
group_names,
|
||||
setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold,
|
||||
unconstrained_paths_,
|
||||
this);
|
||||
path_groups_ = new PathGroups(group_count, endpoint_count, unique_pins,
|
||||
slack_min, slack_max,
|
||||
group_names,
|
||||
setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold,
|
||||
unconstrained_paths_,
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -4004,27 +4004,6 @@ Search::deletePathGroups()
|
|||
path_groups_ = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Search::updatePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
PathGroupNameSet *group_names,
|
||||
bool setup,
|
||||
bool hold,
|
||||
bool recovery,
|
||||
bool removal,
|
||||
bool clk_gating_setup,
|
||||
bool clk_gating_hold)
|
||||
{
|
||||
path_groups_ = makePathGroups(group_count, endpoint_count, unique_pins,
|
||||
min_slack, max_slack,
|
||||
group_names, setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold);
|
||||
}
|
||||
|
||||
PathGroup *
|
||||
Search::pathGroup(const PathEnd *path_end) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "SearchClass.hh"
|
||||
#include "CircuitSim.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "Property.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
|
|||
Loading…
Reference in New Issue