liberty statetables
commit 02bf64b7d48b36a7ed68ee0781f3039d2cf86b4a
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Aug 3 15:20:51 2024 -0700
power gated clk w/statetable
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 587c217900e92551393a882aa4792369760dbff9
Author: James Cherry <cherry@parallaxsw.com>
Date: Fri Aug 2 16:59:11 2024 -0700
statetable equivalence
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 7093b22a41316b346834c63b1f3de132c4301105
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jul 28 16:54:40 2024 -0700
libert Statetable
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit becfdfc6852d01feb184256c8f966a19e57791d4
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jul 28 10:17:11 2024 -0700
parse statetables
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
535c4ea7d3
commit
7b8720985c
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue