Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/database/manager/parser/liberty/Lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,23 @@ LibPort& LibPort::operator=(LibPort&& rhs) noexcept
return *this;
}

void LibPort::inheritBusAttributes(const LibPort& bus)
{
_port_type = bus._port_type;
_is_clock_pin = bus._is_clock_pin;
_clock_gate_clock_pin = bus._clock_gate_clock_pin;
_clock_gate_enable_pin = bus._clock_gate_enable_pin;
_is_clock = bus._is_clock;
_func_expr = bus._func_expr;
_func_expr_str = bus._func_expr_str;
_port_cap = bus._port_cap;
_port_caps = bus._port_caps;
_cap_limits = bus._cap_limits;
_slew_limits = bus._slew_limits;
_fanout_load = bus._fanout_load;
_max_fanout = bus._max_fanout;
}

/**
* @brief Set cap of max/min, rise/fall.
*
Expand Down Expand Up @@ -1067,6 +1084,17 @@ LibPortBus::LibPortBus(const char* port_bus_name) : LibPort(port_bus_name)
{
}

LibPort* LibPortBus::operator[](int index)
{
std::string port_name = std::string(get_port_name()) + "[" + std::to_string(index) + "]";
for (std::unique_ptr<LibPort>& port : _ports) {
if (port_name == port->get_port_name()) {
return port.get();
}
}
return nullptr;
}

LibLeakagePower::LibLeakagePower() : _owner_cell(nullptr)
{
}
Expand Down
5 changes: 4 additions & 1 deletion src/database/manager/parser/liberty/Lib.hh
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ class LibPort : public LibObject
LibPort(LibPort&& other) noexcept;
LibPort& operator=(LibPort&& rhs) noexcept;

void inheritBusAttributes(const LibPort& bus);

const char* get_port_name() { return _port_name.c_str(); }
void set_ower_cell(LibCell* ower_cell) { _ower_cell = ower_cell; }
LibCell* get_ower_cell() { return _ower_cell; }
Expand Down Expand Up @@ -715,11 +717,12 @@ class LibPortBus : public LibPort
void addlibertyPort(std::unique_ptr<LibPort>&& port) { _ports.push_back(std::move(port)); }

auto getBusSize() { return _bus_type ? _bus_type->get_bit_width() : _ports.size(); }
auto& get_ports() { return _ports; }

void set_bus_type(LibType* bus_type) { _bus_type = bus_type; }
auto* get_bus_type() { return _bus_type; }

LibPort* operator[](int index) { return _ports.empty() ? this : _ports[index].get(); }
LibPort* operator[](int index);

private:
absl::InlinedVector<std::unique_ptr<LibPort>, 64> _ports; //!< The bus ports.
Expand Down
129 changes: 43 additions & 86 deletions src/database/manager/parser/liberty/LibParserCpp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,8 @@ unsigned LibertyReader::visitLeakagePower(LibertyGroupStmt* group) {
unsigned LibertyReader::visitBus(LibertyGroupStmt* group) {
LibBuilder* lib_builder = get_library_builder();
LibCell* cell = lib_builder->get_cell();
LibPort* previous_port = lib_builder->get_port();
LibPortBus* previous_bus = lib_builder->get_port_bus();

const char* bus_port_name = getGroupAttriName(group);
auto lib_port_bus = std::make_unique<LibPortBus>(bus_port_name);
Expand All @@ -1249,7 +1251,8 @@ unsigned LibertyReader::visitBus(LibertyGroupStmt* group) {
unsigned is_ok = visitStmtInGroup(group);

// reset the port bus pointer.
lib_builder->set_port_bus(nullptr);
lib_builder->set_port(previous_port);
lib_builder->set_port_bus(previous_bus);

return is_ok;
}
Expand All @@ -1261,55 +1264,55 @@ unsigned LibertyReader::visitBus(LibertyGroupStmt* group) {
* @return unsigned return 1 if success, else 0
*/
unsigned LibertyReader::visitPin(LibertyGroupStmt* group) {
return visitPinGroup(group);
}

template <typename Group>
unsigned LibertyReader::visitPinGroup(Group* group)
{
LibBuilder* lib_builder = get_library_builder();
LibCell* cell = lib_builder->get_cell();

LibPortBus* port_bus = lib_builder->get_port_bus();
LibPort* previous_port = lib_builder->get_port();
const char* port_name = getGroupAttriName(group);
unsigned is_ok = 1;

auto create_port = [lib_builder, cell](const char* port_name) {
auto lib_port = std::make_unique<LibPort>(port_name);
auto create_port = [&](const char* name) {
std::unique_ptr<LibPort> lib_port = std::make_unique<LibPort>(name);
lib_port->set_ower_cell(cell);

if (auto* port_bus = lib_builder->get_port_bus(); !port_bus) {
lib_builder->set_port(lib_port.get());
cell->addLibertyPort(std::move(lib_port));
} else {
lib_port->set_port_type(port_bus->get_port_type());
port_bus->addlibertyPort(std::move(lib_port));
if (port_bus) {
lib_port->inheritBusAttributes(*port_bus);
}
};

auto has_bus_range_marker = [](const char* port_name) {
for (const char* ch = port_name; *ch != '\0'; ++ch) {
if (*ch == '[') {
return true;
}
lib_builder->set_port(lib_port.get());
if (port_bus) {
port_bus->addlibertyPort(std::move(lib_port));
} else {
cell->addLibertyPort(std::move(lib_port));
}
return false;
// Every bit owns its attributes and tables, including conditional arcs.
is_ok &= visitStmtInGroup(group);
};

std::vector<std::string> ret_val;
if (has_bus_range_marker(port_name)) {
std::string regex_pattern = "([A-Za-z]+)\\[(\\d+):(\\d+)\\]";
ret_val = matchPattern(port_name, regex_pattern);
std::vector<std::string> range;
if (std::string_view(port_name).find('[') != std::string_view::npos) {
range = matchPattern(port_name, "(.+)\\[(-?\\d+):(-?\\d+)\\]");
}
if (ret_val.empty()) {
if (range.empty()) {
create_port(port_name);
} else {
std::string port_bus_name = ret_val[1];
int port_range_left = std::atoi(ret_val[2].c_str());
int port_range_right = std::atoi(ret_val[3].c_str());

for (int index = port_range_left; index >= port_range_right; --index) {
std::string one_port_name = makeIndexedName(port_bus_name, index);
create_port(one_port_name.c_str());
int left = std::stoi(range[2]);
int right = std::stoi(range[3]);
int step = left <= right ? 1 : -1;
for (int index = left;; index += step) {
std::string name = makeIndexedName(range[1], index);
create_port(name.c_str());
if (index == right) {
break;
}
}
}

unsigned is_ok = visitStmtInGroup(group);
// reset the port pointer.
lib_builder->set_port(nullptr);

lib_builder->set_port(previous_port);
return is_ok;
}

Expand Down Expand Up @@ -1802,6 +1805,8 @@ unsigned LibertyReader::visitLeakagePower(liberty_ast::LibGroup* group) {
unsigned LibertyReader::visitBus(liberty_ast::LibGroup* group) {
LibBuilder* lib_builder = get_library_builder();
LibCell* cell = lib_builder->get_cell();
LibPort* previous_port = lib_builder->get_port();
LibPortBus* previous_bus = lib_builder->get_port_bus();

const char* port_bus_name = getGroupAttriName(group);

Expand All @@ -1814,62 +1819,14 @@ unsigned LibertyReader::visitBus(liberty_ast::LibGroup* group) {

unsigned is_ok = visitStmtInGroup(group);
// reset the port bus pointer.
lib_builder->set_port_bus(nullptr);
lib_builder->set_port(previous_port);
lib_builder->set_port_bus(previous_bus);

return is_ok;
}

unsigned LibertyReader::visitPin(liberty_ast::LibGroup* group) {
LibBuilder* lib_builder = get_library_builder();
LibCell* cell = lib_builder->get_cell();

const char* port_name = getGroupAttriName(group);

auto create_port = [lib_builder, cell](const char* port_name) {
auto lib_port = std::make_unique<LibPort>(port_name);
lib_port->set_ower_cell(cell);

if (auto* port_bus = lib_builder->get_port_bus(); !port_bus) {
lib_builder->set_port(lib_port.get());
cell->addLibertyPort(std::move(lib_port));
} else {
lib_port->set_port_type(port_bus->get_port_type());
port_bus->addlibertyPort(std::move(lib_port));
}
};

auto has_bus_range_marker = [](const char* port_name) {
for (const char* ch = port_name; *ch != '\0'; ++ch) {
if (*ch == '[') {
return true;
}
}
return false;
};

std::vector<std::string> ret_val;
if (has_bus_range_marker(port_name)) {
std::string regex_pattern = "([A-Za-z]+)\\[(\\d+):(\\d+)\\]";
ret_val = matchPattern(port_name, regex_pattern);
}
if (ret_val.empty()) {
create_port(port_name);
} else {
std::string port_bus_name = ret_val[1];
int port_range_left = std::atoi(ret_val[2].c_str());
int port_range_right = std::atoi(ret_val[3].c_str());

for (int index = port_range_left; index >= port_range_right; --index) {
std::string one_port_name = makeIndexedName(port_bus_name, index);
create_port(one_port_name.c_str());
}
}

unsigned is_ok = visitStmtInGroup(group);
// reset the port pointer.
lib_builder->set_port(nullptr);

return is_ok;
return visitPinGroup(group);
}

unsigned LibertyReader::visitTiming(liberty_ast::LibGroup* group) {
Expand Down
3 changes: 3 additions & 0 deletions src/database/manager/parser/liberty/LibParserCpp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ class LibertyReader
auto* get_library_builder() { return _library_builder; }

private:
template <typename Group>
unsigned visitPinGroup(Group* group);

const char* getGroupAttriName(LibertyGroupStmt* group);
unsigned visitStmtInGroup(LibertyGroupStmt* group);

Expand Down
13 changes: 13 additions & 0 deletions src/operation/iSTA/interface/STAInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,11 @@ void STAInterface::wrapTimingCell(idb::LibCell* lib_cell)
for (std::unique_ptr<idb::LibPort>& lib_port : lib_cell->get_cell_ports()) {
wrapTimingCellPort(timing_cell, lib_port.get());
}
for (std::unique_ptr<idb::LibPortBus>& lib_bus : lib_cell->get_cell_buses()) {
for (std::unique_ptr<idb::LibPort>& lib_port : lib_bus->get_ports()) {
wrapTimingCellPort(timing_cell, lib_port.get());
}
}

wrapTimingCellSequential(timing_cell, lib_cell);
wrapTimingCellPower(timing_cell, lib_cell);
Expand Down Expand Up @@ -764,6 +769,14 @@ void STAInterface::wrapTimingCellPower(TimingCell& timing_cell, idb::LibCell* li
timing_cell.get_power_arc_list().push_back(wrapTimingPortPowerArc(internal_power_info.get(), port_name, lib_library));
}
}
for (std::unique_ptr<idb::LibPortBus>& lib_bus : lib_cell->get_cell_buses()) {
for (std::unique_ptr<idb::LibPort>& lib_port : lib_bus->get_ports()) {
std::string port_name = lib_port->get_port_name();
for (std::unique_ptr<idb::LibInternalPowerInfo>& internal_power_info : lib_port->get_internal_powers()) {
timing_cell.get_power_arc_list().push_back(wrapTimingPortPowerArc(internal_power_info.get(), port_name, lib_library));
}
}
}
}

void STAInterface::wrapTimingCellLeakagePower(TimingCell& timing_cell, idb::LibCell* lib_cell)
Expand Down
50 changes: 37 additions & 13 deletions src/operation/iSTA/source/module/timing_reporter/TimingReporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ namespace ista {

namespace {

constexpr int kTimingFanoutWidth = 8;
constexpr int kTimingValueWidth = 16;
constexpr int kTimingTableExtraWidth = 2 + kTimingFanoutWidth + 2 * kTimingValueWidth + 2;

std::string escapeJsonString(const std::string& value)
{
static constexpr char kHexDigits[] = "0123456789abcdef";
Expand Down Expand Up @@ -221,6 +225,7 @@ void TimingReporter::outputReportHeader(std::ofstream* report_file, DelayType de
(*report_file) << "Nworst : " << STADM.getConfig().endpoint_path_report_number << "\n";
(*report_file) << "MaxPaths : " << STADM.getConfig().path_report_number << "\n";
(*report_file) << "SortBy : slack\n";
(*report_file) << "Fanout : number of unique load pins driven by the point (blank for non-drivers)\n";
(*report_file) << "****************************************\n\n";
}

Expand Down Expand Up @@ -1118,7 +1123,7 @@ std::size_t TimingReporter::outputTimingPointList(std::ofstream* report_file, Ti
{
std::size_t label_width = getTimingLineLabelWidth(timing_path, delay_type);
outputTimingPointHeader(report_file, label_width);
(*report_file) << " " << std::string(label_width + 28, '-') << "\n";
(*report_file) << " " << std::string(label_width + kTimingTableExtraWidth, '-') << "\n";
outputLaunchClockInfo(report_file, timing_path, delay_type, label_width);
bool is_first_point = true;
for (TimingPathPoint& path_point : timing_path.get_point_list()) {
Expand Down Expand Up @@ -1197,7 +1202,8 @@ void TimingReporter::updateTimingLineLabelWidth(std::size_t& label_width, std::s

void TimingReporter::outputTimingPointHeader(std::ofstream* report_file, std::size_t label_width)
{
(*report_file) << " " << std::left << std::setw(label_width) << "Point" << std::right << std::setw(10) << "Incr" << std::setw(11) << "Path"
(*report_file) << " " << std::left << std::setw(label_width + 2) << "Point" << std::right << std::setw(kTimingFanoutWidth) << "Fanout"
<< std::setw(kTimingValueWidth) << "Incr" << std::setw(kTimingValueWidth) << "Path"
<< "\n";
}

Expand Down Expand Up @@ -1240,14 +1246,11 @@ std::string TimingReporter::getLaunchClockEdgeText(TimingPath& timing_path, Dela
}

void TimingReporter::outputTimingLine(std::ofstream* report_file, std::string_view label, double incr, double path, bool has_incr, std::string transition,
std::size_t label_width)
std::size_t label_width, std::optional<std::size_t> fanout)
{
if (has_incr) {
(*report_file) << " " << std::left << std::setw(label_width + 2) << label << getNumberString(incr) << "\n";
(*report_file) << " " << std::setw(label_width + 13) << "" << getNumberString(path);
} else {
(*report_file) << " " << std::left << std::setw(label_width + 13) << label << getNumberString(path);
}
(*report_file) << " " << std::left << std::setw(label_width + 2) << label << std::right << std::setw(kTimingFanoutWidth)
<< (fanout.has_value() ? std::to_string(*fanout) : "") << std::setw(kTimingValueWidth) << (has_incr ? getNumberString(incr) : "")
<< std::setw(kTimingValueWidth) << getNumberString(path);
if (!transition.empty()) {
(*report_file) << " " << transition;
}
Expand All @@ -1256,7 +1259,7 @@ void TimingReporter::outputTimingLine(std::ofstream* report_file, std::string_vi

void TimingReporter::outputTimingSummaryLine(std::ofstream* report_file, std::string label, double value, std::size_t label_width)
{
(*report_file) << " " << std::left << std::setw(label_width + 13) << label << getNumberString(value) << "\n";
outputTimingLine(report_file, label, 0.0, value, false, "", label_width);
}

std::string TimingReporter::getClockName(TimingPath& timing_path)
Expand Down Expand Up @@ -1344,7 +1347,28 @@ void TimingReporter::outputTimingPoint(std::ofstream* report_file, TimingPath& t
arc_delay = path_point.get_arrival() - timing_path.get_launch_time();
}
outputTimingLine(report_file, getPointLabel(path_point), arc_delay, path_point.get_arrival(), true, GetTransTypeInitial()(path_point.get_trans_type()),
label_width);
label_width, getPinFanout(path_point.get_pin_name()));
}

std::optional<std::size_t> TimingReporter::getPinFanout(const std::string& pin_name)
{
Database& database = STADM.getDatabase();
auto pin_it = database.get_pin_map().find(pin_name);
if (pin_it == database.get_pin_map().end()) {
return std::nullopt;
}
auto net_it = database.get_net_map().find(pin_it->second.get_net_name());
if (net_it == database.get_net_map().end()) {
return std::nullopt;
}
Net& net = net_it->second;
const std::vector<std::string>& drivers = net.get_driver_pin_list();
if (net.get_driver_pin() != pin_name && std::find(drivers.begin(), drivers.end(), pin_name) == drivers.end()) {
return std::nullopt;
}
std::set<std::string> loads(net.get_load_pin_list().begin(), net.get_load_pin_list().end());
loads.erase(pin_name);
return loads.size();
}

std::string TimingReporter::getNumberString(double value)
Expand Down Expand Up @@ -1478,10 +1502,10 @@ std::string TimingReporter::getPinLabel(std::string& pin_name)

void TimingReporter::outputTimingPathSummary(std::ofstream* report_file, TimingPath& timing_path, std::size_t label_width)
{
(*report_file) << " " << std::string(label_width + 28, '-') << "\n";
(*report_file) << " " << std::string(label_width + kTimingTableExtraWidth, '-') << "\n";
outputTimingSummaryLine(report_file, "data required time", timing_path.get_required_time(), label_width);
outputTimingSummaryLine(report_file, "data arrival time", -timing_path.get_path_delay(), label_width);
(*report_file) << " " << std::string(label_width + 28, '-') << "\n";
(*report_file) << " " << std::string(label_width + kTimingTableExtraWidth, '-') << "\n";
outputTimingSummaryLine(report_file, STAUTIL.getString("slack (", getSlackStatus(timing_path), ")"), timing_path.get_slack(), label_width);
(*report_file) << "\n\n";
}
Expand Down
Loading
Loading