diff --git a/src/Metrics.tcl b/src/Metrics.tcl index d8c86725d55..b56980fc42e 100644 --- a/src/Metrics.tcl +++ b/src/Metrics.tcl @@ -187,117 +187,7 @@ proc report_units_metric { args } { define_cmd_args "report_design_area_metrics" {} proc report_design_area_metrics { args } { - set db [::ord::get_db] - set dbu_per_uu [expr double([[$db getTech] getDbUnitsPerMicron])] - set block [[$db getChip] getBlock] - set die_bbox [$block getDieArea] - set die_area [expr [$die_bbox dx] * [$die_bbox dy]] - set core_bbox [$block getCoreArea] - set core_area [expr [$core_bbox dx] * [$core_bbox dy]] - - set num_ios [llength [$block getBTerms]] - - set num_insts 0 - set num_stdcells 0 - set num_macros 0 - set num_padcells 0 - set num_cover 0 - - set total_area 0.0 - set stdcell_area 0.0 - set macro_area 0.0 - set padcell_area 0.0 - set cover_area 0.0 - - foreach inst [$block getInsts] { - set inst_master [$inst getMaster] - if { [$inst_master isFiller] } { - continue - } - set wid [$inst_master getWidth] - set ht [$inst_master getHeight] - set inst_area [expr $wid * $ht] - set total_area [expr $total_area + $inst_area] - set num_insts [expr $num_insts + 1] - - if { [$inst_master isBlock] } { - set num_macros [expr $num_macros + 1] - set macro_area [expr $macro_area + $inst_area] - } elseif { [$inst_master isCover] } { - set num_cover [expr $num_cover + 1] - set cover_area [expr $cover_area + $inst_area] - } elseif { [$inst_master isPad] } { - set num_padcells [expr $num_padcells + 1] - set padcell_area [expr $padcell_area + $inst_area] - } else { - set num_stdcells [expr $num_stdcells + 1] - set stdcell_area [expr $stdcell_area + $inst_area] - } - } - - set die_area [expr $die_area / [expr $dbu_per_uu * $dbu_per_uu]] - set core_area [expr $core_area / [expr $dbu_per_uu * $dbu_per_uu]] - set total_area [expr $total_area / [expr $dbu_per_uu * $dbu_per_uu]] - set stdcell_area [expr $stdcell_area / [expr $dbu_per_uu * $dbu_per_uu]] - set macro_area [expr $macro_area / [expr $dbu_per_uu * $dbu_per_uu]] - set padcell_area [expr $padcell_area / [expr $dbu_per_uu * $dbu_per_uu]] - set cover_area [expr $cover_area / [expr $dbu_per_uu * $dbu_per_uu]] - - set total_active_area [expr $stdcell_area + $macro_area] - - if { $core_area > 0 } { - set core_util [expr $total_active_area / $core_area] - if { $core_area > $macro_area } { - set stdcell_util [expr $stdcell_area / [expr $core_area - $macro_area]] - } else { - set stdcell_util 0.0 - } - } else { - set core_util -1.0 - set stdcell_util -1.0 - } - - set std_rows 0 - set std_sites 0 - set rows [dict create] - set sites [dict create] - foreach row [$block getRows] { - set site [$row getSite] - - if { [$site getClass] == "NONE" || [$site getClass] == "CORE" } { - incr std_rows - set std_sites [expr { $std_sites + [$row getSiteCount] }] - } - - dict incr rows [$site getName] 1 - dict incr sites [$site getName] [$row getSiteCount] - } - - utl::metric_int "design__io" $num_ios - utl::metric_float "design__die__area" $die_area - utl::metric_float "design__core__area" $core_area - utl::metric_int "design__instance__count" $num_insts - utl::metric_float "design__instance__area" $total_active_area - utl::metric_int "design__instance__count__stdcell" $num_stdcells - utl::metric_float "design__instance__area__stdcell" $stdcell_area - utl::metric_int "design__instance__count__macros" $num_macros - utl::metric_float "design__instance__area__macros" $macro_area - utl::metric_int "design__instance__count__padcells" $num_padcells - utl::metric_float "design__instance__area__padcells" $padcell_area - utl::metric_int "design__instance__count__cover" $num_cover - utl::metric_float "design__instance__area__cover" $cover_area - utl::metric_float "design__instance__utilization" $core_util - utl::metric_float "design__instance__utilization__stdcell" $stdcell_util - - utl::metric_int "design__rows" $std_rows - dict for {site_name count} $rows { - utl::metric_int "design__rows:$site_name" $count - } - - utl::metric_int "design__sites" $std_sites - dict for {site_name count} $sites { - utl::metric_int "design__sites:$site_name" $count - } + ord::report_design_area_metrics_cmd } # namespace diff --git a/src/OpenRoad.i b/src/OpenRoad.i index 36efba88c2d..a6f25d5065a 100644 --- a/src/OpenRoad.i +++ b/src/OpenRoad.i @@ -648,6 +648,17 @@ void report_hpwl() w.reportHpwl(getLogger()); } +void report_design_area_metrics_cmd() +{ + dbDatabase* db = OpenRoad::openRoad()->getDb(); + odb::dbChip* chip = db->getChip(); + if (chip == nullptr) { + return; + } + dbBlock* block = chip->getBlock(); + odb::blockMetrics(block, getLogger()); } +} // namespace ord + %} // inline diff --git a/src/odb/include/odb/util.h b/src/odb/include/odb/util.h index 2402e73f77a..60912f80b9a 100644 --- a/src/odb/include/odb/util.h +++ b/src/odb/include/odb/util.h @@ -49,6 +49,8 @@ void set_bterm_top_layer_grid(dbBlock* block, bool dbHasCoreRows(dbDatabase* db); +void blockMetrics(dbBlock* block, utl::Logger* logger); + class WireLengthEvaluator { public: diff --git a/src/odb/src/zutil/util.cpp b/src/odb/src/zutil/util.cpp index c009fce8a9e..411706ea9a7 100644 --- a/src/odb/src/zutil/util.cpp +++ b/src/odb/src/zutil/util.cpp @@ -376,6 +376,121 @@ bool hasOneSiteMaster(dbDatabase* db) return false; } +void blockMetrics(dbBlock* block, utl::Logger* logger) +{ + if (block == nullptr) { + return; + } + + const double dbu_per_uu = block->getDbUnitsPerMicron(); + + const odb::Rect die_bbox = block->getDieArea(); + const auto die_area = die_bbox.area(); + + const odb::Rect core_bbox = block->getCoreArea(); + const auto core_area = core_bbox.area(); + + const int num_ios = block->getBTerms().size(); + + const int num_insts = block->getInsts().size(); + int num_stdcells = 0; + int num_macros = 0; + int num_padcells = 0; + int num_cover = 0; + + double stdcell_area = 0.0; + double macro_area = 0.0; + double padcell_area = 0.0; + double cover_area = 0.0; + + for (odb::dbInst* inst : block->getInsts()) { + odb::dbMaster* inst_master = inst->getMaster(); + if (inst_master->isFiller()) { + continue; + } + + const int wid = inst_master->getWidth(); + const int ht = inst_master->getHeight(); + const double inst_area = static_cast(wid) * ht; + + if (inst_master->isBlock()) { + num_macros++; + macro_area += inst_area; + } else if (inst_master->isCover()) { + num_cover++; + cover_area += inst_area; + } else if (inst_master->isPad()) { + num_padcells++; + padcell_area += inst_area; + } else { + num_stdcells++; + stdcell_area += inst_area; + } + } + + const double die_area_um = die_area / (dbu_per_uu * dbu_per_uu); + const double core_area_um = core_area / (dbu_per_uu * dbu_per_uu); + stdcell_area /= (dbu_per_uu * dbu_per_uu); + macro_area /= (dbu_per_uu * dbu_per_uu); + padcell_area /= (dbu_per_uu * dbu_per_uu); + cover_area /= (dbu_per_uu * dbu_per_uu); + + const double total_active_area = stdcell_area + macro_area; + + logger->metric("design__io", num_ios); + logger->metric("design__nets", block->getNets().size()); + logger->metric("design__die__area", die_area_um); + logger->metric("design__core__area", core_area_um); + logger->metric("design__instance__count", num_insts); + logger->metric("design__instance__area", total_active_area); + logger->metric("design__instance__count__stdcell", num_stdcells); + logger->metric("design__instance__area__stdcell", stdcell_area); + logger->metric("design__instance__count__macros", num_macros); + logger->metric("design__instance__area__macros", macro_area); + logger->metric("design__instance__count__padcells", num_padcells); + logger->metric("design__instance__area__padcells", padcell_area); + logger->metric("design__instance__count__cover", num_cover); + logger->metric("design__instance__area__cover", cover_area); + + if (core_area_um > 0) { + logger->metric("design__instance__utilization", + total_active_area / core_area_um); + double stdcell_util = 0.0; + if (core_area_um > macro_area) { + stdcell_util = stdcell_area / (core_area_um - macro_area); + } + logger->metric("design__instance__utilization__stdcell", stdcell_util); + } + + int std_rows = 0; + int64_t std_sites = 0; + std::map rows; + std::map sites; + + for (odb::dbRow* row : block->getRows()) { + odb::dbSite* site = row->getSite(); + + if (site->getClass() == odb::dbSiteClass::NONE + || site->getClass() == odb::dbSiteClass::CORE) { + std_rows++; + std_sites += row->getSiteCount(); + } + + rows[site->getName()]++; + sites[site->getName()] += row->getSiteCount(); + } + + logger->metric("design__rows", std_rows); + for (const auto& [site_name, count] : rows) { + logger->metric("design__rows:" + site_name, count); + } + + logger->metric("design__sites", std_sites); + for (const auto& [site_name, count] : sites) { + logger->metric("design__sites:" + site_name, count); + } +} + int64_t WireLengthEvaluator::hpwl() const { int64_t hpwl_sum = 0;