Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dbSta: Add create_cell_usage_snapshot command #6469

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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/dbSta/include/db_sta/dbSta.hh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@

#pragma once

#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "odb/db.h"
#include "odb/dbBlockCallBackObj.h"
Expand Down Expand Up @@ -191,6 +195,30 @@ class dbSta : public Sta, public ord::OpenRoadObserver
InstType getInstanceType(odb::dbInst* inst);
void report_cell_usage(odb::dbModule* module, bool verbose);

// Creates a cell usage snapshot for the given module at the given stage.
// The snapshot is written to the given path as a JSON file.
void CreateCellUsageSnapshot(
odb::dbModule* module, std::string_view path, std::string_view stage);

// Holds the usage information of a specific cell.
struct CellUsageInfo {
// Name of the cell.
std::string name;

// Number of instances of the cell.
int count = 0;

// Area of the cell in microns^2. Total area of the cell instances can be
// calculated by multiplying the count by this value.
double area = 0.0;
};

// Holds a snapshot of cell usage information at a given stage.
struct CellUsageSnapshot {
std::string stage;
std::vector<CellUsageInfo> cells_usage_info;
};

BufferUse getBufferUse(sta::LibertyCell* buffer);

using Sta::netSlack;
Expand Down
93 changes: 93 additions & 0 deletions src/dbSta/src/dbSta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,21 @@
#include <tcl.h>

#include <algorithm> // min
#include <cmath>
#include <cstdint>
#include <fstream>
#include <map>
#include <mutex>
#include <regex>
#include <string>
#include <string_view>
#include <vector>

#include "AbstractPathRenderer.h"
#include "AbstractPowerDensityDataSource.h"
#include "boost/algorithm/string/join.hpp"
#include "boost/json.hpp"
#include "boost/json/src.hpp"
#include "dbSdcNetwork.hh"
#include "db_sta/MakeDbSta.hh"
#include "db_sta/dbNetwork.hh"
Expand Down Expand Up @@ -80,8 +90,54 @@ dbSta* makeDbSta()
}
} // namespace ord

namespace boost::json {
void tag_invoke(json::value_from_tag, json::value& json_value,
ord::dbSta::CellUsageInfo const& cell_usage_info) {
json_value = {{"name", cell_usage_info.name},
{"count", cell_usage_info.count},
{"area", cell_usage_info.area}};
}

void tag_invoke(json::value_from_tag, json::value& json_value,
ord::dbSta::CellUsageSnapshot const& cell_usage_snapshot) {
json_value = {
{"stage", cell_usage_snapshot.stage},
{"cell_usage_info",
boost::json::value_from(cell_usage_snapshot.cells_usage_info)}};
}

ord::dbSta::CellUsageInfo tag_invoke(value_to_tag<ord::dbSta::CellUsageInfo>,
value const& json_value) {
return {value_to<std::string>(json_value.at("name")),
value_to<int>(json_value.at("count")),
value_to<double>(json_value.at("area"))};
}

ord::dbSta::CellUsageSnapshot tag_invoke(
value_to_tag<ord::dbSta::CellUsageSnapshot>, value const& json_value) {
return {value_to<std::string>(json_value.at("stage")),
value_to<std::vector<ord::dbSta::CellUsageInfo>>(
json_value.at("cell_usage_info"))};
}

} // namespace boost::json

namespace sta {

namespace {

constexpr std::string_view kCellUsageSnapshotPrefix = "cell_usage_snapshot";
constexpr std::string_view kCellUsageSnapshotFileExtension = "json";

std::string GetCellSnapshotName(const std::string& module,
const std::string& stage) {
std::vector<std::string> components = {std::string(kCellUsageSnapshotPrefix),
module, stage};
return boost::algorithm::join(components, "-");
}

} // namespace

using utl::Logger;
using utl::STA;

Expand Down Expand Up @@ -579,6 +635,43 @@ void dbSta::report_cell_usage(odb::dbModule* module, const bool verbose)
}
}

void dbSta::CreateCellUsageSnapshot(odb::dbModule* module,
std::string_view path,
std::string_view stage) {
std::map<std::string, CellUsageInfo> name_to_cell_usage_info;
dbBlock* block = db_->getChip()->getBlock();
const std::vector<dbInst*> insts = module->getLeafInsts();
const double area_to_microns = std::pow(block->getDbUnitsPerMicron(), 2);
for (const dbInst* inst : insts) {
const std::string& cell_name = inst->getMaster()->getName();
auto [it, inserted] = name_to_cell_usage_info.insert(
{cell_name, CellUsageInfo{
.name = cell_name,
.count = 1,
.area = inst->getMaster()->getArea() / area_to_microns,
}});
if (!inserted) {
it->second.count++;
}
}

CellUsageSnapshot cell_usage_snapshot{.stage = std::string(stage)};
cell_usage_snapshot.cells_usage_info.reserve(name_to_cell_usage_info.size());
for (const auto& [cell_name, cell_usage_info] : name_to_cell_usage_info) {
cell_usage_snapshot.cells_usage_info.push_back(cell_usage_info);
}
boost::json::value output = boost::json::value_from(cell_usage_snapshot);
logger_->report("{}", output.as_object());

std::ofstream file;
file.open(
std::string(path) + "/" +
GetCellSnapshotName(std::string(module->getName()), std::string(stage)) +
"." + std::string(kCellUsageSnapshotFileExtension));
file << output.as_object();
file.close();
}

BufferUse dbSta::getBufferUse(sta::LibertyCell* buffer)
{
return buffer_use_analyser_->getBufferUse(buffer);
Expand Down
10 changes: 10 additions & 0 deletions src/dbSta/src/dbSta.i
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ report_cell_usage_cmd(odb::dbModule* mod, const bool verbose)
sta->report_cell_usage(mod, verbose);
}


void
create_cell_usage_snapshot_cmd(
odb::dbModule* module, const char* path, const char* stage) {
cmdLinkedNetwork();
ord::OpenRoad *openroad = ord::getOpenRoad();
sta::dbSta *sta = openroad->getSta();
sta->CreateCellUsageSnapshot(module, std::string(path), std::string(stage));
}

// Copied from sta/verilog/Verilog.i because we don't want sta::read_verilog
// that is in the same file.
void
Expand Down
30 changes: 30 additions & 0 deletions src/dbSta/src/dbSta.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,36 @@ proc report_cell_usage { args } {
report_cell_usage_cmd $module [info exists flags(-verbose)]
}


define_cmd_args "create_cell_usage_snapshot" { \
[-path path]\
[-stage stage]
}

proc create_cell_usage_snapshot { args } {
parse_key_args "create_cell_usage_snapshot" args keys {-path -stage} \
flags {}

if { [ord::get_db_block] == "NULL" } {
sta_error 1001 "No design block found."
}
set module_name [[ord::get_db_block] getTopModule]

if { [info exists keys(-path)] } {
set path_name $keys(-path)
} else {
sta_error 1002 "Missing argument -path"
}

if { [info exists keys(-stage)] } {
set stage_name $keys(-stage)
} else {
sta_error 1003 "Missing argument -stage"
}

create_cell_usage_snapshot_cmd $module_name $path_name $stage_name
}

# redefine sta::sta_warn/error to call utl::warn/error
proc sta_error { id msg } {
utl::error STA $id $msg
Expand Down
1 change: 1 addition & 0 deletions src/dbSta/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ or_integration_tests(
TESTS
block_sta1
constant1
create_cell_usage_snapshot
find_clks1
find_clks2
hier2
Expand Down
1 change: 1 addition & 0 deletions src/dbSta/test/cell_usage_snapshot-top-test_stage.jsonok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"stage":"test_stage","cell_usage_info":[{"name":"snl_bufx1","count":4,"area":1E3},{"name":"snl_ffqx1","count":2,"area":1E3}]}
17 changes: 17 additions & 0 deletions src/dbSta/test/create_cell_usage_snapshot.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Test for creating a cell usage snapshot.

# Test environment setup.
set snapshot_file_name cell_usage_snapshot-top-test_stage.json
source "helpers.tcl"
make_result_dir

# Populate DB with the test design.
read_lef liberty1.lef
read_liberty liberty1.lib
read_verilog hier1.v
link_design top

# Create the cell usage snapshot and compare it to the golden file.
create_cell_usage_snapshot -path $result_dir -stage test_stage
diff_files cell_usage_snapshot-top-test_stage.jsonok $result_dir/$snapshot_file_name

7 changes: 7 additions & 0 deletions test/helpers.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
set test_dir [file dirname [file normalize [info script]]]
set result_dir [file join $test_dir "results"]

proc make_result_dir {} {
variable result_dir
if { ![file exists $result_dir] } {
file mkdir $result_dir
}
}

proc make_result_file { filename } {
variable result_dir
if { ![file exists $result_dir] } {
Expand Down