-
Notifications
You must be signed in to change notification settings - Fork 865
Gui external heatmaps #10005
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
base: master
Are you sure you want to change the base?
Gui external heatmaps #10005
Changes from all commits
7601c60
3ec825d
d7d4a36
9f07eba
03d38b9
a25d69f
2e40931
690ce23
4d7e55d
e868ef7
afcfd53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ | |
| #include "displayControls.h" | ||
| #include "drcWidget.h" | ||
| #include "gif.h" | ||
| #include "gui/heatMap.h" | ||
| #include "heatMapGui.h" | ||
| #include "helpWidget.h" | ||
| #include "inspector.h" | ||
|
|
@@ -48,10 +49,12 @@ | |
| #include "odb/dbObject.h" | ||
| #include "odb/dbShape.h" | ||
| #include "odb/geom.h" | ||
| #include "odb/unfoldedModel.h" | ||
| #include "ord/OpenRoad.hh" | ||
| #include "ruler.h" | ||
| #include "scriptWidget.h" | ||
| #include "timingWidget.h" | ||
| #include "utl/CsvParser.h" | ||
| #include "utl/Logger.h" | ||
| #include "utl/decode.h" | ||
| #include "utl/exception.h" | ||
|
|
@@ -1516,6 +1519,88 @@ void Gui::init(odb::dbDatabase* db, sta::dbSta* sta, utl::Logger* logger) | |
| } | ||
| } | ||
|
|
||
| std::string Gui::loadExternalHeatMap(const std::string& file_path) | ||
| { | ||
| // Parse CSV: | ||
| // row 0 = chiplet_name, heatmap_name; | ||
| // rows 1+ = x0,y0,x1,y1,value. | ||
| const auto csv_rows = utl::readCsv(file_path, logger_); | ||
| if (csv_rows.empty()) { | ||
| logger_->error(utl::GUI, 113, "No data in CSV file: {}", file_path); | ||
| } | ||
| if (csv_rows[0].size() != 2) { | ||
| logger_->error(utl::GUI, | ||
| 114, | ||
| "Invalid CSV file: {} - expected 2 columns in first row; " | ||
| "(chiplet_name, heatmap_name), got {}", | ||
| file_path, | ||
| csv_rows[0].size()); | ||
| } | ||
| const std::string chiplet_name = csv_rows[0][0]; | ||
| const std::string heatmap_name = csv_rows[0][1]; | ||
| std::vector<ExternalHeatMapDataSource::Entry> data; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| for (size_t i = 1; i < csv_rows.size(); ++i) { | ||
| const auto& row = csv_rows[i]; | ||
| if (row.size() != 5) { | ||
| logger_->error( | ||
| utl::GUI, | ||
| 115, | ||
| "Invalid CSV file: {} - expected 5 columns in row {}, got {}", | ||
| file_path, | ||
| i, | ||
| row.size()); | ||
| } | ||
| try { | ||
| data.push_back({std::stod(row[0]), | ||
| std::stod(row[1]), | ||
| std::stod(row[2]), | ||
| std::stod(row[3]), | ||
| std::stod(row[4])}); | ||
| } catch (const std::exception& e) { | ||
| logger_->error(utl::GUI, | ||
| 116, | ||
| "Invalid CSV file: {} - exception in row {}: {}", | ||
| file_path, | ||
| i, | ||
| std::string(e.what())); | ||
| } | ||
| } | ||
| odb::dbChip* chip = nullptr; | ||
| odb::dbTransform transform; | ||
|
|
||
| if (db_->getUnfoldedModel() != nullptr) { | ||
| auto* unfolded_chip | ||
| = db_->getUnfoldedModel()->findUnfoldedChip(chiplet_name); | ||
| if (unfolded_chip != nullptr) { | ||
| chip = unfolded_chip->chip_inst_path.back()->getMasterChip(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Accessing if (unfolded_chip->chip_inst_path.empty()) {
chip = db_->getChip();
} else {
chip = unfolded_chip->chip_inst_path.back()->getMasterChip();
} |
||
| transform = unfolded_chip->transform; | ||
| } else { | ||
| logger_->error(utl::GUI, | ||
| 117, | ||
| "Chiplet {} not found in the loaded design", | ||
| chiplet_name); | ||
| } | ||
| } else { | ||
| if (db_->getChip() == nullptr | ||
| || db_->getChip()->getName() != chiplet_name) { | ||
| logger_->error(utl::GUI, | ||
| 118, | ||
| "Chiplet {} not found in the loaded design", | ||
| chiplet_name); | ||
| } | ||
| chip = db_->getChip(); | ||
| } | ||
| std::string short_name | ||
| = "External_" + std::to_string(owned_heat_maps_.size() + 1); | ||
| auto source = std::make_shared<ExternalHeatMapDataSource>( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "gui::ExternalHeatMapDataSource" is directly included [misc-include-cleaner] auto source = std::make_shared<ExternalHeatMapDataSource>(
^ |
||
| logger_, heatmap_name, short_name, std::move(data)); | ||
| source->setChip(chip); | ||
| source->setTransform(transform); | ||
| registerHeatMap(source.get()); | ||
| owned_heat_maps_.push_back(std::move(source)); | ||
| return short_name; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: constness of 'short_name' prevents automatic move [performance-no-automatic-move] return short_name;
^ |
||
| } | ||
|
|
||
| void Gui::selectHelp(const std::string& item) | ||
| { | ||
| if (!enabled()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -725,6 +725,15 @@ void dump_heatmap(const std::string& name, const std::string& file) | |
| gui->dumpHeatMap(name, file); | ||
| } | ||
|
|
||
| std::string load_external_heatmap(const std::string& file_path) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no tcl command, maybe call this load_heatmap (unless it's specific to the chiplet, in which case that should be clear from the name |
||
| { | ||
| if (!check_gui("load_external_heatmap")) { | ||
| return ""; | ||
| } | ||
| auto gui = gui::Gui::get(); | ||
| return gui->loadExternalHeatMap(file_path); | ||
| } | ||
|
|
||
| void timing_cone(odb::dbITerm* iterm, bool fanin, bool fanout) | ||
| { | ||
| if (!check_gui("timing_cone")) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -247,4 +247,35 @@ sta::Scene* PowerDensityDataSource::getScene() const | |||||
| return nullptr; | ||||||
| } | ||||||
|
|
||||||
| ////////// | ||||||
|
|
||||||
| ExternalHeatMapDataSource::ExternalHeatMapDataSource( | ||||||
| utl::Logger* /* logger */, | ||||||
| const std::string& /* name */, | ||||||
| const std::string& unique_short_name, | ||||||
| std::vector<Entry> /* data */) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: the parameter #4 is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
Suggested change
src/gui/include/gui/heatMap.h:385: - std::vector<Entry> data);
+ const std::vector<Entry>& data);
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maliberty I am not sure how I can bypass this. Clearly this suggestion is correct for the stub implementation because we don't utilize the vector in any way. However, it is better in the main implementation to pass by value as the constructor is intended to be the sink endpoint for that parameter. |
||||||
| : HeatMapDataSource(nullptr, "", unique_short_name, "") | ||||||
| { | ||||||
| } | ||||||
|
|
||||||
| bool ExternalHeatMapDataSource::populateMap() | ||||||
| { | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| odb::Rect ExternalHeatMapDataSource::getBounds() const | ||||||
| { | ||||||
| return HeatMapDataSource::getBounds(); | ||||||
| } | ||||||
|
|
||||||
| void ExternalHeatMapDataSource::combineMapData( | ||||||
| bool /* base_has_value */, | ||||||
| double& /* base */, | ||||||
| const double /* new_data */, | ||||||
| const double /* data_area */, | ||||||
| const double /* intersection_area */, | ||||||
| const double /* rect_area */) | ||||||
| { | ||||||
| } | ||||||
|
|
||||||
| } // namespace gui | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // Copyright (c) 2026, The OpenROAD Authors | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| namespace utl { | ||
|
|
||
| class Logger; | ||
|
|
||
| // Reads a delimiter-separated file and returns all non-empty rows. | ||
| // Each row is a vector of trimmed cell strings. | ||
| // Logs an error and returns an empty result if the file cannot be opened. | ||
| std::vector<std::vector<std::string>> readCsv(const std::string& file_path, | ||
| Logger* logger, | ||
| char delimiter = ','); | ||
|
|
||
| } // namespace utl |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // Copyright (c) 2026, The OpenROAD Authors | ||
|
|
||
| #include "utl/CsvParser.h" | ||
|
|
||
| #include <fstream> | ||
| #include <sstream> | ||
| #include <string> | ||
| #include <utility> | ||
| #include <vector> | ||
|
|
||
| #include "utl/Logger.h" | ||
|
|
||
| namespace utl { | ||
|
|
||
| namespace { | ||
|
|
||
| static std::string trim(const std::string& s) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::string" is directly included [misc-include-cleaner] src/utl/src/CsvParser.cpp:7: + #include <string>
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use boost::trim ? |
||
| { | ||
| const auto start = s.find_first_not_of(" \t\r\n"); | ||
| const auto end = s.find_last_not_of(" \t\r\n"); | ||
| if (start == std::string::npos || end == std::string::npos) { | ||
| return ""; | ||
| } | ||
| return s.substr(start, end - start + 1); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| std::vector<std::vector<std::string>> readCsv(const std::string& file_path, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::vector" is directly included [misc-include-cleaner] src/utl/src/CsvParser.cpp:7: + #include <vector> |
||
| Logger* logger, | ||
| char delimiter) | ||
| { | ||
| std::ifstream in(file_path); | ||
| if (!in.is_open()) { | ||
| logger->error(utl::UTL, 201, "Unable to open {}", file_path); | ||
| return {}; | ||
| } | ||
|
|
||
| std::vector<std::vector<std::string>> rows; | ||
| std::string line; | ||
| while (std::getline(in, line)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::getline" is directly included [misc-include-cleaner] while (std::getline(in, line)) {
^ |
||
| if (line.empty()) { | ||
| continue; | ||
| } | ||
| std::vector<std::string> cells; | ||
| std::stringstream ss(line); | ||
| std::string cell; | ||
| while (std::getline(ss, cell, delimiter)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::getline" is directly included [misc-include-cleaner] while (std::getline(ss, cell, delimiter)) {
^ |
||
| cells.push_back(trim(cell)); | ||
| } | ||
|
Comment on lines
+49
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current CSV parsing logic using |
||
| rows.push_back(std::move(cells)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: no header providing "std::move" is directly included [misc-include-cleaner] src/utl/src/CsvParser.cpp:7: + #include <utility> |
||
| } | ||
| return rows; | ||
| } | ||
|
|
||
| } // namespace utl | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is chiplet_name here? that seems somewhat specific
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To support 3D designs. When you have multiple chiplets in a system, the chiplet name is needed to apply the correct transformation per chiplet.