diff --git a/src/database/manager/builder/verilog_builder/verilog_write.cpp b/src/database/manager/builder/verilog_builder/verilog_write.cpp index 7ffc6a4be0c9a1eda461303658440609c78a5094..1a90232916b3cd5673ad688d88d753665fc4b1af 100644 --- a/src/database/manager/builder/verilog_builder/verilog_write.cpp +++ b/src/database/manager/builder/verilog_builder/verilog_write.cpp @@ -239,9 +239,9 @@ void VerilogWriter::writeWire() is_bus = std::nullopt; } - if (is_bus) { - continue; - } + // if (is_bus) { + // continue; + // } std::string new_net_name = replace_str(net_name, R"(\\)", ""); std::string escape_net_name = escapeName(new_net_name); diff --git a/src/database/manager/parser/liberty/Lib.cc b/src/database/manager/parser/liberty/Lib.cc index 98bd8579656ef493aa6e8226cf00382b05f2f47f..d9750279120c633ae94fd5aaa90f72a53d57b704 100644 --- a/src/database/manager/parser/liberty/Lib.cc +++ b/src/database/manager/parser/liberty/Lib.cc @@ -171,7 +171,7 @@ double LibTable::findValue(double slew, double constrain_slew_or_load) } // first check that slew and constrain_slew_or_load are within the table - // ranges + // ranges auto check_val = [this](auto axis_index, auto val) { auto num_val = getAxis(axis_index).get_axis_size(); auto min_val = getAxis(axis_index)[0]; @@ -184,7 +184,7 @@ double LibTable::findValue(double slew, double constrain_slew_or_load) return num_val; }; - // Find the interpolation interval on the axis, + // Find the interpolation interval on the axis, // and return the two endpoint values required for interpolation and the left index value. auto get_axis_region = [this](auto axis_index, auto num_val, auto val) { auto x2 = 0.0; @@ -208,7 +208,7 @@ double LibTable::findValue(double slew, double constrain_slew_or_load) return std::make_tuple(x1, x2, val_index); }; - auto get_table_value = [this](auto index) { + auto get_table_value = [this](auto index) -> double { auto& table_values = get_table_values(); LOG_FATAL_IF(index >= table_values.size()) << "index " << index << " beyond table value size " << table_values.size(); return table_values[index]->getFloatValue(); @@ -218,8 +218,8 @@ double LibTable::findValue(double slew, double constrain_slew_or_load) // Use linear interpolation (LinearInterpolate) in the case of a single variable auto num_val1 = check_val(0, val1); auto [x1, x2, val1_index] = get_axis_region(0, num_val1, val1); - unsigned int x1_table_val = get_table_value(val1_index); - unsigned int x2_table_val = get_table_value(val1_index + 1); + double x1_table_val = get_table_value(val1_index); + double x2_table_val = get_table_value(val1_index + 1); auto result = LinearInterpolate(x1, x2, x1_table_val, x2_table_val, val1); return result; @@ -1318,26 +1318,159 @@ LibArcSet& LibArcSet::operator=(LibArcSet&& rhs) noexcept /** * @brief get delay or constrain arc set value, should contain value vec. - * - * @param trans_type - * @param slew - * @param load_or_constrain_slew - * @return std::vector + * + * @param trans_type + * @param slew + * @param load_or_constrain_slew + * @return std::vector + */ +std::vector LibArcSet::getDelayOrConstrainCheckNs(TransType input_trans_type, TransType output_trans_type, double slew, + double load_or_constrain_slew) +{ + std::vector values; + bool is_flip = (input_trans_type == output_trans_type) ? false : true; + + for (auto& lib_arc : _arcs) { + if (!lib_arc->isCheckArc()) { + // skip timing sense not consistent + if (is_flip && lib_arc->isPositiveArc()) { + continue; + } + + if (!is_flip && lib_arc->isNegativeArc()) { + continue; + } + } + + double find_value = lib_arc->getDelayOrConstrainCheckNs(output_trans_type, slew, load_or_constrain_slew); + values.push_back(find_value); + } + + // sort by descending. + std::ranges::sort(values, std::greater()); + + LOG_FATAL_IF(values.empty()) << "No arc found for find table value."; + + return values; +} + +/** + * @brief get slew arc set value, should contain value vec. + * + * @param trans_type + * @param slew + * @param load + * @return std::vector */ -std::vector LibArcSet::getDelayOrConstrainCheckNs(TransType trans_type, double slew, double load_or_constrain_slew) { +std::vector LibArcSet::getSlewNs(TransType input_trans_type, TransType output_trans_type, double slew, double load) +{ std::vector values; - // LOG_INFO_IF_EVERY_N(_arcs.size() > 1, 100) << "arc set size is " << _arcs.size(); + bool is_flip = (input_trans_type == output_trans_type) ? false : true; for (auto& lib_arc : _arcs) { - double find_value = lib_arc->getDelayOrConstrainCheckNs(trans_type, slew, load_or_constrain_slew); + if (is_flip && lib_arc->isPositiveArc()) { + continue; + } + + if (!is_flip && lib_arc->isNegativeArc()) { + continue; + } + + double find_value = lib_arc->getSlewNs(output_trans_type, slew, load); values.push_back(find_value); } // sort by descending. std::ranges::sort(values, std::greater()); + LOG_FATAL_IF(values.empty()) << "No arc found for find table value."; + return values; +} + +/** + * @brief + * + * @param trans_type + * @return true + * @return false + */ +bool LibArcSet::isMatchTimingType(TransType trans_type) +{ + for (auto& lib_arc : _arcs) { + if (lib_arc->isMatchTimingType(trans_type)) { + return true; + } + } + return false; +} + +/** + * @brief judge arc set whether positive. + * + * @return unsigned + */ +unsigned LibArcSet::isPositiveArc() +{ + for (auto& lib_arc : _arcs) { + if (!lib_arc->isPositiveArc()) { + return false; + } + } + + return true; +} + +/** + * @brief judge arc set whether negative. + * + * @return unsigned + */ +unsigned LibArcSet::isNegativeArc() +{ + for (auto& lib_arc : _arcs) { + if (!lib_arc->isNegativeArc()) { + return false; + } + } + + return true; +} + +/** + * @brief judge arc set whether unate. + * + * @return unsigned + */ +unsigned LibArcSet::isUnateArc() +{ + for (auto& lib_arc : _arcs) { + if (!lib_arc->isUnateArc()) { + return false; + } + } + return true; +} + +/** + * @brief judge arc set whether two type sense arc set. + * + * @return unsigned + */ +unsigned LibArcSet::isTwoTypeSenseArcSet() +{ + bool is_has_positive = false; + bool is_has_negative = false; + + for (auto& lib_arc : _arcs) { + if (lib_arc->isPositiveArc()) { + is_has_positive = true; + } else if (lib_arc->isNegativeArc()) { + is_has_negative = true; + } + } + return (is_has_positive && is_has_negative); } LibPowerArc::LibPowerArc() : _owner_cell(nullptr) diff --git a/src/database/manager/parser/liberty/Lib.hh b/src/database/manager/parser/liberty/Lib.hh index f5995cc86c98bb1a0440358472d7ab104e847e65..1cdde40f1e680c6609cc28e948c886e9d4d05263 100644 --- a/src/database/manager/parser/liberty/Lib.hh +++ b/src/database/manager/parser/liberty/Lib.hh @@ -477,6 +477,7 @@ class LibPowerTableModel final : public LibTableModel LibTable* getTable(int index) override { return _tables[index].get(); } double gatePower(TransType trans_type, double slew, std::optional load) override; + auto& get_tables() { return _tables; } private: std::array, kTableNum> _tables; // power table,include rise power/fall power. @@ -840,6 +841,8 @@ class LibArc : public LibObject unsigned isNegativeArc() { return _timing_sense == TimingSense::kNegativeUnate; } + unsigned isNonUnateArc() { return _timing_sense == TimingSense::kNonUnate;} + unsigned isSetupArc() { return (_timing_type == TimingType::kSetupRising) || (_timing_type == TimingType::kSetupFalling); } unsigned isHoldArc() { return (_timing_type == TimingType::kHoldRising) || (_timing_type == TimingType::kHoldFalling); } @@ -912,7 +915,14 @@ class LibArcSet LibArc* front() { return _arcs.front().get(); } auto& get_arcs() { return _arcs; } - std::vector getDelayOrConstrainCheckNs(TransType trans_type, double slew, double load_or_constrain_slew); + std::vector getDelayOrConstrainCheckNs(TransType input_trans_type, TransType output_trans_type, double slew, double load_or_constrain_slew); + std::vector getSlewNs(TransType input_trans_type, TransType output_trans_type, double slew, double load); + bool isMatchTimingType(TransType trans_type); + + unsigned isPositiveArc(); + unsigned isNegativeArc(); + unsigned isUnateArc(); + unsigned isTwoTypeSenseArcSet(); private: Vector> _arcs; diff --git a/src/evaluation/src/module/congestion/congestion_eval.cpp b/src/evaluation/src/module/congestion/congestion_eval.cpp index 841542dc9f4df318cf1a8d2afd750a07c2ec0374..b0d831b05359f50b0e5febe5a6cfce7094a06049 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.cpp +++ b/src/evaluation/src/module/congestion/congestion_eval.cpp @@ -1692,38 +1692,17 @@ std::map>> CongestionEval::getDemandSu return diff_map; } -struct CongestionGridIndex -{ - int grid_size_x = EVAL_INIT_IDB_INST->getDieWidth() / 100; - int grid_size_y = EVAL_INIT_IDB_INST->getDieHeight() / 100; - std::unordered_map, std::vector, CongestionPairHash> grid_map; - - void build(const std::vector& nets) - { - for (int i = 0; i < nets.size(); ++i) { - const auto& net = nets[i]; - // 计算net覆盖的网格范围 - int min_x = net.lx / grid_size_x; - int max_x = net.ux / grid_size_x; - int min_y = net.ly / grid_size_y; - int max_y = net.uy / grid_size_y; - // 注册到所有覆盖的网格 - for (int x = min_x; x <= max_x; ++x) { - for (int y = min_y; y <= max_y; ++y) { - grid_map[{x, y}].push_back(i); - } - } - } - } -}; std::map CongestionEval::patchRUDYCongestion(CongestionNets nets, std::map, std::pair>> patch_coords) { - // 预计算 + // 预计算线网数据 auto net_metadata = precomputeNetData(nets); - CongestionGridIndex index; - index.build(net_metadata); // 构建空间索引 + + // 预处理:按x坐标排序线网数据 + std::sort(net_metadata.begin(), net_metadata.end(), [](const NetMetadata& a, const NetMetadata& b) { + return a.lx < b.lx; + }); std::map patch_rudy_map; @@ -1734,44 +1713,34 @@ std::map CongestionEval::patchRUDYCongestion(CongestionNets nets, const int patch_ux = u_range.first, patch_uy = u_range.second; const int patch_area = (patch_ux - patch_lx) * (patch_uy - patch_ly); - // 获取覆盖的网格范围 - int min_gx = patch_lx / index.grid_size_x; - int max_gx = patch_ux / index.grid_size_x; - int min_gy = patch_ly / index.grid_size_y; - int max_gy = patch_uy / index.grid_size_y; - - std::unordered_set processed_nets; // 去重 double rudy = 0.0; - // 遍历覆盖的网格 - for (int gx = min_gx; gx <= max_gx; ++gx) { - for (int gy = min_gy; gy <= max_gy; ++gy) { - auto it = index.grid_map.find({gx, gy}); - if (it == index.grid_map.end()) - continue; - - // 处理该网格内的候选net - for (int net_id : it->second) { - if (processed_nets.count(net_id)) - continue; - processed_nets.insert(net_id); - - const auto& net = net_metadata[net_id]; - // 快速边界检查 - if (net.ux <= patch_lx || net.lx >= patch_ux || net.uy <= patch_ly || net.ly >= patch_uy) - continue; - - // 计算重叠区域 - const int overlap_lx = std::max(net.lx, patch_lx); - const int overlap_ly = std::max(net.ly, patch_ly); - const int overlap_ux = std::min(net.ux, patch_ux); - const int overlap_uy = std::min(net.uy, patch_uy); - - const int overlap_width = overlap_ux - overlap_lx; - const int overlap_height = overlap_uy - overlap_ly; - if (overlap_width <= 0 || overlap_height <= 0) - continue; - + // 使用二分查找确定x坐标范围 + auto start_it = std::lower_bound(net_metadata.begin(), net_metadata.end(), patch_lx, + [](const NetMetadata& net, int x) { + return net.ux < x; + }); + + auto end_it = std::upper_bound(net_metadata.begin(), net_metadata.end(), patch_ux, + [](int x, const NetMetadata& net) { + return x < net.lx; + }); + + // 遍历可能重叠的线网 + for (auto it = start_it; it != end_it; ++it) { + const auto& net = *it; + + // 检查y坐标是否重叠 + if (net.ly <= patch_uy && net.uy >= patch_ly) { + // 计算重叠区域 + const int overlap_lx = std::max(net.lx, patch_lx); + const int overlap_ly = std::max(net.ly, patch_ly); + const int overlap_ux = std::min(net.ux, patch_ux); + const int overlap_uy = std::min(net.uy, patch_uy); + + const int overlap_width = overlap_ux - overlap_lx; + const int overlap_height = overlap_uy - overlap_ly; + if (overlap_width > 0 && overlap_height > 0) { // 累加RUDY值(使用预计算结果) rudy += (overlap_width * overlap_height) * (net.hor_rudy + net.ver_rudy) / patch_area; } diff --git a/src/evaluation/src/module/congestion/congestion_eval.h b/src/evaluation/src/module/congestion/congestion_eval.h index c28e4bec0e185af96d102b01fd08b45c373a593a..e7eeeb6ef2275b3a447666a2a845279117aa657a 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.h +++ b/src/evaluation/src/module/congestion/congestion_eval.h @@ -23,17 +23,6 @@ struct NetMetadata double hor_rudy, ver_rudy; // 预计算的RUDY因子 }; -// 辅助哈希函数 -struct CongestionPairHash -{ - template - size_t operator()(const std::pair& p) const - { - auto hash1 = std::hash{}(p.first); - auto hash2 = std::hash{}(p.second); - return hash1 ^ (hash2 << 1); - } -}; class CongestionEval { diff --git a/src/evaluation/src/module/density/density_eval.cpp b/src/evaluation/src/module/density/density_eval.cpp index fe1e53954ca3e6548442002975adfa5ca36b0e1e..c02417a9511b7a18b2a5069914970aacc2e9acae 100644 --- a/src/evaluation/src/module/density/density_eval.cpp +++ b/src/evaluation/src/module/density/density_eval.cpp @@ -7,6 +7,7 @@ #include "density_eval.h" +#include #include #include #include @@ -548,22 +549,12 @@ std::vector DensityEval::initMarginGrid(DensityRegion die, int32_t g std::map DensityEval::patchCellDensity(DensityCells cells, std::map, std::pair>> patch_coords) { std::map patch_cell_density; - DensityGridIndex index; - index.grid_size_x = EVAL_INIT_IDB_INST->getDieWidth() / 100 ; - index.grid_size_y = EVAL_INIT_IDB_INST->getDieHeight() / 100; - // 构建单元格网格索引 - for (auto& cell : cells) { - int min_grid_x = cell.lx / index.grid_size_x; - int max_grid_x = (cell.lx + cell.width) / index.grid_size_x; - int min_grid_y = cell.ly / index.grid_size_y; - int max_grid_y = (cell.ly + cell.height) / index.grid_size_y; - - for (int x = min_grid_x; x <= max_grid_x; ++x) { - for (int y = min_grid_y; y <= max_grid_y; ++y) { - index.cell_grid[{x, y}].push_back(cell); - } - } - } + + // 预处理:将单元格按x坐标排序,提升查找性能 + std::vector sorted_cells = cells; + std::sort(sorted_cells.begin(), sorted_cells.end(), [](const DensityCell& a, const DensityCell& b) { + return a.lx < b.lx; + }); for (const auto& [patch_id, coord] : patch_coords) { double density = 0.0; @@ -575,45 +566,43 @@ std::map DensityEval::patchCellDensity(DensityCells cells, std::map const int patch_ux = u_range.first; const int patch_uy = u_range.second; - // 计算 patch 面积(保持与 pin 密度相同的左闭右开区间) + // 计算 patch 面积 const int patch_width = patch_ux - patch_lx; const int patch_height = patch_uy - patch_ly; const int patch_area = patch_width * patch_height; - // 计算 patch 覆盖的网格范围 - int min_grid_x = patch_lx / index.grid_size_x; - int max_grid_x = patch_ux / index.grid_size_x; - int min_grid_y = patch_ly / index.grid_size_y; - int max_grid_y = patch_uy / index.grid_size_y; - - std::unordered_set processed_cells; // 记录已处理的 cell ID, 避免重复多次处理同一cell - - for (int x = min_grid_x; x <= max_grid_x; ++x) { - for (int y = min_grid_y; y <= max_grid_y; ++y) { - auto it = index.cell_grid.find({x, y}); - if (it == index.cell_grid.end()) continue; - - for (const auto& cell : it->second) { - if (processed_cells.count(cell.id)) continue; - processed_cells.insert(cell.id); - // 计算重叠面积 - const int overlap_lx = std::max(cell.lx, patch_lx); - const int overlap_ly = std::max(cell.ly, patch_ly); - const int overlap_ux = std::min(cell.lx + cell.width, patch_ux); - const int overlap_uy = std::min(cell.ly + cell.height, patch_uy); - - // 有效重叠面积计算 - const int overlap_width = std::max(0, overlap_ux - overlap_lx); - const int overlap_height = std::max(0, overlap_uy - overlap_ly); - const int overlap_area = overlap_width * overlap_height; - - // 累加密度贡献(当且仅当有重叠时) - if (overlap_area > 0) { - density += static_cast(overlap_area) / patch_area; - } - - } + // 使用二分查找确定x坐标范围,减少需要检查的单元格数量 + auto lower_it = std::lower_bound(sorted_cells.begin(), sorted_cells.end(), patch_lx, + [](const DensityCell& cell, int x) { + return cell.lx + cell.width <= x; + }); + auto upper_it = std::upper_bound(sorted_cells.begin(), sorted_cells.end(), patch_ux, + [](int x, const DensityCell& cell) { + return x < cell.lx; + }); + + // 只检查x坐标范围内可能重叠的单元格 + for (auto it = lower_it; it != upper_it; ++it) { + const auto& cell = *it; + + // 检查y坐标是否重叠 + if (cell.ly + cell.height > patch_ly && cell.ly < patch_uy) { + // 计算重叠面积 + const int overlap_lx = std::max(cell.lx, patch_lx); + const int overlap_ly = std::max(cell.ly, patch_ly); + const int overlap_ux = std::min(cell.lx + cell.width, patch_ux); + const int overlap_uy = std::min(cell.ly + cell.height, patch_uy); + + // 有效重叠面积计算 + const int overlap_width = std::max(0, overlap_ux - overlap_lx); + const int overlap_height = std::max(0, overlap_uy - overlap_ly); + const int overlap_area = overlap_width * overlap_height; + + // 累加密度贡献(当且仅当有重叠时) + if (overlap_area > 0) { + density += static_cast(overlap_area) / patch_area; } + } } patch_cell_density[patch_id] = density; @@ -627,16 +616,11 @@ std::map DensityEval::patchPinDensity(DensityPins pins, std::map patch_pin_density; - // 构建 pin 网格索引 - DensityGridIndex index; - index.grid_size_x = EVAL_INIT_IDB_INST->getDieWidth() / 100 ; - index.grid_size_y = EVAL_INIT_IDB_INST->getDieHeight() / 100; - - for (const auto& pin : pins) { - int grid_x = pin.lx / index.grid_size_x; - int grid_y = pin.ly / index.grid_size_y; - index.pin_grid[{grid_x, grid_y}].push_back(pin); - } + // 预处理:将引脚按x坐标排序,提升查找性能 + std::vector sorted_pins = pins; + std::sort(sorted_pins.begin(), sorted_pins.end(), [](const DensityPin& a, const DensityPin& b) { + return a.lx < b.lx; + }); for (const auto& [patch_id, coord] : patch_coords) { auto [l_range, u_range] = coord; @@ -647,25 +631,24 @@ std::map DensityEval::patchPinDensity(DensityPins pins, std::mapsecond) { - if (pin.lx >= patch_lx && pin.ly >= patch_ly && - pin.lx <= patch_ux && pin.ly <= patch_uy) - { - ++pin_count; - } - } - } + // 使用二分查找确定x坐标范围,减少需要检查的引脚数量 + auto lower_it = std::lower_bound(sorted_pins.begin(), sorted_pins.end(), patch_lx, + [](const DensityPin& pin, int x) { + return pin.lx < x; + }); + auto upper_it = std::lower_bound(sorted_pins.begin(), sorted_pins.end(), patch_ux, + [](const DensityPin& pin, int x) { + return pin.lx <= x; + }); + + // 只检查x坐标范围内的引脚 + for (auto it = lower_it; it != upper_it; ++it) { + const auto& pin = *it; + + // 检查y坐标是否在patch范围内 + if (pin.ly >= patch_ly && pin.ly <= patch_uy) { + ++pin_count; + } } patch_pin_density[patch_id] = pin_count; } @@ -675,23 +658,12 @@ std::map DensityEval::patchPinDensity(DensityPins pins, std::map DensityEval::patchNetDensity(DensityNets nets, std::map, std::pair>> patch_coords) { std::map patch_net_density; - DensityGridIndex index; - index.grid_size_x = EVAL_INIT_IDB_INST->getDieWidth() / 100 ; - index.grid_size_y = EVAL_INIT_IDB_INST->getDieHeight() / 100; - - // 构建线网网格索引 - for (const auto& net : nets) { - int min_grid_x = net.lx / index.grid_size_x; - int max_grid_x = net.ux / index.grid_size_x; - int min_grid_y = net.ly / index.grid_size_y; - int max_grid_y = net.uy / index.grid_size_y; - - for (int x = min_grid_x; x <= max_grid_x; ++x) { - for (int y = min_grid_y; y <= max_grid_y; ++y) { - index.net_grid[{x, y}].push_back(net); - } - } - } + + // 预处理:将线网按x坐标排序,提升查找性能 + std::vector sorted_nets = nets; + std::sort(sorted_nets.begin(), sorted_nets.end(), [](const DensityNet& a, const DensityNet& b) { + return a.lx < b.lx; + }); for (const auto& [patch_id, coord] : patch_coords) { double density = 0.0; @@ -703,45 +675,43 @@ std::map DensityEval::patchNetDensity(DensityNets nets, std::map processed_nets; // 记录已处理的 net ID, 避免重复多次处理同一 net - - for (int x = min_grid_x; x <= max_grid_x; ++x) { - for (int y = min_grid_y; y <= max_grid_y; ++y) { - auto it = index.net_grid.find({x, y}); - if (it == index.net_grid.end()) continue; - - for (const auto& net : it->second) { - if (processed_nets.count(net.id)) continue; - processed_nets.insert(net.id); - // 计算重叠面积 - const int overlap_lx = std::max(net.lx, patch_lx); - const int overlap_ly = std::max(net.ly, patch_ly); - const int overlap_ux = std::min(net.ux, patch_ux); - const int overlap_uy = std::min(net.uy, patch_uy); - - // 有效重叠面积计算 - const int overlap_width = std::max(0, overlap_ux - overlap_lx); - const int overlap_height = std::max(0, overlap_uy - overlap_ly); - const int overlap_area = overlap_width * overlap_height; - - // 累加密度贡献(当且仅当有重叠时) - if (overlap_area > 0) { - density += static_cast(overlap_area) / patch_area; - } - - } + // 使用二分查找确定x坐标范围,减少需要检查的线网数量 + auto lower_it = std::lower_bound(sorted_nets.begin(), sorted_nets.end(), patch_lx, + [](const DensityNet& net, int x) { + return net.ux <= x; + }); + auto upper_it = std::upper_bound(sorted_nets.begin(), sorted_nets.end(), patch_ux, + [](int x, const DensityNet& net) { + return x < net.lx; + }); + + // 只检查x坐标范围内可能重叠的线网 + for (auto it = lower_it; it != upper_it; ++it) { + const auto& net = *it; + + // 检查y坐标是否重叠 + if (net.uy > patch_ly && net.ly < patch_uy) { + // 计算重叠面积 + const int overlap_lx = std::max(net.lx, patch_lx); + const int overlap_ly = std::max(net.ly, patch_ly); + const int overlap_ux = std::min(net.ux, patch_ux); + const int overlap_uy = std::min(net.uy, patch_uy); + + // 有效重叠面积计算 + const int overlap_width = std::max(0, overlap_ux - overlap_lx); + const int overlap_height = std::max(0, overlap_uy - overlap_ly); + const int overlap_area = overlap_width * overlap_height; + + // 累加密度贡献(当且仅当有重叠时) + if (overlap_area > 0) { + density += static_cast(overlap_area) / patch_area; } + } } patch_net_density[patch_id] = density; @@ -761,6 +731,11 @@ std::map DensityEval::patchMacroMargin(DensityCells cells, DensityRegi } } + // 预处理:将宏按x坐标排序,提升查找性能 + std::sort(macros.begin(), macros.end(), [](const DensityCell& a, const DensityCell& b) { + return a.lx < b.lx; + }); + for (const auto& [patch_id, coord] : patch_coords) { auto [l_range, u_range] = coord; @@ -788,39 +763,61 @@ std::map DensityEval::patchMacroMargin(DensityCells cells, DensityRegi int overlap_area = 0; int margin = 0; - for (size_t j = 0; j < macros.size(); ++j) { - int32_t rect_lx = std::max(patch_lx, macros[j].lx); - int32_t rect_ly = std::max(patch_ly, macros[j].ly); - int32_t rect_ux = std::min(patch_ux, macros[j].lx + macros[j].width); - int32_t rect_uy = std::min(patch_uy, macros[j].ly + macros[j].height); - if (rect_lx < rect_ux && rect_ly < rect_uy) { - overlap_area += (std::min(patch_ux, macros[j].lx + macros[j].width) - std::max(patch_lx, macros[j].lx)) - * (std::min(patch_uy, macros[j].ly + macros[j].height) - std::max(patch_ly, macros[j].ly)); - } - if (overlap_area > 0.5 * patch_area) { - overlap = true; - break; + // 使用二分查找确定x坐标范围,减少需要检查的宏数量 + auto lower_it = std::lower_bound(macros.begin(), macros.end(), patch_lx, + [](const DensityCell& macro, int x) { + return macro.lx + macro.width <= x; + }); + auto upper_it = std::upper_bound(macros.begin(), macros.end(), patch_ux, + [](int x, const DensityCell& macro) { + return x < macro.lx; + }); + + // 只检查x坐标范围内可能重叠的宏 + for (auto it = lower_it; it != upper_it; ++it) { + const auto& macro = *it; + + // 检查y坐标是否重叠 + if (macro.ly + macro.height > patch_ly && macro.ly < patch_uy) { + int32_t rect_lx = std::max(patch_lx, macro.lx); + int32_t rect_ly = std::max(patch_ly, macro.ly); + int32_t rect_ux = std::min(patch_ux, macro.lx + macro.width); + int32_t rect_uy = std::min(patch_uy, macro.ly + macro.height); + if (rect_lx < rect_ux && rect_ly < rect_uy) { + overlap_area += (std::min(patch_ux, macro.lx + macro.width) - std::max(patch_lx, macro.lx)) + * (std::min(patch_uy, macro.ly + macro.height) - std::max(patch_ly, macro.ly)); + } + if (overlap_area > 0.5 * patch_area) { + overlap = true; + break; + } } } if (!overlap) { - for (size_t j = 0; j < macros.size(); ++j) { - int32_t macro_middle_x = macros[j].lx + macros[j].width * 0.5; - int32_t macro_middle_y = macros[j].ly + macros[j].height * 0.5; - int32_t grid_middle_x = (patch_lx + patch_ux) * 0.5; - int32_t grid_middle_y = (patch_ly + patch_uy) * 0.5; - if (grid_middle_y >= macros[j].ly && grid_middle_y <= macros[j].ly + macros[j].height) { - if (macro_middle_x > grid_middle_x) { - h_right = std::min(h_right, macros[j].lx); - } else { - h_left = std::max(h_left, macros[j].lx + macros[j].width); + // 再次使用相同的范围进行margin计算 + for (auto it = lower_it; it != upper_it; ++it) { + const auto& macro = *it; + + // 检查y坐标是否重叠 + if (macro.ly + macro.height > patch_ly && macro.ly < patch_uy) { + int32_t macro_middle_x = macro.lx + macro.width * 0.5; + int32_t macro_middle_y = macro.ly + macro.height * 0.5; + int32_t grid_middle_x = (patch_lx + patch_ux) * 0.5; + int32_t grid_middle_y = (patch_ly + patch_uy) * 0.5; + if (grid_middle_y >= macro.ly && grid_middle_y <= macro.ly + macro.height) { + if (macro_middle_x > grid_middle_x) { + h_right = std::min(h_right, macro.lx); + } else { + h_left = std::max(h_left, macro.lx + macro.width); + } } - } - if (grid_middle_x >= macros[j].lx && grid_middle_x <= macros[j].lx + macros[j].width) { - if (macro_middle_y > grid_middle_y) { - v_up = std::min(v_up, macros[j].ly); - } else { - v_down = std::max(v_down, macros[j].ly + macros[j].height); + if (grid_middle_x >= macro.lx && grid_middle_x <= macro.lx + macro.width) { + if (macro_middle_y > grid_middle_y) { + v_up = std::min(v_up, macro.ly); + } else { + v_down = std::max(v_down, macro.ly + macro.height); + } } } } diff --git a/src/evaluation/src/module/density/density_eval.h b/src/evaluation/src/module/density/density_eval.h index b633554239416598649b8473eb59012753196f16..3da5086347af835aa77fc6b948cbc89f8c0ebcbc 100644 --- a/src/evaluation/src/module/density/density_eval.h +++ b/src/evaluation/src/module/density/density_eval.h @@ -23,24 +23,6 @@ struct MarginGrid int32_t margin; }; -// 辅助哈希函数 -struct DensityPairHash { - template - std::size_t operator () (const std::pair &p) const { - auto h1 = std::hash{}(p.first); - auto h2 = std::hash{}(p.second); - return h1 ^ (h2 << 1); - } -}; - -// 网格索引结构体 -struct DensityGridIndex { - int grid_size_x = 2000; // 默认x方向网格大小 - int grid_size_y = 2000; // 默认y方向网格大小 - std::unordered_map, DensityCells, DensityPairHash> cell_grid; - std::unordered_map, DensityPins, DensityPairHash> pin_grid; - std::unordered_map, DensityNets, DensityPairHash> net_grid; -}; class DensityEval { diff --git a/src/evaluation/src/util/init_sta.cc b/src/evaluation/src/util/init_sta.cc index d29863e19e81b67d449c89893a0eb37216d59fb2..3b6646f549cdaf0f7134fedbcbe9c0d01fb22116 100644 --- a/src/evaluation/src/util/init_sta.cc +++ b/src/evaluation/src/util/init_sta.cc @@ -1148,7 +1148,8 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string std::thread t1([&]() { json j = json::array(); for (unsigned node_id = 0; auto& node : timing_wire_graph._nodes) { - j.push_back({{"id", Str::printf("node_%d", node_id++)}, {"name", node._name}, {"is_pin", node._is_pin}, {"is_port", node._is_port}}); + std::string node_id_str = "node_" + std::to_string(node_id++); + j.push_back({{"id", node_id_str}, {"name", node._name}, {"is_pin", node._is_pin}, {"is_port", node._is_port}}); } nodes_json = j; }); @@ -1157,7 +1158,8 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string std::thread t2([&]() { json j = json::array(); for (unsigned edge_id = 0; auto& edge : timing_wire_graph._edges) { - j.push_back({{"id", Str::printf("edge_%d", edge_id++)}, {"from_node", edge._from_node}, {"to_node", edge._to_node}, {"is_net_edge", edge._is_net_edge}}); + std::string edge_id_str = "edge_" + std::to_string(edge_id++); + j.push_back({{"id", edge_id_str}, {"from_node", edge._from_node}, {"to_node", edge._to_node}, {"is_net_edge", edge._is_net_edge}}); } edges_json = j; }); @@ -1191,7 +1193,8 @@ void SaveTimingInstanceGraph(const TimingInstanceGraph& timing_instance_graph, c std::thread t1([&]() { json j = json::array(); for (unsigned node_id = 0; auto& node : timing_instance_graph._nodes) { - j.push_back({{"id", Str::printf("node_%d", node_id++)}, {"name", node._name}}); + std::string id_str = "node_" + std::to_string(node_id++); + j.push_back({{"id", id_str}, {"name", node._name}}); } nodes_json = j; }); @@ -1200,7 +1203,8 @@ void SaveTimingInstanceGraph(const TimingInstanceGraph& timing_instance_graph, c std::thread t2([&]() { json j = json::array(); for (unsigned edge_id = 0; auto& edge : timing_instance_graph._edges) { - j.push_back({{"id", Str::printf("edge_%d", edge_id++)}, {"from_node", edge._from_node}, {"to_node", edge._to_node}}); + std::string id_str = "edge_" + std::to_string(edge_id++); + j.push_back({{"id", id_str}, {"from_node", edge._from_node}, {"to_node", edge._to_node}}); } edges_json = j; }); @@ -1426,67 +1430,50 @@ std::map InitSTA::patchTimingMap(std::mapgetIDBAdapter(); auto dbu = idb_adapter->get_dbu(); - // 网格索引,减小搜索空间 - int64_t min_x = INT64_MAX; - int64_t max_x = INT64_MIN; - int64_t min_y = INT64_MAX; - int64_t max_y = INT64_MIN; - for (const auto& [coord, _] : inst_timing_map) { - int64_t x = static_cast(coord.first * dbu); - int64_t y = static_cast(coord.second * dbu); - min_x = std::min(min_x, x); - max_x = std::max(max_x, x); - min_y = std::min(min_y, y); - max_y = std::max(max_y, y); - } - - // 启发式确定网格大小 - int64_t grid_size_x = (max_x - min_x) / 100; - int64_t grid_size_y = (max_y - min_y) / 100; - - // 创建网格: 二维网格,每个网格内存有对应的insts - std::vector, double>>>> grid; - int64_t grid_width = (max_x - min_x) / grid_size_x + 1; - int64_t grid_height = (max_y - min_y) / grid_size_y + 1; - grid.resize(grid_width, std::vector, double>>>(grid_height)); - - // 填充网格 + // 预处理:将实例坐标转换并按x坐标排序,提升查找性能 + std::vector> sorted_instances; + sorted_instances.reserve(inst_timing_map.size()); + for (const auto& [coord, slack] : inst_timing_map) { - int64_t x = static_cast(coord.first * dbu); - int64_t y = static_cast(coord.second * dbu); - int64_t grid_x = (x - min_x) / grid_size_x; - int64_t grid_y = (y - min_y) / grid_size_y; - grid[grid_x][grid_y].push_back({{x, y}, slack}); + int64_t inst_x = static_cast(coord.first * dbu); + int64_t inst_y = static_cast(coord.second * dbu); + sorted_instances.emplace_back(inst_x, inst_y, slack); } + + // 按x坐标排序,便于后续二分查找 + std::sort(sorted_instances.begin(), sorted_instances.end()); for (const auto& [patch_id, coord] : patch) { auto [l_range, u_range] = coord; const int64_t patch_lx = static_cast(l_range.first); const int64_t patch_ly = static_cast(l_range.second); - const int64_t patch_ux = static_cast(u_range.first); - const int64_t patch_uy = static_cast(u_range.second); - - // 计算覆盖的网格范围 - int64_t start_grid_x = std::max(static_cast(0), (patch_lx - min_x) / grid_size_x); - int64_t end_grid_x = std::min(grid_width - 1, (patch_ux - min_x) / grid_size_x); - int64_t start_grid_y = std::max(static_cast(0), (patch_ly - min_y) / grid_size_y); - int64_t end_grid_y = std::min(grid_height - 1, (patch_uy - min_y) / grid_size_y); + const int64_t patch_ux = static_cast(u_range.first); + const int64_t patch_uy = static_cast(u_range.second); double min_slack = std::numeric_limits::max(); - - // 只检查覆盖的网格 - for (int64_t gx = start_grid_x; gx <= end_grid_x; ++gx) { - for (int64_t gy = start_grid_y; gy <= end_grid_y; ++gy) { - for (const auto& [inst_coord, inst_slack] : grid[gx][gy]) { - int64_t inst_x = inst_coord.first; - int64_t inst_y = inst_coord.second; - if (patch_lx <= inst_x && inst_x <= patch_ux && patch_ly <= inst_y && inst_y <= patch_uy) { - min_slack = std::min(min_slack, inst_slack); - } - } + bool found_instance = false; + + // 使用二分查找确定x坐标范围,减少需要检查的实例数量 + auto lower_it = std::lower_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_lx, INT64_MIN, 0.0)); + auto upper_it = std::upper_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_ux, INT64_MAX, 0.0)); + + // 只检查x坐标在范围内的实例 + for (auto it = lower_it; it != upper_it; ++it) { + int64_t inst_y = std::get<1>(*it); + double slack = std::get<2>(*it); + + if (patch_ly <= inst_y && inst_y <= patch_uy) { + min_slack = std::min(min_slack, slack); + found_instance = true; } } + if (!found_instance) { + min_slack = 0.0; + } + patch_timing_map[patch_id] = min_slack; } @@ -1511,64 +1498,41 @@ std::map InitSTA::patchPowerMap(std::mapgetIDBAdapter(); auto dbu = idb_adapter->get_dbu(); - // 网格索引,减小搜索空间 - int64_t min_x = INT64_MAX; - int64_t max_x = INT64_MIN; - int64_t min_y = INT64_MAX; - int64_t max_y = INT64_MIN; - for (const auto& [coord, _] : inst_power_map) { - int64_t x = static_cast(coord.first * dbu); - int64_t y = static_cast(coord.second * dbu); - min_x = std::min(min_x, x); - max_x = std::max(max_x, x); - min_y = std::min(min_y, y); - max_y = std::max(max_y, y); - } - - // 启发式确定网格大小 - int64_t grid_size_x = (max_x - min_x) / 100; - int64_t grid_size_y = (max_y - min_y) / 100; - - // 创建网格: 二维网格,每个网格内存有对应的insts - std::vector, double>>>> grid; - int64_t grid_width = (max_x - min_x) / grid_size_x + 1; - int64_t grid_height = (max_y - min_y) / grid_size_y + 1; - grid.resize(grid_width, std::vector, double>>>(grid_height)); - - // 填充网格 + // 预处理:将实例坐标转换并按x坐标排序,提升查找性能 + std::vector> sorted_instances; + sorted_instances.reserve(inst_power_map.size()); + for (const auto& [coord, power] : inst_power_map) { - int64_t x = static_cast(coord.first * dbu); - int64_t y = static_cast(coord.second * dbu); - int64_t grid_x = (x - min_x) / grid_size_x; - int64_t grid_y = (y - min_y) / grid_size_y; - grid[grid_x][grid_y].push_back({{x, y}, power}); + int64_t inst_x = static_cast(coord.first * dbu); + int64_t inst_y = static_cast(coord.second * dbu); + sorted_instances.emplace_back(inst_x, inst_y, power); } + + // 按x坐标排序,便于后续二分查找 + std::sort(sorted_instances.begin(), sorted_instances.end()); for (const auto& [patch_id, coord] : patch) { auto [l_range, u_range] = coord; const int64_t patch_lx = static_cast(l_range.first); - const int64_t patch_ly = static_cast(l_range.second); - const int64_t patch_ux = static_cast(u_range.first); - const int64_t patch_uy = static_cast(u_range.second); - - // 计算覆盖的网格范围 - int64_t start_grid_x = std::max(static_cast(0), (patch_lx - min_x) / grid_size_x); - int64_t end_grid_x = std::min(grid_width - 1, (patch_ux - min_x) / grid_size_x); - int64_t start_grid_y = std::max(static_cast(0), (patch_ly - min_y) / grid_size_y); - int64_t end_grid_y = std::min(grid_height - 1, (patch_uy - min_y) / grid_size_y); + const int64_t patch_ly = static_cast(l_range.second); + const int64_t patch_ux = static_cast(u_range.first); + const int64_t patch_uy = static_cast(u_range.second); double total_power = 0.0; - // 只检查覆盖的网格 - for (int64_t gx = start_grid_x; gx <= end_grid_x; ++gx) { - for (int64_t gy = start_grid_y; gy <= end_grid_y; ++gy) { - for (const auto& [inst_coord, inst_power] : grid[gx][gy]) { - int64_t inst_x = inst_coord.first; - int64_t inst_y = inst_coord.second; - if (patch_lx <= inst_x && inst_x <= patch_ux && patch_ly <= inst_y && inst_y <= patch_uy) { - total_power += inst_power; - } - } + // 使用二分查找确定x坐标范围,减少需要检查的实例数量 + auto lower_it = std::lower_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_lx, INT64_MIN, 0.0)); + auto upper_it = std::upper_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_ux, INT64_MAX, 0.0)); + + // 只检查x坐标在范围内的实例 + for (auto it = lower_it; it != upper_it; ++it) { + int64_t inst_y = std::get<1>(*it); + double power = std::get<2>(*it); + + if (patch_ly <= inst_y && inst_y <= patch_uy) { + total_power += power; } } @@ -1604,42 +1568,20 @@ std::map InitSTA::patchIRDropMap(std::mapgetIDBAdapter(); auto dbu = idb_adapter->get_dbu(); - // 网格索引,减小搜索空间 - int64_t min_x = INT64_MAX; - int64_t max_x = INT64_MIN; - int64_t min_y = INT64_MAX; - int64_t max_y = INT64_MIN; - std::vector> instances; - instances.reserve(instance_to_ir_drop.size()); - + // 预处理:将实例坐标转换并按x坐标排序,提升查找性能 + std::vector> sorted_instances; + sorted_instances.reserve(instance_to_ir_drop.size()); + for (auto& [sta_inst, ir_drop] : instance_to_ir_drop) { auto coord = sta_inst->get_coordinate().value(); - int64_t x = static_cast(coord.first * dbu); - int64_t y = static_cast(coord.second * dbu); - instances.emplace_back(x, y, ir_drop); - min_x = std::min(min_x, x); - max_x = std::max(max_x, x); - min_y = std::min(min_y, y); - max_y = std::max(max_y, y); - } - // 启发式确定网格大小 - int64_t grid_size_x = (max_x - min_x) / 100; - int64_t grid_size_y = (max_y - min_y) / 100; - - // 创建网格 - std::vector, double>>>> grid; - int64_t grid_width = (max_x - min_x) / grid_size_x + 1; - int64_t grid_height = (max_y - min_y) / grid_size_y + 1; - grid.resize(grid_width, std::vector, double>>>(grid_height)); - - // 填充网格 - for (const auto& [x, y, ir_drop] : instances) { - int64_t grid_x = (x - min_x) / grid_size_x; - int64_t grid_y = (y - min_y) / grid_size_y; - grid[grid_x][grid_y].push_back({{x, y}, ir_drop}); + int64_t inst_x = static_cast(coord.first * dbu); + int64_t inst_y = static_cast(coord.second * dbu); + sorted_instances.emplace_back(inst_x, inst_y, ir_drop); } + + // 按x坐标排序,便于后续二分查找 + std::sort(sorted_instances.begin(), sorted_instances.end()); - int processed_count = 0; for (const auto& [patch_id, coord] : patch) { auto [l_range, u_range] = coord; const int64_t patch_lx = static_cast(l_range.first); @@ -1647,34 +1589,31 @@ std::map InitSTA::patchIRDropMap(std::map(u_range.first); const int64_t patch_uy = static_cast(u_range.second); - // 计算覆盖的网格范围 - int64_t start_grid_x = std::max(static_cast(0), (patch_lx - min_x) / grid_size_x); - int64_t end_grid_x = std::min(grid_width - 1, (patch_ux - min_x) / grid_size_x); - int64_t start_grid_y = std::max(static_cast(0), (patch_ly - min_y) / grid_size_y); - int64_t end_grid_y = std::min(grid_height - 1, (patch_uy - min_y) / grid_size_y); - double max_ir_drop = 0.0; - - // 只检查覆盖的网格 - for (int64_t gx = start_grid_x; gx <= end_grid_x; ++gx) { - for (int64_t gy = start_grid_y; gy <= end_grid_y; ++gy) { - for (const auto& [inst_coord, inst_ir_drop] : grid[gx][gy]) { - int64_t inst_x = inst_coord.first; - int64_t inst_y = inst_coord.second; - if (patch_lx <= inst_x && inst_x <= patch_ux && patch_ly <= inst_y && inst_y <= patch_uy) { - max_ir_drop = std::max(max_ir_drop, inst_ir_drop); - } - } + bool found_instance = false; + + // 使用二分查找确定x坐标范围,减少需要检查的实例数量 + auto lower_it = std::lower_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_lx, INT64_MIN, 0.0)); + auto upper_it = std::upper_bound(sorted_instances.begin(), sorted_instances.end(), + std::make_tuple(patch_ux, INT64_MAX, 0.0)); + + // 只检查x坐标在范围内的实例 + for (auto it = lower_it; it != upper_it; ++it) { + int64_t inst_y = std::get<1>(*it); + double ir_drop = std::get<2>(*it); + + if (patch_ly <= inst_y && inst_y <= patch_uy) { + max_ir_drop = std::max(max_ir_drop, ir_drop); + found_instance = true; } } - patch_ir_drop_map[patch_id] = max_ir_drop; - - // 每处理5000个patch输出一次日志 - processed_count++; - if (processed_count % 5000 == 0) { - LOG_INFO << "Processed " << processed_count << " patches out of " << patch.size(); + if (!found_instance) { + max_ir_drop = 0.0; } + + patch_ir_drop_map[patch_id] = max_ir_drop; } return patch_ir_drop_map; diff --git a/src/operation/iPA/api/Power.cc b/src/operation/iPA/api/Power.cc index f67056b97e9ebbdf5e9c9df824ac6553924ef3f8..1c245645d3ed31b724cd1f3ab64cd4f92543a5fc 100644 --- a/src/operation/iPA/api/Power.cc +++ b/src/operation/iPA/api/Power.cc @@ -1023,10 +1023,11 @@ unsigned Power::reportPower(bool is_copy) { auto backup_work_space = BackupPwrFiles(output_dir, is_copy); _backup_work_dir = backup_work_space; std::filesystem::create_directories(output_dir); + const char* design_name = ista->get_design_name().c_str(); { std::string file_name = - Str::printf("%s.pwr", ista->get_design_name().c_str()); + Str::printf("%s.pwr", design_name); if (is_copy) { CopyFile(backup_work_space, output_dir, file_name); } @@ -1036,7 +1037,7 @@ unsigned Power::reportPower(bool is_copy) { { std::string file_name = - Str::printf("%s_%s.pwr", ista->get_design_name().c_str(), "instance"); + Str::printf("%s_%s.pwr", design_name, "instance"); if (is_copy) { CopyFile(backup_work_space, output_dir, file_name); @@ -1048,7 +1049,7 @@ unsigned Power::reportPower(bool is_copy) { { std::string file_name = - Str::printf("%s_%s.csv", ista->get_design_name().c_str(), "instance"); + Str::printf("%s_%s.csv", design_name, "instance"); if (is_copy) { CopyFile(backup_work_space, output_dir, file_name); @@ -1059,7 +1060,7 @@ unsigned Power::reportPower(bool is_copy) { if (isJsonReportEnabled()) { std::string file_name = - Str::printf("%s.pwr.json", ista->get_design_name().c_str()); + Str::printf("%s.pwr.json", design_name); if (is_copy) { CopyFile(backup_work_space, output_dir, file_name); } @@ -1068,6 +1069,27 @@ unsigned Power::reportPower(bool is_copy) { reportSummaryPowerJSON(output_path.c_str(), PwrAnalysisMode::kAveraged); } + if (0) { + using json = nlohmann::ordered_json; + + json graph_json; + PwrDumpGraphJson dump_graph_json(graph_json); + auto &the_graph = get_power_graph(); + dump_graph_json(&the_graph); + + std::string graph_json_file_name = Str::printf( + "%s/%s_pwr_graph.json", output_dir.c_str(), design_name); + + std::ofstream out_file(graph_json_file_name); + if (out_file.is_open()) { + out_file << graph_json.dump(4); // 4 spaces indent + LOG_INFO << "JSON report written to: " << graph_json_file_name; + out_file.close(); + } else { + LOG_ERROR << "Failed to open JSON report file: " << graph_json_file_name; + } + } + LOG_INFO << "power report end, output dir: " << output_dir; double memory_delta = stats.memoryDelta(); LOG_INFO << "power report memory usage " << memory_delta << "MB"; diff --git a/src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc b/src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc index d0f628c4b31d89e223a0d35c8bcabba47d3c4488..9ca3c84880c799f7eb30007e382cb4698aeb5cd9 100644 --- a/src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc +++ b/src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc @@ -315,16 +315,24 @@ double PwrCalcInternalPower::calcClockPinPower(Instance* inst, Pin* clock_pin, // rise power auto rise_slew = (*the_clock_sta_vertex) ->getSlewNs(AnalysisMode::kMax, TransType::kRise); - LOG_FATAL_IF(!rise_slew) - << (*the_clock_sta_vertex)->getName() << " rise slew is not exist."; + if (!rise_slew) { + LOG_ERROR_IF(!rise_slew) + << (*the_clock_sta_vertex)->getName() << " rise slew is not exist."; + rise_slew = 0.0; + } + double rise_power = internal_power->gatePower(TransType::kRise, *rise_slew, std ::nullopt); double rise_power_mw = lib_cell->convertTablePowerToMw(rise_power); // fall power auto fall_slew = (*the_clock_sta_vertex) ->getSlewNs(AnalysisMode::kMax, TransType::kFall); - LOG_FATAL_IF(!rise_slew) - << (*the_clock_sta_vertex)->getName() << " fall slew is not exist."; + if (!fall_slew) { + LOG_ERROR_IF(!fall_slew) + << (*the_clock_sta_vertex)->getName() << " fall slew is not exist."; + fall_slew = 0.0; + } + double fall_power = internal_power->gatePower(TransType::kFall, *fall_slew, std ::nullopt); double fall_power_mw = lib_cell->convertTablePowerToMw(fall_power); @@ -475,7 +483,7 @@ double PwrCalcInternalPower::calcCombInternalPower(Instance* inst) { /*calc input port power*/ double pin_internal_power = calcCombInputPinPower(inst, pin, input_sum_toggle, output_pin_toggle); - + the_pwr_vertex->set_internal_power(pin_internal_power); inst_internal_power += pin_internal_power; } @@ -526,8 +534,7 @@ double PwrCalcInternalPower::calcSeqInternalPower(Instance* inst) { /*calc input port power*/ if ((*the_sta_vertex)->is_clock()) { /*calc clk power*/ - pin_internal_power = - calcClockPinPower(inst, pin, output_pin_toggle); + pin_internal_power = calcClockPinPower(inst, pin, output_pin_toggle); inst_internal_power += pin_internal_power; } else { pin_internal_power = calcSeqInputPinPower(inst, pin); @@ -540,7 +547,7 @@ double PwrCalcInternalPower::calcSeqInternalPower(Instance* inst) { /*calc output port power*/ double pin_internal_power = calcOutputPinPower(inst, pin); inst_internal_power += pin_internal_power; - } + } } return inst_internal_power; diff --git a/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.cc b/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.cc index c190f52d2ec0f90f62f0256f390458af302dc52f..fb3887fd5abf2338e7795124ded9c9f7490fc7a7 100644 --- a/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.cc +++ b/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.cc @@ -1,16 +1,16 @@ // *************************************************************************************** // Copyright (c) 2023-2025 Peng Cheng Laboratory -// Copyright (c) 2023-2025 Institute of Computing Technology, Chinese Academy of Sciences -// Copyright (c) 2023-2025 Beijing Institute of Open Source Chip +// Copyright (c) 2023-2025 Institute of Computing Technology, Chinese Academy of +// Sciences Copyright (c) 2023-2025 Beijing Institute of Open Source Chip // // iEDA is licensed under Mulan PSL v2. -// You can use this software according to the terms and conditions of the Mulan PSL v2. -// You may obtain a copy of Mulan PSL v2 at: +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. You may obtain a copy of Mulan PSL v2 at: // http://license.coscl.org.cn/MulanPSL2 // -// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, -// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, -// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // // See the Mulan PSL v2 for more details. // *************************************************************************************** @@ -30,11 +30,11 @@ #include #include +#include "api/Power.hh" #include "core/PwrSeqGraph.hh" -#include "string/Str.hh" #include "sta/Sta.hh" -#include "api/Power.hh" #include "sta/StaDump.hh" +#include "string/Str.hh" namespace ipower { @@ -284,9 +284,9 @@ void PwrDumpGraphViz::printText(const char* file_name) { /** * @brief dump the power node feature. - * - * @param the_graph - * @return PwrDumpGraphJson::json + * + * @param the_graph + * @return PwrDumpGraphJson::json */ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeFeature(PwrGraph* the_graph) { json all_vertex_node_feature_array = json::array(); @@ -343,14 +343,13 @@ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeFeature(PwrGraph* the_graph) { one_node_feature_array.push_back(max_rise_cap); one_node_feature_array.push_back(max_fall_cap); - double toggle_data= pwr_vertex->getToggleData(std::nullopt); - double sp_data= pwr_vertex->getSPData(std::nullopt); + double toggle_data = pwr_vertex->getToggleData(std::nullopt); + double sp_data = pwr_vertex->getSPData(std::nullopt); one_node_feature_array.push_back(toggle_data); one_node_feature_array.push_back(sp_data); all_vertex_node_feature_array.push_back(one_node_feature_array); - } return all_vertex_node_feature_array; @@ -358,9 +357,9 @@ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeFeature(PwrGraph* the_graph) { /** * @brief for net driver node, dump the net power. - * - * @param the_graph - * @return PwrDumpGraphJson::json + * + * @param the_graph + * @return PwrDumpGraphJson::json */ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeNetPower(PwrGraph* the_graph) { json all_vertex_node_net_power_array = json::array(); @@ -390,17 +389,17 @@ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeNetPower(PwrGraph* the_graph) { all_vertex_node_net_power_array.push_back(switch_power); } - return all_vertex_node_net_power_array; } /** * @brief for input pin node, dump the pin internal power. - * - * @param the_graph - * @return PwrDumpGraphJson::json + * + * @param the_graph + * @return PwrDumpGraphJson::json */ -PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeInternalPower(PwrGraph* the_graph) { +PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeInternalPower( + PwrGraph* the_graph) { json all_vertex_node_internal_power_array = json::array(); auto& pwr_vertexes = the_graph->get_vertexes(); for (auto& pwr_vertex : pwr_vertexes) { @@ -413,16 +412,18 @@ PwrDumpGraphJson::json PwrDumpGraphJson::dumpNodeInternalPower(PwrGraph* the_gra /** * @brief for cell instance power arc, dump the arc power. - * - * @param the_graph - * @return PwrDumpGraphJson::json + * + * @param the_graph + * @return PwrDumpGraphJson::json */ -PwrDumpGraphJson::json PwrDumpGraphJson::dumpInstInternalPower(PwrGraph* the_graph) { +PwrDumpGraphJson::json PwrDumpGraphJson::dumpInstInternalPower( + PwrGraph* the_graph) { json all_inst_arc_delay_array = json::array(); auto& pwr_arcs = the_graph->get_arcs(); for (auto& the_pwr_arc : pwr_arcs) { if (the_pwr_arc->isInstArc()) { - double internal_power = dynamic_cast(the_pwr_arc.get())->getInternalPower(); + double internal_power = + dynamic_cast(the_pwr_arc.get())->getInternalPower(); all_inst_arc_delay_array.push_back(internal_power); } } @@ -430,33 +431,112 @@ PwrDumpGraphJson::json PwrDumpGraphJson::dumpInstInternalPower(PwrGraph* the_gra return all_inst_arc_delay_array; } +/** + * @brief dump inst power arc feature. + * + * @param the_graph + * @return PwrDumpGraphJson::json + */ +PwrDumpGraphJson::json PwrDumpGraphJson::dumpInstPowerArcFeature( + PwrGraph* the_graph) { + auto& the_arcs = the_graph->get_arcs(); + json all_inst_arc_lib_data_array = json::array(); + + for (auto& the_arc : the_arcs) { + if (the_arc->isInstArc()) { + json one_inst_arc_table_array = json::array(); + auto* the_pwr_arc_set = + dynamic_cast(the_arc.get())->get_power_arc_set(); + // for skywater130, assume only one power arc. + auto* the_pwr_arc = the_pwr_arc_set->front(); + auto* power_model = dynamic_cast( + the_pwr_arc->get_power_table_model()); + auto& power_tables = power_model->get_tables(); + + for (auto& power_table : power_tables) { + // copy axies + if (power_table) { + double is_valid = 1.0; + one_inst_arc_table_array.push_back(is_valid); + auto& table_axes = power_table->get_axes(); + for (auto& table_axis : table_axes) { + auto& axis_values = table_axis->get_axis_values(); + for (auto& axis_value : axis_values) { + double data_value = axis_value->getFloatValue(); + one_inst_arc_table_array.push_back(data_value); + } + } + } else { + double is_valid = 0.0; + one_inst_arc_table_array.push_back(is_valid); + // hard code 2 axis, 7*2 data + for (int i = 0; i < 7 * 2; i++) { + double data_value = 0.0; + one_inst_arc_table_array.push_back(data_value); + } + } + } + + // copy table values + for (auto& power_table : power_tables) { + if (power_table) { + auto& table_values = power_table->get_table_values(); + for (auto& table_value : table_values) { + one_inst_arc_table_array.push_back(table_value->getFloatValue()); + } + } else { + for (int i = 0; i < 7; ++i) { + double data_value = 0.0; + one_inst_arc_table_array.push_back(data_value); + } + } + } + + all_inst_arc_lib_data_array.push_back(one_inst_arc_table_array); + } + } + + return all_inst_arc_lib_data_array; +} + /** * @brief dump the power graph json for power predict. - * - * @param the_graph - * @return unsigned + * + * @param the_graph + * @return unsigned */ unsigned PwrDumpGraphJson::operator()(PwrGraph* the_graph) { LOG_INFO << "dump graph json start"; auto* the_sta_graph = the_graph->get_sta_graph(); - ista::StaDumpGraphJson dump_graph_json(_json_file); + ista::StaDumpGraphJson dump_sta_graph_json(_json_file); unsigned num_nodes = the_graph->numVertex(); _json_file["num_nodes"] = num_nodes; - _json_file["edges"] = dump_graph_json.dumpEdges(the_sta_graph); - + _json_file["edges"] = dump_sta_graph_json.dumpEdges(the_sta_graph); + // dump node features auto n_node_features = dumpNodeFeature(the_graph); + auto n_internal_power = dumpNodeInternalPower(the_graph); auto n_net_power = dumpNodeNetPower(the_graph); _json_file["node_features"]["nf"] = n_node_features; - _json_file["node_features"]["n_net_powers"] = n_node_features; + _json_file["node_features"]["n_internal_powers"] = n_internal_power; + _json_file["node_features"]["n_net_powers"] = n_net_power; // dump arc features auto e_inst_arc_internal_power = dumpInstInternalPower(the_graph); - _json_file["edge_features"]["e_inst_arc_internal_power"] = e_inst_arc_internal_power; - + auto e_net_in_arc_features = + dump_sta_graph_json.dumpNetInArcFeature(the_sta_graph); + auto e_net_out_arc_features = + dump_sta_graph_json.dumpNetOutArcFeature(the_sta_graph); + auto e_inst_pwr_arc_features = dumpInstPowerArcFeature(the_graph); + + _json_file["edge_features"]["cell_out"]["e_inst_arc_internal_power"] = + e_inst_arc_internal_power; + _json_file["edge_features"]["cell_out"]["ef"] = e_inst_pwr_arc_features; + _json_file["edge_features"]["net_in"]["ef"] = e_net_in_arc_features; + _json_file["edge_features"]["net_out"]["ef"] = e_net_out_arc_features; LOG_INFO << "dump graph json end"; return 1; diff --git a/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.hh b/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.hh index 3d999b6b66c8e0c6dc1036402ec1168e5032a202..cdca5f0bd9c12a2d2733d54cae3d00069106ef32 100644 --- a/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.hh +++ b/src/operation/iPA/source/module/ops/dump/PwrDumpGraph.hh @@ -81,6 +81,7 @@ class PwrDumpGraphJson : public PwrFunc { json dumpNodeNetPower(PwrGraph* the_graph); json dumpNodeInternalPower(PwrGraph* the_graph); json dumpInstInternalPower(PwrGraph* the_graph); + json dumpInstPowerArcFeature(PwrGraph* the_graph); private: json& _json_file; diff --git a/src/operation/iSTA/source/module/sta/Sta.cc b/src/operation/iSTA/source/module/sta/Sta.cc index 2d9c0a37b9edb0133e3f054b5454025d37bcf164..ff3a0a782df90336ec596fa9f87bfe28f896766a 100644 --- a/src/operation/iSTA/source/module/sta/Sta.cc +++ b/src/operation/iSTA/source/module/sta/Sta.cc @@ -812,7 +812,7 @@ void Sta::linkDesignWithRustParser(const char *top_cell_name) { LOG_ERROR << "the right port is not exist."; } - } else if (the_right_net && !the_right_port) { + } else if (the_right_net) { // assign output_port = net; if (the_left_port) { the_right_net->addPinPort(the_left_port); diff --git a/src/operation/iSTA/source/module/sta/StaArc.hh b/src/operation/iSTA/source/module/sta/StaArc.hh index 981436aed54af48959c15b8813f63cf8df812dd9..4255e2089ff0428147492738dd2926751bc040e3 100644 --- a/src/operation/iSTA/source/module/sta/StaArc.hh +++ b/src/operation/iSTA/source/module/sta/StaArc.hh @@ -59,6 +59,8 @@ class StaArc { virtual unsigned isPositiveArc() const { return 0; } virtual unsigned isNegativeArc() const { return 0; } virtual unsigned isUnateArc() const { return 0; } + + virtual unsigned isTwoTypeSenseArc() const { return 0; } virtual unsigned isSetupArc() const { return 0; } virtual unsigned isHoldArc() const { return 0; } virtual unsigned isRecoveryArc() const { return 0; } @@ -214,9 +216,19 @@ class StaInstArc : public StaArc { unsigned isRecoveryArc() const override { return _lib_arc->isRecoveryArc(); } unsigned isRemovalArc() const override { return _lib_arc->isRemovalArc(); } - unsigned isPositiveArc() const override { return _lib_arc->isPositiveArc(); } - unsigned isNegativeArc() const override { return _lib_arc->isNegativeArc(); } - unsigned isUnateArc() const override { return _lib_arc->isUnateArc(); } + unsigned isPositiveArc() const override { + return _lib_arc_set->isPositiveArc(); + } + unsigned isNegativeArc() const override { + return _lib_arc_set->isNegativeArc(); + } + unsigned isUnateArc() const override { + return _lib_arc_set->isUnateArc(); + } + + unsigned isTwoTypeSenseArc() const override { + return _lib_arc_set->isTwoTypeSenseArcSet(); + } unsigned isRisingEdgeCheck() const override { return _lib_arc->isRisingEdgeCheck(); @@ -245,9 +257,9 @@ class StaInstArc : public StaArc { #endif private: - LibArc* _lib_arc; //!< The mapped to lib arc. - LibArcSet* _lib_arc_set; //!< The mapped to lib arc set. - Instance* _inst; //!< The owned inst. + LibArc* _lib_arc; //!< The mapped to lib arc. + LibArcSet* _lib_arc_set = nullptr; //!< The mapped to lib arc set. + Instance* _inst; //!< The owned inst. #if CUDA_PROPAGATION Lib_Arc_GPU* _lib_gpu_arc = nullptr; //!< The gpu lib arc. diff --git a/src/operation/iSTA/source/module/sta/StaDataSlewDelayPropagation.cc b/src/operation/iSTA/source/module/sta/StaDataSlewDelayPropagation.cc index 7aae98c6ba1a049fec28c5f953d48046db28bf85..effc19ea3e69462b3411bf28b7c00bdefa8baf60 100644 --- a/src/operation/iSTA/source/module/sta/StaDataSlewDelayPropagation.cc +++ b/src/operation/iSTA/source/module/sta/StaDataSlewDelayPropagation.cc @@ -38,7 +38,6 @@ namespace ista { * @return unsigned */ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { - #if 0 std::lock_guard lk(the_arc->get_snk()->get_fwd_mutex()); StaSlewPropagation slew_propagation; @@ -122,8 +121,8 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { if (the_arc->isInstArc()) { auto* inst_arc = dynamic_cast(the_arc); auto* lib_arc = inst_arc->get_lib_arc(); - auto* lib_arc_set = dynamic_cast(the_arc)->get_lib_arc_set(); - auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); + auto* lib_arc_set = + dynamic_cast(the_arc)->get_lib_arc_set(); if (the_arc->isCheckArc()) { // Since slew is fitter accord trigger type, May be do not need below @@ -144,7 +143,7 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { dynamic_cast(snk_slew_data)->get_slew(); auto snk_slew = FS_TO_NS(snk_slew_fs); auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs( - snk_trans_type, in_slew, snk_slew); + trans_type, snk_trans_type, in_slew, snk_slew); double delay_ns = analysis_mode == AnalysisMode::kMax ? delay_values.front() : delay_values.back(); @@ -152,7 +151,8 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { StaArcDelayData* arc_delay = nullptr; if (isIncremental()) { - arc_delay = the_arc->getArcDelayData(analysis_mode, snk_trans_type); + arc_delay = + the_arc->getArcDelayData(analysis_mode, snk_trans_type); } if (!arc_delay) { @@ -163,19 +163,31 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { } } else if (the_arc->isDelayArc()) { - auto out_trans_type = lib_arc->isNegativeArc() + auto out_trans_type = the_arc->isNegativeArc() ? flip_trans_type(trans_type) : trans_type; auto* rc_net = getSta()->getRcNet(the_net); - auto load_pf = rc_net - ? rc_net->load(analysis_mode, out_trans_type) - : the_net->getLoad(analysis_mode, out_trans_type); - double load = load_pf; - if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { - load = PF_TO_FF(load_pf); - } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { - load = load_pf; + auto trans_to_index = [](TransType trans_type) -> int { + return static_cast(trans_type) - 1; + }; + + std::array load_array; // rise, fall load. + + for (auto load_trans_type : {TransType::kRise, TransType::kFall}) { + auto load_pf = + rc_net ? rc_net->load(analysis_mode, out_trans_type) + : the_net->getLoad(analysis_mode, out_trans_type); + auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); + + double load{0}; + if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { + load = PF_TO_FF(load_pf); + } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { + load = load_pf; + } + + load_array[trans_to_index(load_trans_type)] = load; } if (auto* arnoldi_net = dynamic_cast(rc_net); @@ -185,17 +197,24 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type)) { continue; } - auto out_slew_ns = lib_arc->getSlewNs(out_trans_type, in_slew, load); + auto slew_values = lib_arc_set->getSlewNs( + trans_type, out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); + double out_slew_ns = analysis_mode == AnalysisMode::kMax + ? slew_values.front() + : slew_values.back(); - auto output_current = - lib_arc->getOutputCurrent(out_trans_type, in_slew, load); + auto output_current = lib_arc->getOutputCurrent( + out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); - auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs(out_trans_type, - in_slew, load); + auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs( + trans_type, out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); double delay_ns = analysis_mode == AnalysisMode::kMax ? delay_values.front() : delay_values.back(); @@ -206,23 +225,32 @@ unsigned StaDataSlewDelayPropagation::operator()(StaArc* the_arc) { std::move(output_current), slew_data); /*The non-unate arc or tco should split two.*/ - if (!lib_arc->isUnateArc() || src_vertex->is_clock()) { + if (!the_arc->isUnateArc() || the_arc->isTwoTypeSenseArc() || src_vertex->is_clock()) { auto out_trans_type1 = flip_trans_type(trans_type); // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type1)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type1)) { continue; } - auto out_slew1_ns = - lib_arc->getSlewNs(out_trans_type1, in_slew, load); + auto slew_values = lib_arc_set->getSlewNs( + trans_type, out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); + double out_slew1_ns = analysis_mode == AnalysisMode::kMax + ? slew_values.front() + : slew_values.back(); - auto output_current1 = - lib_arc->getOutputCurrent(out_trans_type1, in_slew, load); + auto output_current1 = lib_arc->getOutputCurrent( + out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); - auto delay1_ns = lib_arc->getDelayOrConstrainCheckNs( - out_trans_type1, in_slew, load); + auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs( + trans_type, out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); + double delay1_ns = analysis_mode == AnalysisMode::kMax + ? delay_values.front() + : delay_values.back(); auto delay1 = NS_TO_FS(delay1_ns); construct_slew_delay_data(analysis_mode, out_trans_type1, diff --git a/src/operation/iSTA/source/module/sta/StaDelayPropagation.cc b/src/operation/iSTA/source/module/sta/StaDelayPropagation.cc index a0ab2df7e4e25193054088c1aeacdf2d13c4d65d..02256cb17afeb128ae5b43b728818329bae288f0 100644 --- a/src/operation/iSTA/source/module/sta/StaDelayPropagation.cc +++ b/src/operation/iSTA/source/module/sta/StaDelayPropagation.cc @@ -83,7 +83,8 @@ unsigned StaDelayPropagation::operator()(StaArc* the_arc) { if (the_arc->isInstArc()) { auto* lib_arc = dynamic_cast(the_arc)->get_lib_arc(); - auto* lib_arc_set = dynamic_cast(the_arc)->get_lib_arc_set(); + auto* lib_arc_set = + dynamic_cast(the_arc)->get_lib_arc_set(); /*The check arc is the end of the recursion .*/ if (the_arc->isCheckArc()) { // Since slew is fitter accord trigger type, May be do not need below @@ -103,7 +104,7 @@ unsigned StaDelayPropagation::operator()(StaArc* the_arc) { auto snk_slew_fs = dynamic_cast(snk_slew_data)->get_slew(); auto snk_slew = FS_TO_NS(snk_slew_fs); - auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs( + auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs(trans_type, snk_trans_type, in_slew, snk_slew); double delay_ns = analysis_mode == AnalysisMode::kMax ? delay_values.front() @@ -115,30 +116,41 @@ unsigned StaDelayPropagation::operator()(StaArc* the_arc) { } else if (the_arc->isDelayArc()) { auto* rc_net = getSta()->getRcNet(the_net); - auto out_trans_type = lib_arc->isNegativeArc() + auto out_trans_type = the_arc->isNegativeArc() ? flip_trans_type(trans_type) : trans_type; + auto trans_to_index = [](TransType trans_type) -> int { + return static_cast(trans_type) - 1; + }; + + std::array load_array; // rise, fall load. + + for (auto load_trans_type : {TransType::kRise, TransType::kFall}) { + auto load_pf = + rc_net ? rc_net->load(analysis_mode, out_trans_type) + : the_net->getLoad(analysis_mode, out_trans_type); + auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); + + double load{0}; + if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { + load = PF_TO_FF(load_pf); + } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { + load = load_pf; + } - auto load_pf = rc_net ? rc_net->load(analysis_mode, out_trans_type) - : the_net->getLoad(analysis_mode, out_trans_type); - auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); - - double load{0}; - if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { - load = PF_TO_FF(load_pf); - } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { - load = load_pf; + load_array[trans_to_index(load_trans_type)] = load; } // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type)) { continue; } - + // assure delay values sort by descending order. - auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs(out_trans_type, - in_slew, load); + auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs(trans_type, + out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); double delay_ns = analysis_mode == AnalysisMode::kMax ? delay_values.front() : delay_values.back(); @@ -146,16 +158,20 @@ unsigned StaDelayPropagation::operator()(StaArc* the_arc) { construct_delay_data(analysis_mode, out_trans_type, the_arc, delay); /*The unate arc should split two.*/ - if (!lib_arc->isUnateArc() || src_vertex->is_clock()) { + if (!the_arc->isUnateArc() || the_arc->isTwoTypeSenseArc() || src_vertex->is_clock()) { auto out_trans_type1 = flip_trans_type(trans_type); // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type1)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type1)) { continue; } - auto delay1_ns = lib_arc->getDelayOrConstrainCheckNs( - out_trans_type1, in_slew, load); + auto delay_values = lib_arc_set->getDelayOrConstrainCheckNs(trans_type, + out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); + double delay1_ns = analysis_mode == AnalysisMode::kMax + ? delay_values.front() + : delay_values.back(); auto delay1 = NS_TO_FS(delay1_ns); construct_delay_data(analysis_mode, out_trans_type1, the_arc, diff --git a/src/operation/iSTA/source/module/sta/StaDump.cc b/src/operation/iSTA/source/module/sta/StaDump.cc index 8a3d9775c5b98e25fa0da8e5ec012c7159be092d..29fbb6b07677f4140b61d7d2b9bbbd8fea2c0a53 100644 --- a/src/operation/iSTA/source/module/sta/StaDump.cc +++ b/src/operation/iSTA/source/module/sta/StaDump.cc @@ -613,23 +613,21 @@ StaDumpGraphJson::json StaDumpGraphJson::dumpEdges(StaGraph* the_graph) { auto& the_arcs = the_graph->get_arcs(); for (auto& the_arc : the_arcs) { if (the_arc->isDelayArc()) { - int src_id = vertex_id_map[the_arc->get_src()]; - int snk_id = vertex_id_map[the_arc->get_snk()]; - - if (the_arc->isInstArc() && the_arc->isDelayArc()) { - edges["cell_out"]["src"].push_back(src_id); - edges["cell_out"]["dst"].push_back(snk_id); - } else if (the_arc->isNetArc()) { - edges["net_out"]["src"].push_back(src_id); - edges["net_out"]["dst"].push_back(snk_id); - - // reverse direction for net out - edges["net_in"]["src"].push_back(snk_id); - edges["net_in"]["dst"].push_back(src_id); - } - + int src_id = vertex_id_map[the_arc->get_src()]; + int snk_id = vertex_id_map[the_arc->get_snk()]; + + if (the_arc->isInstArc() && the_arc->isDelayArc()) { + edges["cell_out"]["src"].push_back(src_id); + edges["cell_out"]["dst"].push_back(snk_id); + } else if (the_arc->isNetArc()) { + edges["net_out"]["src"].push_back(src_id); + edges["net_out"]["dst"].push_back(snk_id); + + // reverse direction for net out + edges["net_in"]["src"].push_back(snk_id); + edges["net_in"]["dst"].push_back(src_id); + } } - } return edges; } @@ -689,7 +687,10 @@ StaDumpGraphJson::json StaDumpGraphJson::dumpNodeNetDelay(StaGraph* the_graph) { std::string obj_name = the_obj->getFullName(); auto* the_net = the_obj->get_net(); auto* rc_net = getSta()->getRcNet(the_net); - auto* rc_tree = rc_net->rct(); + RcTree* rc_tree = nullptr; + if (rc_net) { + rc_tree = rc_net->rct(); + } double max_rise_delay = 0.0; double max_fall_delay = 0.0; @@ -961,7 +962,7 @@ StaDumpGraphJson::json StaDumpGraphJson::dumpInstArcFeature( double is_valid = 0.0; one_inst_arc_table_array.push_back(is_valid); // hard code 2 axis, 7*2 data - for (int i = 0; i < 7 * 2; i++) { + for (int i = 0; i < 7 * 2; ++i) { double data_value = 0.0; one_inst_arc_table_array.push_back(data_value); } @@ -970,9 +971,16 @@ StaDumpGraphJson::json StaDumpGraphJson::dumpInstArcFeature( // copy table values for (auto* delay_table : store_tables) { - auto& table_values = delay_table->get_table_values(); - for (auto& table_value : table_values) { - one_inst_arc_table_array.push_back(table_value->getFloatValue()); + if (delay_table) { + auto& table_values = delay_table->get_table_values(); + for (auto& table_value : table_values) { + one_inst_arc_table_array.push_back(table_value->getFloatValue()); + } + } else { + for (int i = 0; i < 7; ++i) { + double data_value = 0.0; + one_inst_arc_table_array.push_back(data_value); + } } } diff --git a/src/operation/iSTA/source/module/sta/StaSlewPropagation.cc b/src/operation/iSTA/source/module/sta/StaSlewPropagation.cc index e99c7976329a95b3fdbaa99b690d0906d3d2d374..5bf478e832274d80dabcb832252fecf071f5a9bc 100644 --- a/src/operation/iSTA/source/module/sta/StaSlewPropagation.cc +++ b/src/operation/iSTA/source/module/sta/StaSlewPropagation.cc @@ -69,7 +69,6 @@ unsigned StaSlewPropagation::operator()(StaArc* the_arc) { slew_data->set_slew(slew); slew_data->set_output_current_data(std::move(output_current_data)); } - }; unsigned is_ok = 1; @@ -85,11 +84,10 @@ unsigned StaSlewPropagation::operator()(StaArc* the_arc) { } auto* the_pin = dynamic_cast(obj); - LOG_FATAL_IF(!the_pin) << "obj " << obj->getFullName() - << " is not a pin"; + LOG_FATAL_IF(!the_pin) << "obj " << obj->getFullName() << " is not a pin"; auto* the_net = the_pin->get_net(); LOG_FATAL_IF(!the_net) << "The pin " << the_pin->getFullName() - << " has not connect net."; + << " has not connect net."; StaData* slew_data; FOREACH_SLEW_DATA(src_vertex, slew_data) { @@ -112,19 +110,33 @@ unsigned StaSlewPropagation::operator()(StaArc* the_arc) { if (the_arc->isInstArc()) { auto* inst_arc = dynamic_cast(the_arc); auto* lib_arc = inst_arc->get_lib_arc(); - auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); + auto* lib_arc_set = + dynamic_cast(the_arc)->get_lib_arc_set(); auto out_trans_type = - lib_arc->isNegativeArc() ? flip_trans_type(trans_type) : trans_type; + the_arc->isNegativeArc() ? flip_trans_type(trans_type) : trans_type; auto* rc_net = getSta()->getRcNet(the_net); - auto load_pf = rc_net ? rc_net->load(analysis_mode, out_trans_type) - : the_net->getLoad(analysis_mode, out_trans_type); - double load = load_pf; - if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { - load = PF_TO_FF(load_pf); - } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { - load = load_pf; + auto trans_to_index = [](TransType trans_type) -> int { + return static_cast(trans_type) - 1; + }; + + std::array load_array; // rise, fall load. + + for (auto load_trans_type : {TransType::kRise, TransType::kFall}) { + auto load_pf = rc_net + ? rc_net->load(analysis_mode, out_trans_type) + : the_net->getLoad(analysis_mode, out_trans_type); + auto* the_lib = lib_arc->get_owner_cell()->get_owner_lib(); + + double load{0}; + if (the_lib->get_cap_unit() == CapacitiveUnit::kFF) { + load = PF_TO_FF(load_pf); + } else if (the_lib->get_cap_unit() == CapacitiveUnit::kPF) { + load = load_pf; + } + + load_array[trans_to_index(load_trans_type)] = load; } if (auto* arnoldi_net = dynamic_cast(rc_net); @@ -134,34 +146,45 @@ unsigned StaSlewPropagation::operator()(StaArc* the_arc) { // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type)) { continue; } - auto out_slew_ns = lib_arc->getSlewNs(out_trans_type, in_slew, load); + auto slew_values = + lib_arc_set->getSlewNs(trans_type, out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); + double out_slew_ns = analysis_mode == AnalysisMode::kMax + ? slew_values.front() + : slew_values.back(); - auto output_current = - lib_arc->getOutputCurrent(out_trans_type, in_slew, load); + auto output_current = lib_arc->getOutputCurrent( + out_trans_type, in_slew, + load_array[trans_to_index(out_trans_type)]); construct_slew_data(analysis_mode, out_trans_type, snk_vertex, NS_TO_FS(out_slew_ns), std::move(output_current), slew_data); /*The non-unate arc or tco should split two.*/ - if (!lib_arc->isUnateArc() || src_vertex->is_clock()) { + if (!the_arc->isUnateArc() || the_arc->isTwoTypeSenseArc() || src_vertex->is_clock()) { auto out_trans_type1 = flip_trans_type(trans_type); // fix the timing type not match the trans type, which would lead to // crash. - if (!lib_arc->isMatchTimingType(out_trans_type1)) { + if (!lib_arc_set->isMatchTimingType(out_trans_type1)) { continue; } - auto out_slew1_ns = - lib_arc->getSlewNs(out_trans_type1, in_slew, load); + auto slew_values = + lib_arc_set->getSlewNs(trans_type, out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); + double out_slew1_ns = analysis_mode == AnalysisMode::kMax + ? slew_values.front() + : slew_values.back(); - auto output_current1 = - lib_arc->getOutputCurrent(out_trans_type1, in_slew, load); + auto output_current1 = lib_arc->getOutputCurrent( + out_trans_type1, in_slew, + load_array[trans_to_index(out_trans_type1)]); construct_slew_data(analysis_mode, out_trans_type1, snk_vertex, NS_TO_FS(out_slew1_ns), diff --git a/src/vectorization/readme.dm b/src/vectorization/README.md similarity index 100% rename from src/vectorization/readme.dm rename to src/vectorization/README.md diff --git a/src/vectorization/database/vec_instance.h b/src/vectorization/database/vec_instance.h index 960ab7b4c4ecdb78f195d6b111a519aa203791d7..a4cf10d58b4bbe00b74959aa88ff242115f61cfa 100644 --- a/src/vectorization/database/vec_instance.h +++ b/src/vectorization/database/vec_instance.h @@ -38,8 +38,8 @@ struct VecInstance uint64_t id; int cell_id; std::string name; - int x; - int y; + int cx; + int cy; int width; int height; int llx; diff --git a/src/vectorization/database/vec_net.h b/src/vectorization/database/vec_net.h index a37cac3ad4c91b6438a68ef29f83b5951fe2480e..e00584aa8388730fc159cce9debbdce3fef1da1e 100644 --- a/src/vectorization/database/vec_net.h +++ b/src/vectorization/database/vec_net.h @@ -49,6 +49,18 @@ struct VecNetWireFeature std::vector drc_type = {}; }; +struct VecPlaceFeature +{ + int pin_num = 0; + int aspect_ratio = 0; + int64_t width = 0; + int64_t height = 0; + int64_t area = 0; + float l_ness = 0.0; + int64_t hpwl = 0; + int64_t rsmt = 0; +}; + struct VecNetFeature { int llx = 0; @@ -63,16 +75,14 @@ struct VecNetFeature double power = 0.0; double delay = 0.0; double slew = 0.0; - int fanout = 0; int aspect_ratio = 0; int64_t width = 0; int64_t height = 0; int64_t area = 0; - float l_ness = 0.0; - std::vector drc_type = {}; int64_t volume = 0; - std::vector layer_ratio = {}; - int rsmt = 0; + std::vector drc_type = {}; + std::vector layer_ratio = {}; + VecPlaceFeature place_feature; }; static int64_t wire_id_index = 0; diff --git a/src/vectorization/src/data_manager/vec_file.cpp b/src/vectorization/src/data_manager/vec_file.cpp index 5b82bddb9289041d8906827af7ea9bdad90843f3..c26d7164badc006dfa5ff5227d4ec5def745984e 100644 --- a/src/vectorization/src/data_manager/vec_file.cpp +++ b/src/vectorization/src/data_manager/vec_file.cpp @@ -124,15 +124,23 @@ bool VecLayoutFileIO::saveJsonNets(bool batch_mode) json_feature["power"] = net_feature->power; json_feature["delay"] = net_feature->delay; json_feature["slew"] = net_feature->slew; - json_feature["fanout"] = net_feature->fanout; json_feature["aspect_ratio"] = net_feature->aspect_ratio; json_feature["width"] = net_feature->width; json_feature["height"] = net_feature->height; json_feature["area"] = net_feature->area; json_feature["volume"] = net_feature->volume; - json_feature["l_ness"] = net_feature->l_ness; json_feature["layer_ratio"] = net_feature->layer_ratio; - json_feature["rsmt"] = net_feature->rsmt; + // place_feature + json json_place_feature = {}; + json_place_feature["pin_num"] = net_feature->place_feature.pin_num; + json_place_feature["aspect_ratio"] = net_feature->place_feature.aspect_ratio; + json_place_feature["width"] = net_feature->place_feature.width; + json_place_feature["height"] = net_feature->place_feature.height; + json_place_feature["area"] = net_feature->place_feature.area; + json_place_feature["l_ness"] = net_feature->place_feature.l_ness; + json_place_feature["hpwl"] = net_feature->place_feature.hpwl; + json_place_feature["rsmt"] = net_feature->place_feature.rsmt; + json_feature["place_feature"] = json_place_feature; } json_net["feature"] = json_feature; } @@ -409,7 +417,6 @@ bool VecLayoutFileIO::saveJsonPatchs(bool batch_mode) json_patch["row_max"] = patch.rowIdMax; json_patch["col_min"] = patch.colIdMin; json_patch["col_max"] = patch.colIdMax; - json_patch["area"] = area; json_patch["cell_density"] = patch.cell_density; json_patch["pin_density"] = patch.pin_density; json_patch["net_density"] = patch.net_density; @@ -494,7 +501,7 @@ bool VecLayoutFileIO::saveJsonPatchs(bool batch_mode) json_wire["feature"] = json_feature; } - /// paths + /// paths { auto& paths = wire.get_paths(); json_wire["path_num"] = paths.size(); @@ -761,8 +768,8 @@ bool VecLayoutFileIO::saveJsonInstances() json_inst["id"] = vec_inst.id; json_inst["cell_id"] = vec_inst.cell_id; json_inst["name"] = vec_inst.name; - json_inst["x"] = vec_inst.x; - json_inst["y"] = vec_inst.y; + json_inst["cx"] = vec_inst.cx; + json_inst["cy"] = vec_inst.cy; json_inst["width"] = vec_inst.width; json_inst["height"] = vec_inst.height; json_inst["llx"] = vec_inst.llx; diff --git a/src/vectorization/src/feature/vec_feature_drc.cpp b/src/vectorization/src/feature/vec_feature_drc.cpp index 6ff1a0ecf89983733f9b24459a12bb2fff02a72a..967d796899e85e98995326867852e620e3ce53bc 100644 --- a/src/vectorization/src/feature/vec_feature_drc.cpp +++ b/src/vectorization/src/feature/vec_feature_drc.cpp @@ -66,7 +66,7 @@ void VecFeatureDrc::markNodes() int drc_id = 0; int drc_without_net = 0; - // 新增:用于记录 drc_id 和 drc_type(rule)的映射 + // used for recording the mapping between drc_id and drc_type (rule) std::map drc_id_to_type; for (auto& [rule, drc_list_map] : detail_drc_map) { @@ -93,7 +93,7 @@ void VecFeatureDrc::markNodes() auto& node_feature = node->get_node_data()->get_feature(); omp_set_lock(&lck); node_feature.drc_ids.insert(drc_id + i); - drc_id_to_type[drc_id + i] = rule; // 将 drc_id 和 rule 关联 + drc_id_to_type[drc_id + i] = rule; // record the mapping between drc_id and drc_type (rule) omp_unset_lock(&lck); if (node->get_node_data()->get_net_id() >= 0) { @@ -178,7 +178,7 @@ void VecFeatureDrc::markWires() mark_drc_num += drc_ids.size(); omp_unset_lock(&lck); } else { - // 如果路径跨层,分别处理 node1 和 node2 的 drc_ids + // if path cross layer, handle drc_ids of node1 and node2 separately drc_ids.insert(node1->get_node_data()->get_feature().drc_ids.begin(), node1->get_node_data()->get_feature().drc_ids.end()); drc_ids.insert(node2->get_node_data()->get_feature().drc_ids.begin(), node2->get_node_data()->get_feature().drc_ids.end()); @@ -194,9 +194,8 @@ void VecFeatureDrc::markWires() omp_unset_lock(&lck); } } - // 填充 wire_feature->drc_type for (auto drc_id : drc_ids) { - wire_feature->drc_type.push_back(_drc_id_to_type[drc_id]); // 根据 drc_id 获取对应的 drc_type + wire_feature->drc_type.push_back(_drc_id_to_type[drc_id]); // obtain drc_type according to drc_id } } @@ -234,7 +233,6 @@ void VecFeatureDrc::markNets() auto& layer_map = layout_layers.get_layout_layer_map(); for (int layer_id = 0; layer_id < (int) layer_map.size(); ++layer_id) { auto& grid = layout_layers.findLayoutLayer(layer_id)->get_grid(); - // 这里改用get_all_nodes()替代原来的get_node_matrix() auto nodes = grid.get_all_nodes(); #pragma omp parallel for schedule(dynamic) @@ -266,10 +264,9 @@ void VecFeatureDrc::markNets() auto* net_feature = vec_net.get_feature(true); net_feature->drc_num += net_drc_map[i].size(); - // 填充 drc_type for (auto drc_id : net_drc_map[i]) { omp_set_lock(&lck); - net_feature->drc_type.push_back(_drc_id_to_type[drc_id]); // 根据 drc_id 获取对应的 drc_type + net_feature->drc_type.push_back(_drc_id_to_type[drc_id]); // obtain drc_type according to drc_id omp_unset_lock(&lck); } diff --git a/src/vectorization/src/feature/vec_feature_statis.cpp b/src/vectorization/src/feature/vec_feature_statis.cpp index 099daf7d1c37491207c0fb77d8fa1c0fefb79a93..3409305bb8d81ad66fef2b33de894df5120696d9 100644 --- a/src/vectorization/src/feature/vec_feature_statis.cpp +++ b/src/vectorization/src/feature/vec_feature_statis.cpp @@ -17,6 +17,7 @@ #include "vec_feature_statis.h" +#include #include #include #include @@ -78,20 +79,26 @@ void VecFeatureStatis::feature_graph() auto* net_feature = vec_net.get_feature(true); std::string net_name = _layout->findNetName(it->first); - net_feature->aspect_ratio = CONGESTION_API_INST->findAspectRatio(net_name); - net_feature->width = CONGESTION_API_INST->findBBoxWidth(net_name); - net_feature->height = CONGESTION_API_INST->findBBoxHeight(net_name); - net_feature->area = CONGESTION_API_INST->findBBoxArea(net_name); - net_feature->l_ness = CONGESTION_API_INST->findLness(net_name); - net_feature->rsmt = WIRELENGTH_API_INST->findNetFLUTE(net_name); - - /// 初始化 layer_ratio - int16_t min_order = INT8_MAX; // 记录最小层 - int16_t max_order = INT8_MIN; // 记录最大层 + + net_feature->place_feature.pin_num = CONGESTION_API_INST->findPinNumber(net_name); + net_feature->place_feature.aspect_ratio = CONGESTION_API_INST->findAspectRatio(net_name); + net_feature->place_feature.width = CONGESTION_API_INST->findBBoxWidth(net_name); + net_feature->place_feature.height = CONGESTION_API_INST->findBBoxHeight(net_name); + net_feature->place_feature.area = CONGESTION_API_INST->findBBoxArea(net_name); + net_feature->place_feature.l_ness = CONGESTION_API_INST->findLness(net_name); + net_feature->place_feature.rsmt = WIRELENGTH_API_INST->findNetFLUTE(net_name); + net_feature->place_feature.hpwl = net_feature->place_feature.width + net_feature->place_feature.height; + + /// init layer_ratio + int16_t min_order = INT8_MAX; // record minimum layer + int16_t max_order = INT8_MIN; // record maximum layer int layer_order_top = layout_layers.get_layer_order_top(); int layer_order_bottom = layout_layers.get_layer_order_bottom(); - int num_layers = layer_order_top - layer_order_bottom + 1; // 总布线层数 - net_feature->layer_ratio = std::vector(num_layers, 0); + int num_layers = layer_order_top - layer_order_bottom + 1; // total number of layers + net_feature->layer_ratio = std::vector(num_layers, 0.0f); + + std::vector layer_wire_length(num_layers, 0.0); + double total_wire_length = 0.0; for (auto& wire : vec_net.get_wires()) { auto* wire_feature = wire.get_feature(true); @@ -103,14 +110,8 @@ void VecFeatureStatis::feature_graph() auto& grid = layout_layer->get_grid(); auto layer_name = layout_layer->get_layer_name(); - /// 更新最小层和最大层 min_order = std::min(min_order, order); max_order = std::max(max_order, order); - /// 更新 layer_ratio - if (order >= layer_order_bottom && order <= layer_order_top) { - int layer_index = order - layer_order_bottom; // 计算层的索引 - net_feature->layer_ratio[layer_index] = 1; // 设置为 1,表示该层有线经过 - } /// set feature wire_feature->wire_width = layout_layer->get_wire_width(); @@ -155,8 +156,15 @@ void VecFeatureStatis::feature_graph() int horizontal_len = (max_col - min_col) * gridInfoInst.x_step; int vertical_len = (max_row - min_row) * gridInfoInst.y_step; + double segment_length = horizontal_len + vertical_len; + + if (order >= layer_order_bottom && order <= layer_order_top) { + int layer_index = order - layer_order_bottom; + layer_wire_length[layer_index] += segment_length; + total_wire_length += segment_length; + } - wire_feature->wire_len += (horizontal_len + vertical_len); + wire_feature->wire_len += segment_length; wire_feature->wire_density = wire_feature->wire_len * wire_feature->wire_width / static_cast(net_feature->area); /// some feature label on node @@ -179,18 +187,37 @@ void VecFeatureStatis::feature_graph() net_feature->urx = gridInfoInst.calculate_x(net_col_max); net_feature->lly = gridInfoInst.calculate_y(net_row_min); net_feature->ury = gridInfoInst.calculate_y(net_row_max); - net_feature->fanout = vec_net.get_pin_ids().size() - 1; + net_feature->width = net_feature->urx - net_feature->llx; + net_feature->height = net_feature->ury - net_feature->lly; + net_feature->area = net_feature->width * net_feature->height; + + if (net_feature->width >= net_feature->height && net_feature->height != 0) { + net_feature->aspect_ratio = std::round(net_feature->width / static_cast(net_feature->height)); + } else if (net_feature->height > net_feature->width && net_feature->width != 0) { + net_feature->aspect_ratio = std::round(net_feature->height / static_cast(net_feature->width)); + } } - /// 计算 BBox体积 + if (total_wire_length > 0) { + for (int i = 0; i < num_layers; ++i) { + double ratio = layer_wire_length[i] / total_wire_length; + net_feature->layer_ratio[i] = static_cast(std::round(ratio * 100.0) / 100.0); + } + } else { + for (int i = 0; i < num_layers; ++i) { + net_feature->layer_ratio[i] = 0.0f; + } + } + + /// calculate volume if (min_order != INT32_MAX && max_order != INT32_MIN) { int total_height = (max_order - min_order); if (total_height == 0) { - total_height = 1; // 如果只在一层,层高为单层高度 + total_height = 1; // if only one layer, set height to 1 } net_feature->volume = net_feature->area * total_height; } else { - net_feature->volume = 0; // 如果没有有效的层,体积为 0 + net_feature->volume = 0; } if (i % 1000 == 0) { @@ -221,31 +248,17 @@ void VecFeatureStatis::feature_patch() omp_lock_t lck; omp_init_lock(&lck); - // 评估器特征计算,返回的是 patch_id 和 value 的 map + // key is patch_id, value is the corresponding map value. std::map cell_power_map = TimingPower_API_INST->patchPowerMap(patch_xy_map); std::map cell_timing_map = TimingPower_API_INST->patchTimingMap(patch_xy_map); std::map cell_ir_map = TimingPower_API_INST->patchIRDropMap(patch_xy_map); - std::map pin_density_map = DENSITY_API_INST->patchPinDensity(patch_xy_map); - LOG_INFO << "finish pin_density_map, runtime: " << stats.elapsedRunTime(); - std::map cell_density_map = DENSITY_API_INST->patchCellDensity(patch_xy_map); - LOG_INFO << "finish cell_density_map, runtime: " << stats.elapsedRunTime(); - std::map net_density_map = DENSITY_API_INST->patchNetDensity(patch_xy_map); - LOG_INFO << "finish net_density_map, runtime: " << stats.elapsedRunTime(); - std::map macro_margin_map = DENSITY_API_INST->patchMacroMargin(patch_xy_map); - LOG_INFO << "finish macro_margin_map, runtime: " << stats.elapsedRunTime(); - std::map rudy_congestion_map = CONGESTION_API_INST->patchRUDYCongestion(patch_xy_map); - LOG_INFO << "finish rudy_congestion_map, runtime: " << stats.elapsedRunTime(); - std::map egr_congestion_map = CONGESTION_API_INST->patchEGRCongestion(patch_xy_map); - LOG_INFO << "finish egr_congestion_map, runtime: " << stats.elapsedRunTime(); - std::map> layer_congestion_map = CONGESTION_API_INST->patchLayerEGRCongestion(patch_xy_map); - LOG_INFO << "finish layer_egr_congestion_map, runtime: " << stats.elapsedRunTime(); #pragma omp parallel for schedule(dynamic) for (int i = 0; i < (int) patchs.size(); ++i) { @@ -254,7 +267,6 @@ void VecFeatureStatis::feature_patch() auto& patch_id = it->first; auto& patch = it->second; - // 根据 patch_id 获取 patch feature patch.pin_density = pin_density_map[patch_id]; patch.cell_density = cell_density_map[patch_id]; patch.net_density = net_density_map[patch_id]; @@ -262,7 +274,6 @@ void VecFeatureStatis::feature_patch() patch.RUDY_congestion = rudy_congestion_map[patch_id]; patch.EGR_congestion = egr_congestion_map[patch_id]; - // // timing, power, ir drop map auto cell_timing_map_find = cell_timing_map.find(patch_id); if (cell_timing_map_find != cell_timing_map.end()) { patch.timing_map = cell_timing_map_find->second; @@ -270,17 +281,17 @@ void VecFeatureStatis::feature_patch() auto cell_power_map_find = cell_power_map.find(patch_id); if (cell_power_map_find != cell_power_map.end()) { - patch.power_map = cell_power_map[patch_id]; + patch.power_map = cell_power_map_find->second; } auto cell_ir_map_find = cell_ir_map.find(patch_id); if (cell_ir_map_find != cell_ir_map.end()) { - patch.ir_drop_map = cell_ir_map[patch_id]; + patch.ir_drop_map = cell_ir_map_find->second; } for (auto& [layer_id, patch_layer] : patch.get_layer_map()) { patch_layer.wire_width = layout_layers.findLayoutLayer(layer_id)->get_wire_width(); - // 获取每一层对应patch的拥塞值 + // obtain congestion value for each layer in the patch std::string layer_name = layout_layers.findLayoutLayer(layer_id)->get_layer_name(); patch_layer.congestion = layer_congestion_map[patch_id][layer_name]; diff --git a/src/vectorization/src/layout/data_manager/vec_layout_init.cpp b/src/vectorization/src/layout/data_manager/vec_layout_init.cpp index c3e3f7b180ff6ed1557ea24189eb5b5a80101071..7139cc5f9fdc82b4ae75c0e5d98f4630fde3cacc 100644 --- a/src/vectorization/src/layout/data_manager/vec_layout_init.cpp +++ b/src/vectorization/src/layout/data_manager/vec_layout_init.cpp @@ -406,8 +406,8 @@ void VecLayoutInit::initInstances() vec_inst.cell_id = cell_id; vec_inst.name = idb_inst->get_name(); - vec_inst.x = idb_inst->get_coordinate()->get_x(); - vec_inst.y = idb_inst->get_coordinate()->get_y(); + vec_inst.cx = idb_inst->get_bounding_box()->get_middle_point_x(); + vec_inst.cy = idb_inst->get_bounding_box()->get_middle_point_y(); vec_inst.width = idb_inst->get_cell_master()->get_width(); vec_inst.height = idb_inst->get_cell_master()->get_height(); diff --git a/src/vectorization/src/patch/database/vec_patch.h b/src/vectorization/src/patch/database/vec_patch.h index 28f95be50cef96d9fade248743f2c9577748e026..e7898313b6c5210bd8a4ac8773f764b7dd6b0d01 100644 --- a/src/vectorization/src/patch/database/vec_patch.h +++ b/src/vectorization/src/patch/database/vec_patch.h @@ -90,7 +90,6 @@ class VecPatch int colIdMin = -1; int colIdMax = -1; - int area = 0; double cell_density = -1; int pin_density = -1; double net_density = -1;