48 Commits

Author SHA1 Message Date
  Emin 2d40d738ab
!78 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao 1dd64638b0 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao e0a9ef7e61 fix:build in centos 2 months ago
  zxy 600a00a43f fix check arc bugs 2 months ago
  zxy e4fd0c78d0 fix merge net bugs 2 months ago
  simintao ed10bd4639 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao 7080a6da4f fix:slew random when not exist 2 months ago
  Yell-walkalone 9e153f3b84 merge 2 months ago
  Yell-walkalone a492242453 fix bug for process string in def parser 2 months ago
  simintao df9c3e59d2 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 2 months ago
  simintao 1edd03d9a1 fix:copy power file when vector 2 months ago
  YihangQiu baaa99e278 merge 2 months ago
  YihangQiu 98edb63e1a fix: eval density error without driver pin 2 months ago
  Yell-walkalone 1ac903c243 fix bug for create via 2 months ago
  simintao 09958ed8f9 feature:add power rpt when vector 2 months ago
  simintao f02743de89 fix:mask ir drop temp 2 months ago
  sgpsdd 43cdf9f509 fix: add driver null check in init_sta 2 months ago
  sgpsdd 7b9586bbeb fix: add null check for sta_net in init_sta 3 months ago
  YihangQiu 7c30cc63ab merge 3 months ago
  YihangQiu abb7b44161 fix: from max_route_wire_density to sum_route_wire_density 3 months ago
  simintao 3cd9e384d0 fix:use hpwl for place eval 3 months ago
  simintao e714cd6fa9 fix:report summary when wire path 3 months ago
  simintao f31a5c328c fix:float io pins 3 months ago
  simintao 3239f47ea6 fix:design name is local val 3 months ago
  simintao 94b9f926e9 fix:crash of no IR Drop map 3 months ago
  simintao ff3f66a96f feature:support cell leakage power 3 months ago
  simintao ce51ef862d feature:support read spef for vectornization 3 months ago
  simintao 3c153b8359 feature:support spef path 3 months ago
  simintao f78c1dc640 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 3 months ago
  simintao 88eeeac11f feature:support benchmark for test score 3 months ago
  YihangQiu f6a5b4ad8f merge 3 months ago
  YihangQiu 76af26eb78 fix: net_density computation based on routed wire 3 months ago
  simintao 03573a8298 Merge branch 'master' of gitee.com:ieda-ipd/iEDA 3 months ago
  simintao 8109f63b1c feature:support get Top n path 3 months ago
  YihangQiu d7956d6702 feat: select timing evaluation mode between SPEF and Layout 3 months ago
  YihangQiu 27da608fe6 merge 3 months ago
  YihangQiu 8202f52568 feat: vectorization at placement stage 3 months ago
  Yell-walkalone 7cb0c1a5ed add instance flip flop flag from sta timing engine 3 months ago
  simintao 340a0a2f9b feature:support spef vectornization 3 months ago
  simintao 10ca55c2f4 fix:add judge seq cell 3 months ago
  simintao 48c622712b feature:add power feature 3 months ago
  simintao 029a024b98 fix:cap is 0 3 months ago
  simintao f0e1a429ed Merge branch 'master' of gitee.com:ieda-ipd/iEDA 3 months ago
  simintao 609e72bede refactor:feature format and add node cap 3 months ago
  Yell-walkalone d9cc2de404 fix bug for pdn connect two layers 3 months ago
  simintao 29d30cca61 feature:support dump node and edge feature 3 months ago
  simintao 07645fa5a4 feature:add edge feature 3 months ago
  simintao e17ff481b1 feature:add node feature 3 months ago
66 changed files with 1075 additions and 387 deletions
Split View
  1. +8
    -4
      src/database/data/design/db_design/IdbInstance.cpp
  2. +2
    -0
      src/database/data/design/db_design/IdbInstance.h
  3. +36
    -6
      src/database/data/design/db_design/IdbVias.cpp
  4. +4
    -3
      src/database/data/design/db_design/IdbVias.h
  5. +13
    -8
      src/database/manager/builder/def_builder/def_read.cpp
  6. +7
    -6
      src/database/manager/builder/def_builder/def_write.cpp
  7. +25
    -2
      src/database/manager/builder/verilog_builder/verilog_read.cpp
  8. +2
    -0
      src/database/manager/builder/verilog_builder/verilog_read.h
  9. +6
    -0
      src/evaluation/src/module/congestion/congestion_eval.cpp
  10. +18
    -2
      src/evaluation/src/module/density/density_eval.cpp
  11. +8
    -0
      src/evaluation/src/util/init_idb.cpp
  12. +402
    -72
      src/evaluation/src/util/init_sta.cc
  13. +70
    -2
      src/evaluation/src/util/init_sta.hh
  14. +1
    -1
      src/interface/python/py_vec/py_register_vec.h
  15. +2
    -2
      src/interface/python/py_vec/py_vec.cpp
  16. +1
    -1
      src/interface/python/py_vec/py_vec.h
  17. +2
    -2
      src/operation/iCTS/source/data_manager/database/CtsNet.cc
  18. +28
    -1
      src/operation/iPA/api/Power.hh
  19. +13
    -0
      src/operation/iPA/source/module/core/PwrGraph.hh
  20. +3
    -0
      src/operation/iPA/source/module/ops/build_graph/PwrBuildGraph.cc
  21. +7
    -7
      src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc
  22. +11
    -14
      src/operation/iPDN/source/module/pdn_plan/pdn_plan.cpp
  23. +1
    -0
      src/operation/iPDN/source/module/pdn_via/CMakeLists.txt
  24. +11
    -7
      src/operation/iPDN/source/module/pdn_via/pdn_via.cpp
  25. +6
    -2
      src/operation/iPDN/source/module/pdn_via/pdn_via.h
  26. +2
    -2
      src/operation/iPL/source/module/detail_placer/database/DPRow.cc
  27. +2
    -1
      src/operation/iPL/source/module/topology_manager/TopologyManager.cc
  28. +2
    -1
      src/operation/iPL/source/utility/Geometry.hh
  29. +16
    -8
      src/operation/iSTA/api/TimingEngine.cc
  30. +8
    -2
      src/operation/iSTA/api/TimingEngine.hh
  31. +1
    -0
      src/operation/iSTA/source/module/AI-inference/AISta.hh
  32. +1
    -0
      src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc
  33. +36
    -11
      src/operation/iSTA/source/module/sta/Sta.cc
  34. +7
    -5
      src/operation/iSTA/source/module/sta/Sta.hh
  35. +1
    -0
      src/operation/iSTA/source/module/sta/StaPathData.hh
  36. +2
    -3
      src/operation/iSTA/source/module/sta/StaReport.cc
  37. +4
    -4
      src/operation/iSTA/source/module/sta/StaVertex.cc
  38. +1
    -1
      src/operation/iSTA/test/AIModelTest.cc
  39. +1
    -0
      src/platform/data_manager/config/dm_config.cpp
  40. +12
    -0
      src/platform/tool_manager/tool_api/ista_io/ista_io.cpp
  41. +2
    -0
      src/platform/tool_manager/tool_api/ista_io/ista_io.h
  42. +1
    -1
      src/third_party/LSAssigner4iEDA
  43. +2
    -2
      src/vectorization/api/vec_api.cpp
  44. +1
    -1
      src/vectorization/api/vec_api.h
  45. +1
    -0
      src/vectorization/database/vec_net.cpp
  46. +11
    -9
      src/vectorization/src/data_manager/vec_dm.cpp
  47. +5
    -5
      src/vectorization/src/data_manager/vec_dm.h
  48. +1
    -0
      src/vectorization/src/data_manager/vec_file.cpp
  49. +2
    -2
      src/vectorization/src/feature/vec_feature.cpp
  50. +5
    -1
      src/vectorization/src/feature/vec_feature.h
  51. +122
    -88
      src/vectorization/src/feature/vec_feature_statis.cpp
  52. +3
    -1
      src/vectorization/src/feature/vec_feature_statis.h
  53. +21
    -3
      src/vectorization/src/feature/vec_feature_timing.cpp
  54. +4
    -1
      src/vectorization/src/feature/vec_feature_timing.h
  55. +7
    -1
      src/vectorization/src/graph/data_manager/vec_graph_dm.cpp
  56. +1
    -1
      src/vectorization/src/graph/data_manager/vec_graph_dm.h
  57. +4
    -4
      src/vectorization/src/layout/data_manager/vec_layout_dm.cpp
  58. +2
    -2
      src/vectorization/src/layout/data_manager/vec_layout_dm.h
  59. +48
    -43
      src/vectorization/src/layout/data_manager/vec_layout_init.cpp
  60. +2
    -2
      src/vectorization/src/layout/data_manager/vec_layout_init.h
  61. +8
    -8
      src/vectorization/src/patch/data_manager/vec_patch_dm.cpp
  62. +4
    -4
      src/vectorization/src/patch/data_manager/vec_patch_dm.h
  63. +6
    -2
      src/vectorization/src/patch/data_manager/vec_patch_init.cpp
  64. +1
    -1
      src/vectorization/src/patch/data_manager/vec_patch_init.h
  65. +22
    -19
      src/vectorization/src/vectorization.cpp
  66. +6
    -6
      src/vectorization/src/vectorization.h

+ 8
- 4
src/database/data/design/db_design/IdbInstance.cpp View File

@@ -97,10 +97,14 @@ void IdbInstance::set_type(string type)

bool IdbInstance::is_flip_flop()
{
for (IdbPin* pin : _pin_list->get_pin_list()) {
IdbTerm* term = pin->get_term();
if (term->get_type() == IdbConnectType::kClock) {
return true;
if (_flip_flop_flag != -1) {
return _flip_flop_flag == 1 ? true : false;
} else {
for (IdbPin* pin : _pin_list->get_pin_list()) {
IdbTerm* term = pin->get_term();
if (term->get_type() == IdbConnectType::kClock) {
return true;
}
}
}



+ 2
- 0
src/database/data/design/db_design/IdbInstance.h View File

@@ -128,6 +128,7 @@ class IdbInstance : public IdbObject

void set_orient(IdbOrient orient, bool b_update = true);
void set_orient_by_enum(int32_t lef_orient);
void set_as_flip_flop_flag() { _flip_flop_flag = 1; }

IdbHalo* set_halo(IdbHalo* halo = nullptr);
IdbRouteHalo* set_route_halo(IdbRouteHalo* route_halo = nullptr);
@@ -167,6 +168,7 @@ class IdbInstance : public IdbObject
// region
// Group
IdbRegion* _region;
int _flip_flop_flag = -1; /// -1:not set, 0:not flip flop, 1:flip flop
};

class IdbInstanceList


+ 36
- 6
src/database/data/design/db_design/IdbVias.cpp View File

@@ -304,7 +304,8 @@ IdbVia* IdbVias::add_via(string name)
/// width_design : width that set by the designer
/// height_design : height that set by the designer

IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design)
IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design,
IdbLayerDirection direction)
{
IdbViaRuleGenerate* via_rule = layer_cut->get_via_rule();
if (via_rule == nullptr)
@@ -363,7 +364,7 @@ IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t widt
int32_t top_enclosure_x = 0;
int32_t top_enclosure_y = 0;

if (layer_bottom->is_horizontal()) {
auto process_bottom_horizontal = [&]() {
int32_t rule_bottom_enclosure_x = via_rule->get_enclosure_bottom()->get_overhang_1();
int32_t rule_bottom_enclosure_y = via_rule->get_enclosure_bottom()->get_overhang_2();

@@ -385,8 +386,8 @@ IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t widt
/// calculate enclosure x
bottom_enclosure_x = (bottom_width - (cols * cutsize_x + (cols - kMinRowColNum) * cut_spacing_x)) / 2;
bottom_enclosure_x = std::max(bottom_enclosure_x, rule_bottom_enclosure_x);
} else {
};
auto process_bottom_vertical = [&]() {
int32_t rule_bottom_enclosure_x = via_rule->get_enclosure_bottom()->get_overhang_2();
int32_t rule_bottom_enclosure_y = via_rule->get_enclosure_bottom()->get_overhang_1();

@@ -407,9 +408,23 @@ IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t widt
/// calculate enclosure y
bottom_enclosure_y = (bottom_height - (rows * cutsize_y + (rows - kMinRowColNum) * cut_spacing_y)) / 2;
bottom_enclosure_y = std::max(bottom_enclosure_y, rule_bottom_enclosure_y);
};

if (direction == IdbLayerDirection::kNone) {
if (layer_bottom->is_horizontal()) {
process_bottom_horizontal();
} else {
process_bottom_vertical();
}
} else {
if (direction == IdbLayerDirection::kHorizontal) {
process_bottom_horizontal();
} else {
process_bottom_vertical();
}
}

if (layer_top->is_horizontal()) {
auto process_top_horizontal = [&]() {
int32_t rule_top_enclosure_x = via_rule->get_enclosure_top()->get_overhang_1();
int32_t rule_top_enclosure_y = via_rule->get_enclosure_top()->get_overhang_2();

@@ -430,7 +445,8 @@ IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t widt
/// calculate enclosure x
top_enclosure_x = (top_width - (cols * cutsize_x + (cols - kMinRowColNum) * cut_spacing_x)) / 2;
top_enclosure_x = std::max(top_enclosure_x, rule_top_enclosure_x);
} else {
};
auto process_top_vertical = [&]() {
int32_t rule_top_enclosure_x = via_rule->get_enclosure_top()->get_overhang_2();
int32_t rule_top_enclosure_y = via_rule->get_enclosure_top()->get_overhang_1();

@@ -451,6 +467,20 @@ IdbVia* IdbVias::createVia(string via_name, IdbLayerCut* layer_cut, int32_t widt
/// calculate enclosure y
top_enclosure_y = (top_height - (rows * cutsize_y + (rows - kMinRowColNum) * cut_spacing_y)) / 2;
top_enclosure_y = std::max(top_enclosure_y, rule_top_enclosure_y);
};

if (direction == IdbLayerDirection::kNone) {
if (layer_bottom->is_horizontal()) {
process_top_horizontal();
} else {
process_top_vertical();
}
} else {
if (direction == IdbLayerDirection::kHorizontal) {
process_top_horizontal();
} else {
process_top_vertical();
}
}

master_generate->set_enclosure_bottom(bottom_enclosure_x, bottom_enclosure_y);


+ 4
- 3
src/database/data/design/db_design/IdbVias.h View File

@@ -38,8 +38,8 @@
// #include "IdbViaMaster.h"
#include "../../../basic/geometry/IdbGeometry.h"
#include "../../../basic/geometry/IdbLayerShape.h"
#include "../IdbEnum.h"
#include "../IdbObject.h"
// #include "../db_layout/IdbLayer.h"

namespace idb {

@@ -74,7 +74,7 @@ class IdbVia : public IdbObject
void reset_instance(IdbViaMaster* instance);
void set_coordinate(IdbCoordinate<int32_t>* point);
void set_coordinate(int32_t x, int32_t y) { _coordinate->set_xy(x, y); }
// operator
IdbVia* clone();
void clear();
@@ -111,7 +111,8 @@ class IdbVias
void init_via_list(int32_t size) { _via_list.reserve(size); }

// operator
IdbVia* createVia(string via_name, IdbLayerCut* layer_cut, int32_t width_design = 0, int32_t height_design = 0);
IdbVia* createVia(string via_name, IdbLayerCut* layer_cut, int32_t width_design = 0, int32_t height_design = 0,
IdbLayerDirection direction = IdbLayerDirection::kNone);
// IdbVia* createViaDefault(string via_name, IdbLayerCut* layer_cut);
std::pair<int32_t, int32_t> calculateRowsCols(IdbLayerCut* layer_cut, int32_t width = 0, int32_t height = 0);
string createViaPatternString(int row_num, int col_num, IdbLayerCutArraySpacing* _array_spacing);


+ 13
- 8
src/database/manager/builder/def_builder/def_read.cpp View File

@@ -904,10 +904,6 @@ int32_t DefRead::parse_component(defiComponent* def_component)

std::string inst_name = def_component->id();
std::string new_inst_name = ieda::Str::trimEscape(inst_name);
if ("u_NV_NVDLA_cbuf/u_cbuf_ram_bank6_ram0/rmod/u_mema" == new_inst_name) {
int a = 0;
a += 1;
}

IdbInstance* instance = instance_list->add_instance(new_inst_name);
if (instance == nullptr) {
@@ -1092,7 +1088,9 @@ int32_t DefRead::parse_net(defiNet* def_net)

IdbPin* pin = nullptr;
if (io_name.compare("PIN") == 0) {
pin = io_pin_list->find_pin(def_net->pin(i));
std::string pin_name = def_net->pin(i);
pin_name = ieda::Str::trimEscape(pin_name);
pin = io_pin_list->find_pin(pin_name);
if (pin == nullptr) {
std::cout << "Can not find Pin in Pin list ... pin name = " << def_net->pin(i) << std::endl;
} else {
@@ -1103,7 +1101,9 @@ int32_t DefRead::parse_net(defiNet* def_net)
IdbInstance* instance = instance_list->find_instance(io_name);
if (instance != nullptr) {
net->get_instance_list()->add_instance(instance);
pin = instance->get_pin_by_term(def_net->pin(i));
std::string pin_name = def_net->pin(i);
pin_name = ieda::Str::trimEscape(pin_name);
pin = instance->get_pin_by_term(pin_name);
if (pin == nullptr) {
std::cout << "Can not find Pin in Pin list ... pin name = " << def_net->pin(i) << std::endl;
} else {
@@ -1332,11 +1332,14 @@ int32_t DefRead::parse_pdn(defiNet* def_net)

for (int i = 0; i < def_net->numConnections(); i++) {
string io_name = def_net->instance(i);
io_name = ieda::Str::trimEscape(io_name);
IdbPin* pin = nullptr;
if (io_name.compare("*") == 0) {
net->add_pin_string(def_net->pin(i));
} else if (io_name.compare("PIN") == 0) {
pin = io_pin_list->find_pin(def_net->pin(i));
std::string pin_name = def_net->pin(i);
pin_name = ieda::Str::trimEscape(pin_name);
pin = io_pin_list->find_pin(pin_name);
if (pin == nullptr) {
std::cout << "Can not find Pin in Pin list ... pin name = " << def_net->pin(i) << std::endl;
} else {
@@ -1347,7 +1350,9 @@ int32_t DefRead::parse_pdn(defiNet* def_net)
IdbInstance* instance = instance_list->find_instance(io_name);
if (instance != nullptr) {
net->add_instance(instance);
pin = instance->get_pin_by_term(def_net->pin(i));
std::string pin_name = def_net->pin(i);
pin_name = ieda::Str::trimEscape(pin_name);
pin = instance->get_pin_by_term(pin_name);
if (pin == nullptr) {
std::cout << "Can not find Pin in Pin list ... pin name = " << def_net->pin(i) << std::endl;
} else {


+ 7
- 6
src/database/manager/builder/def_builder/def_write.cpp View File

@@ -35,7 +35,8 @@

#include <algorithm>
#include <cstdint>

#include <stdarg.h>
#include <zlib.h>
#include "../../../data/design/IdbDesign.h"
#include "Str.hh"
#include "boost_definition.h"
@@ -475,7 +476,7 @@ int32_t DefWrite::write_component()

for (IdbInstance* instance : instance_list->get_instance_list()) {
std::string inst_name = instance->get_name();
std::string new_inst_name = ieda::Str::addBackslash(inst_name);
// std::string new_inst_name = ieda::Str::addBackslash(inst_name);

string type = instance->get_type() != IdbInstanceType::kNone
? "+ SOURCE " + IdbEnum::GetInstance()->get_instance_property()->get_type_str(instance->get_type())
@@ -484,10 +485,10 @@ int32_t DefWrite::write_component()
string orient = IdbEnum::GetInstance()->get_site_property()->get_orient_name(instance->get_orient());

if (instance->has_placed()) {
writestr(" - %s %s %s + %s ( %d %d ) %s \n", new_inst_name.c_str(), instance->get_cell_master()->get_name().c_str(), type.c_str(),
writestr(" - %s %s %s + %s ( %d %d ) %s \n", inst_name.c_str(), instance->get_cell_master()->get_name().c_str(), type.c_str(),
status.c_str(), instance->get_coordinate()->get_x(), instance->get_coordinate()->get_y(), orient.c_str());
} else {
writestr(" - %s %s %s \n", new_inst_name.c_str(), instance->get_cell_master()->get_name().c_str(), type.c_str());
writestr(" - %s %s %s \n", inst_name.c_str(), instance->get_cell_master()->get_name().c_str(), type.c_str());
}

/// halo
@@ -829,8 +830,8 @@ int32_t DefWrite::write_net()

for (IdbNet* net : net_list->get_net_list()) {
std::string net_name = net->get_net_name();
std::string net_name_new = ieda::Str::addBackslash(net_name);
writestr("- %s", net_name_new.c_str());
// std::string net_name_new = ieda::Str::addBackslash(net_name);
writestr("- %s", net_name.c_str());

auto* io_pins = net->get_io_pins();
for (auto* io_pin : io_pins->get_pin_list()) {


+ 25
- 2
src/database/manager/builder/verilog_builder/verilog_read.cpp View File

@@ -119,6 +119,8 @@ bool RustVerilogRead::createDb(std::string file, std::string top_module_name)
build_components();
build_assign();

post_process_float_io_pins();

return true;
}

@@ -439,8 +441,7 @@ int32_t RustVerilogRead::build_assign()
auto* the_left_io_pin = idb_io_pin_list->find_pin(left_net_name.c_str());
auto* the_right_io_pin = idb_io_pin_list->find_pin(right_net_name.c_str());

if ((the_left_idb_net && the_right_idb_net && !the_left_io_pin && !the_right_io_pin)
|| (the_left_idb_net && the_right_idb_net && the_left_io_pin && the_right_io_pin)) {
if (the_left_idb_net && the_right_idb_net) {
// assign net = net, need merge two net to one net.

// std::cout << "merge " << left_net_name << " = " << right_net_name << "\n";
@@ -1077,4 +1078,26 @@ int32_t RustVerilogRead::build_components()
return kVerilogSuccess;
}

int32_t RustVerilogRead::post_process_float_io_pins() {
IdbDesign* idb_design = _def_service->get_design();
IdbPins* idb_io_pin_list = idb_design->get_io_pin_list();

for (auto* io_pin : idb_io_pin_list->get_pin_list()) {
if (io_pin->is_io_pin() && (io_pin->get_net() == nullptr)) {
// create a net for float io pin.
IdbNet* idb_net = new IdbNet();
idb_net->set_net_name(io_pin->get_pin_name());
idb_net->set_connect_type(IdbConnectType::kSignal);
idb_design->get_net_list()->add_net(idb_net);

idb_net->add_io_pin(io_pin);
io_pin->set_net(idb_net);
io_pin->set_net_name(idb_net->get_net_name());
}
}

return kVerilogSuccess;

}

} // namespace idb

+ 2
- 0
src/database/manager/builder/verilog_builder/verilog_read.h View File

@@ -87,6 +87,8 @@ class RustVerilogRead
int32_t build_nets();
int32_t build_pins();

int32_t post_process_float_io_pins();

private:
IdbDesign* _idb_design = nullptr;
IdbDefService* _def_service = nullptr;


+ 6
- 0
src/evaluation/src/module/congestion/congestion_eval.cpp View File

@@ -1888,6 +1888,12 @@ std::vector<NetMetadata> CongestionEval::precomputeNetData(const CongestionNets&
md.ux = std::max(md.ux, pin.lx);
md.uy = std::max(md.uy, pin.ly);
}
// 安全检查:跳过无效的net坐标
if (md.lx == INT32_MAX || md.ly == INT32_MAX || md.ux == INT32_MIN || md.uy == INT32_MIN) {
continue; // 跳过没有有效pin的net
}
// 预计算RUDY因子
md.hor_rudy = (md.uy == md.ly) ? 1.0 : 1.0 / (md.uy - md.ly);
md.ver_rudy = (md.ux == md.lx) ? 1.0 : 1.0 / (md.ux - md.lx);


+ 18
- 2
src/evaluation/src/module/density/density_eval.cpp View File

@@ -659,6 +659,13 @@ std::map<int, double> DensityEval::patchNetDensity(DensityNets nets, std::map<in
{
std::map<int, double> patch_net_density;
if (nets.empty()) {
for (const auto& [patch_id, coord] : patch_coords) {
patch_net_density[patch_id] = 0.0;
}
return patch_net_density;
}
// 预处理:将线网按x坐标排序,提升查找性能
std::vector<DensityNet> sorted_nets = nets;
std::sort(sorted_nets.begin(), sorted_nets.end(), [](const DensityNet& a, const DensityNet& b) {
@@ -679,6 +686,11 @@ std::map<int, double> DensityEval::patchNetDensity(DensityNets nets, std::map<in
const int patch_width = patch_ux - patch_lx;
const int patch_height = patch_uy - patch_ly;
const int patch_area = patch_width * patch_height;
if (patch_area <= 0) {
patch_net_density[patch_id] = 0.0;
continue;
}

// 使用二分查找确定x坐标范围,减少需要检查的线网数量
auto lower_it = std::lower_bound(sorted_nets.begin(), sorted_nets.end(), patch_lx,
@@ -694,6 +706,10 @@ std::map<int, double> DensityEval::patchNetDensity(DensityNets nets, std::map<in
for (auto it = lower_it; it != upper_it; ++it) {
const auto& net = *it;
if (net.lx > net.ux || net.ly > net.uy) {
continue;
}
// 检查y坐标是否重叠
if (net.uy > patch_ly && net.ly < patch_uy) {
// 计算重叠面积
@@ -716,8 +732,8 @@ std::map<int, double> DensityEval::patchNetDensity(DensityNets nets, std::map<in
patch_net_density[patch_id] = density;
}
return patch_net_density;
return patch_net_density;
}

std::map<int, int> DensityEval::patchMacroMargin(DensityCells cells, DensityRegion core, std::map<int, std::pair<std::pair<int, int>, std::pair<int, int>>> patch_coords)


+ 8
- 0
src/evaluation/src/util/init_idb.cpp View File

@@ -230,6 +230,14 @@ void InitIDB::initDensityDBNets()
max_ux = std::max(max_ux, idb_load_pin->get_average_coordinate()->get_x());
max_uy = std::max(max_uy, idb_load_pin->get_average_coordinate()->get_y());
}
// 安全检查:如果net没有任何pin或坐标无效,跳过此net
if (min_lx == INT32_MAX || min_ly == INT32_MAX ||
max_ux == INT32_MIN || max_uy == INT32_MIN ||
min_lx > max_ux || min_ly > max_uy) {
continue;
}
net.lx = min_lx;
net.ly = min_ly;
net.ux = max_ux;


+ 402
- 72
src/evaluation/src/util/init_sta.cc View File

@@ -41,7 +41,7 @@
namespace ieval {

using json = nlohmann::ordered_json;
#define STA_INST (ista::TimingEngine::getOrCreateTimingEngine())
#define RT_INST (irt::RTInterface::getInst())
#define PW_INST (ipower::PowerEngine::getOrCreatePowerEngine())
@@ -92,6 +92,91 @@ void InitSTA::runVecSTA(ivec::VecLayout* vec_layout, std::string work_dir)
updateResult("Vectorization");
}

void InitSTA::runPlaceVecSTA(const std::string& routing_type, const bool& rt_done, std::string work_dir)
{
initStaEngine();

if (routing_type == "EGR" || routing_type == "DR") {
if (!rt_done) {
callRT(routing_type);
}
} else {
buildRCTree(routing_type);
}

std::string path_dir = work_dir;
STA_INST->set_design_work_space(path_dir.c_str());
STA_INST->reportWirePaths(10000);

updateResult(routing_type);
}

void InitSTA::runSpefVecSTA(std::string work_dir) {
initStaEngine();

buildSpefRCTree(work_dir);

updateResult("Vectorization");
}

///@brief save ppa index into csv.
void InitSTA::saveTimingPowerBenchmark() {
// get freq、TNS、Top100 path delay
std::map<std::string, std::pair<double, double>> clock_freq_map; // clock_name, <freq, TNS>
auto all_clocks = STA_INST->getClockList();
for (auto* clock : all_clocks) {
double clock_period = clock->getPeriodNs();
double slack = STA_INST->getWNS(clock->get_clock_name(), ista::AnalysisMode::kMax);

// freq is period inverse.
double freq_MHz = 1000 / (clock_period - slack);

double TNS = STA_INST->getTNS(clock->get_clock_name(), ista::AnalysisMode::kMax);
clock_freq_map[clock->get_clock_name()] = std::make_pair(freq_MHz, TNS);
}

std::vector<std::pair<std::string, double>> end_vertex_to_path_delay;
unsigned top_n_path = 100;
// get top100 path delay
auto top_n_seq_path_vec = STA_INST->getTopNWorstSeqPaths(ista::AnalysisMode::kMax, top_n_path);
LOG_INFO << "seq path num: " << top_n_seq_path_vec.size();
for (auto* seq_path : top_n_seq_path_vec) {
double path_delay = seq_path->getArriveTimeNs();
auto* end_vertex = seq_path->getEndVertex();

end_vertex_to_path_delay.emplace_back(end_vertex->getName(), path_delay);
}

// leakage power、internal power、switch power
double leakage_power = PW_INST->get_power()->getSumLeakagePower();
double internal_power = PW_INST->get_power()->getSumInternalPower();
double switch_power = PW_INST->get_power()->getSumSwitchPower();
// net density need in single file.
// save to json.

std::string benchmark_file_path = STA_INST->get_design_work_space();
benchmark_file_path += "/timing_power_benchmark.json";

std::ofstream json_file(benchmark_file_path, std::ios::out | std::ios::trunc);
if (!json_file.is_open()) {
LOG_ERROR << "Fail to open timing_power_benchmark.json";
return;
}

json json_data;
json_data["clock_freq_map"] = clock_freq_map;
json_data["end_vertex_to_path_delay"] = end_vertex_to_path_delay;
json_data["leakage_power"] = leakage_power;
json_data["internal_power"] = internal_power;
json_data["switch_power"] = switch_power;

json_file << json_data.dump(4) << std::endl;

json_file.close();
LOG_INFO << "save benchmark json path: " << benchmark_file_path;
}

void InitSTA::evalTiming(const std::string& routing_type, const bool& rt_done)
{
initStaEngine();
@@ -308,6 +393,9 @@ void InitSTA::buildRCTree(const std::string& routing_type)
for (size_t net_id = 0; net_id < idb_nets.size(); ++net_id) {
auto* idb_net = idb_nets[net_id];
sta_net = sta_netlist->findNet(idb_net->get_net_name().c_str());
if (sta_net == nullptr || sta_net->getDriver() == nullptr) {
continue;
}
STA_INST->resetRcTree(sta_net);
// WLM
if (routing_type == "WLM") {
@@ -565,6 +653,19 @@ void InitSTA::buildVecRCTree(ivec::VecLayout* vec_layout, std::string work_dir)
STA_INST->reportWirePaths(10000);
}

void InitSTA::buildSpefRCTree(std::string work_dir) {
std::string spef_path = dmInst->get_config().get_spef_path();
LOG_INFO << "spef path: " << spef_path;
STA_INST->readSpef(spef_path.c_str());
STA_INST->updateTiming();
STA_INST->get_ista()->reportUsedLibs();

std::string path_dir = work_dir;
STA_INST->set_design_work_space(path_dir.c_str());
STA_INST->reportWirePaths(10000);
}


void InitSTA::initPowerEngine()
{
if (!PW_INST->isBuildGraph()) {
@@ -572,6 +673,7 @@ void InitSTA::initPowerEngine()
PW_INST->get_power()->initToggleSPData();
}
PW_INST->get_power()->updatePower();
PW_INST->get_power()->reportPower(false);
}

void InitSTA::updateResult(const std::string& routing_type)
@@ -612,6 +714,9 @@ void InitSTA::updateResult(const std::string& routing_type)
}
_power[routing_type]["static_power"] = static_power;
_power[routing_type]["dynamic_power"] = dynamic_power;
// save benchmark file for test.
saveTimingPowerBenchmark();
}

double InitSTA::getEarlySlack(const std::string& pin_name) const
@@ -951,37 +1056,160 @@ TimingWireGraph InitSTA::getTimingWireGraph()
LOG_INFO << "get wire timing graph start";
ieda::Stats stats;

auto* ista = STA_INST->get_ista();
LOG_ERROR_IF(!ista->isBuildGraph()) << "timing graph is not build";
// build equivalent library cells map
auto& all_libs = ista->getAllLib();
std::vector<LibLibrary*> equiv_libs;
for (auto& lib : all_libs) {
equiv_libs.push_back(lib.get());
}

ista->makeClassifiedCells(equiv_libs);

auto* ipower = PW_INST->get_power();

// build switch power map.
auto& switch_powers = ipower->get_switch_powers();
std::map<ipower::PwrVertex*, double> vertex_to_switch_power;
for (auto& switch_power : switch_powers) {
auto* the_net = switch_power->get_design_obj();
auto* the_driver = dynamic_cast<ista::Net*>(the_net)->getDriver();
auto* the_sta_vertex = ista->findVertex(the_driver);
auto* the_pwr_vertex = ipower->get_power_graph().staToPwrVertex(the_sta_vertex);
vertex_to_switch_power[the_pwr_vertex] = switch_power->get_switch_power();
}

TimingWireGraph timing_wire_graph;

/// create node in wire graph
auto create_node = [&timing_wire_graph](std::string& node_name, bool is_pin, bool is_port) -> unsigned {
auto index = timing_wire_graph.findNode(node_name);
if (!index) {
TimingWireNode the_node;
the_node._name = node_name;
the_node._is_pin = is_pin;
the_node._is_port = is_port;
TimingWireNode the_node;
the_node._name = node_name;
the_node._is_pin = is_pin;
the_node._is_port = is_port;

index = timing_wire_graph.addNode(the_node);
}
auto index = timing_wire_graph.addNode(the_node);

return index.value();
return index;
};

/// the node is StaNode
auto create_inst_node = [&create_node](auto* the_node) -> unsigned {
auto create_inst_node = [&timing_wire_graph, &create_node, &vertex_to_switch_power, ista, ipower](auto* the_node) -> unsigned {
std::string node_name = the_node->getName();
auto index = timing_wire_graph.findNode(node_name);
if (index) {
return index.value();
}

auto* design_obj = the_node->get_design_obj();
bool is_pin = design_obj ? design_obj->isPin() : false;
bool is_port = design_obj ? design_obj->isPort() : false;
auto* the_net = design_obj->get_net();

/// dump node feature.
TimingNodeFeature node_feature;
const double inf = 1.1e20;

node_feature._is_input = design_obj->isInput();
if (!node_feature._is_input && the_net) {
node_feature._fanout_num = the_net->getFanouts();
}

node_feature._is_endpoint = the_node->is_end();

auto* own_cell = the_node->getOwnCell();
node_feature._cell_name = own_cell ? own_cell->get_cell_name() : "NA";

auto* equiv_cells = ista->classifyCells(own_cell);
if (equiv_cells) {
for (auto* equiv_cell : *equiv_cells) {
node_feature._sizer_cells.push_back(equiv_cell->get_cell_name());
}
}

if (design_obj->get_coordinate()) {
node_feature._node_coord = design_obj->get_coordinate().value();
}

// dump node slews.
double max_rise_slew = the_node->getSlewNs(AnalysisMode::kMax, TransType::kRise).value_or(inf);
double max_fall_slew = the_node->getSlewNs(AnalysisMode::kMax, TransType::kFall).value_or(inf);
double min_rise_slew = the_node->getSlewNs(AnalysisMode::kMin, TransType::kRise).value_or(inf);
double min_fall_slew = the_node->getSlewNs(AnalysisMode::kMin, TransType::kFall).value_or(inf);

node_feature._node_slews = {max_rise_slew, max_fall_slew, min_rise_slew, min_fall_slew};

// dump node caps.
double max_rise_cap = the_node->getLoad(AnalysisMode::kMax, TransType::kRise);
double max_fall_cap = the_node->getLoad(AnalysisMode::kMax, TransType::kFall);

double min_rise_cap = the_node->getLoad(AnalysisMode::kMin, TransType::kRise);
double min_fall_cap = the_node->getLoad(AnalysisMode::kMin, TransType::kFall);
node_feature._node_caps = {max_rise_cap, max_fall_cap, min_rise_cap, min_fall_cap};

// dump node arrive times.
double max_rise_at = the_node->getArriveTimeNs(AnalysisMode::kMax, TransType::kRise).value_or(inf);
double max_fall_at = the_node->getArriveTimeNs(AnalysisMode::kMax, TransType::kFall).value_or(inf);
double min_rise_at = the_node->getArriveTimeNs(AnalysisMode::kMin, TransType::kRise).value_or(inf);
double min_fall_at = the_node->getArriveTimeNs(AnalysisMode::kMin, TransType::kFall).value_or(inf);
node_feature._node_ats = {max_rise_at, max_fall_at, min_rise_at, min_fall_at};

// dump node required times.
double max_rise_rat = the_node->getReqTimeNs(AnalysisMode::kMax, TransType::kRise).value_or(inf);
double max_fall_rat = the_node->getReqTimeNs(AnalysisMode::kMax, TransType::kFall).value_or(inf);
double min_rise_rat = the_node->getReqTimeNs(AnalysisMode::kMin, TransType::kRise).value_or(inf);
double min_fall_rat = the_node->getReqTimeNs(AnalysisMode::kMin, TransType::kFall).value_or(inf);
node_feature._node_rats = {max_rise_rat, max_fall_rat, min_rise_rat, min_fall_rat};

// dump node net load delays.
auto* rc_net = ista->getRcNet(the_net);
RcTree* rc_tree = nullptr;
if (rc_net) {
rc_tree = rc_net->rct();
if (rc_tree) {
std::string obj_name = design_obj->getFullName();

double max_rise_delay = rc_tree->delay(obj_name.c_str(), AnalysisMode::kMax, TransType::kRise);
double max_fall_delay = rc_tree->delay(obj_name.c_str(), AnalysisMode::kMax, TransType::kFall);
double min_rise_delay = rc_tree->delay(obj_name.c_str(), AnalysisMode::kMin, TransType::kRise);
double min_fall_delay = rc_tree->delay(obj_name.c_str(), AnalysisMode::kMin, TransType::kFall);
node_feature._node_net_delays = {max_rise_delay, max_fall_delay, min_rise_delay, min_fall_delay};
}
}

// dump power feature.
PowerNodeFeature power_feature;
auto* pwr_vertex = ipower->get_power_graph().staToPwrVertex(the_node);
power_feature._toggle = pwr_vertex->getToggleData(std::nullopt);
power_feature._sp = pwr_vertex->getSPData(std::nullopt);

power_feature._node_internal_power = pwr_vertex->getInternalPower();
double switch_power = 0.0;
if (vertex_to_switch_power.contains(pwr_vertex)) {
switch_power = vertex_to_switch_power[pwr_vertex];
}
power_feature._node_net_power = switch_power;

auto wire_node_index = create_node(node_name, is_pin, is_port);
auto& wire_node = timing_wire_graph.getNode(wire_node_index);

wire_node._node_feature = node_feature;
wire_node._power_feature = power_feature;

return wire_node_index;
};

/// the node is RC Node
auto create_net_node = [&create_node](auto& the_node) -> unsigned {
auto create_net_node = [&timing_wire_graph, &create_node](auto& the_node) -> unsigned {
std::string node_name = the_node.get_name();
auto index = timing_wire_graph.findNode(node_name);
if (index) {
return index.value();
}

bool is_pin = the_node.get_obj() ? the_node.get_obj()->isPin() : false;
bool is_port = the_node.get_obj() ? the_node.get_obj()->isPort() : false;

@@ -989,14 +1217,18 @@ TimingWireGraph InitSTA::getTimingWireGraph()
return wire_node_index;
};

auto* ista = STA_INST->get_ista();
LOG_ERROR_IF(!ista->isBuildGraph()) << "timing graph is not build";

auto* the_timing_graph = &(ista->get_graph());
ista::StaArc* the_arc;
ista::StaVertex* the_vertex;

timing_wire_graph._edges.reserve(the_timing_graph->get_arcs().size() * 100);
timing_wire_graph._nodes.reserve(the_timing_graph->get_vertexes().size() * 10);

FOREACH_VERTEX(the_timing_graph, the_vertex)
{
create_inst_node(the_vertex);
}

FOREACH_ARC(the_timing_graph, the_arc)
{
if (the_arc->isNetArc()) {
@@ -1005,41 +1237,88 @@ TimingWireGraph InitSTA::getTimingWireGraph()
auto* the_net = the_net_arc->get_net();

auto* rc_net = ista->getRcNet(the_net);
auto* rc_tree = rc_net->rct();

if (rc_net) {
if (rc_net && rc_tree) {
auto* snk_node = the_arc->get_snk();
auto snk_node_name = snk_node->get_design_obj()->getFullName();

auto wire_topo = rc_net->getWireTopo(snk_node_name.c_str());

auto vertex_slew = the_arc->get_src()->getSlewNs(ista::AnalysisMode::kMax, TransType::kRise);
if (!vertex_slew) {
vertex_slew = the_arc->get_src()->getSlewNs(ista::AnalysisMode::kMax, TransType::kFall);
}
auto max_rise_all_nodes_slew = rc_tree->getAllNodeSlew(vertex_slew.value_or(0.0), AnalysisMode::kMax, TransType::kRise);
vertex_slew = the_arc->get_src()->getSlewNs(ista::AnalysisMode::kMax, TransType::kFall);
auto max_fall_all_nodes_slew = rc_tree->getAllNodeSlew(vertex_slew.value_or(0.0), AnalysisMode::kMax, TransType::kFall);
vertex_slew = the_arc->get_src()->getSlewNs(ista::AnalysisMode::kMin, TransType::kRise);
auto min_rise_all_nodes_slew = rc_tree->getAllNodeSlew(vertex_slew.value_or(0.0), AnalysisMode::kMin, TransType::kRise);
vertex_slew = the_arc->get_src()->getSlewNs(ista::AnalysisMode::kMin, TransType::kFall);
auto min_fall_all_nodes_slew = rc_tree->getAllNodeSlew(vertex_slew.value_or(0.0), AnalysisMode::kMin, TransType::kFall);

auto wire_topo = rc_net->getWireTopo(snk_node_name.c_str());
for (auto* wire_edge : wire_topo | std::ranges::views::reverse) {
ieda::Stats stats2;
auto& from_node = wire_edge->get_from();
auto& to_node = wire_edge->get_to();

// from node
auto wire_from_node_index = create_net_node(from_node);
auto& wire_from_node = timing_wire_graph.getNode(wire_from_node_index);
wire_from_node._node_feature._node_slews
= {max_rise_all_nodes_slew[from_node.get_name()], max_fall_all_nodes_slew[from_node.get_name()],
min_rise_all_nodes_slew[from_node.get_name()], min_fall_all_nodes_slew[from_node.get_name()]};
wire_from_node._node_feature._node_caps = {from_node.cap(AnalysisMode::kMax, TransType::kRise),
from_node.cap(AnalysisMode::kMax, TransType::kFall),
from_node.cap(AnalysisMode::kMin, TransType::kRise),
from_node.cap(AnalysisMode::kMin, TransType::kFall)};
// to node
auto wire_to_node_index = create_net_node(to_node);

timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
auto& wire_to_node = timing_wire_graph.getNode(wire_to_node_index);
wire_to_node._node_feature._node_slews
= {max_rise_all_nodes_slew[to_node.get_name()], max_fall_all_nodes_slew[to_node.get_name()],
min_rise_all_nodes_slew[to_node.get_name()], min_fall_all_nodes_slew[to_node.get_name()]};
wire_to_node._node_feature._node_caps = {to_node.cap(AnalysisMode::kMax, TransType::kRise),
to_node.cap(AnalysisMode::kMax, TransType::kFall),
to_node.cap(AnalysisMode::kMin, TransType::kRise),
to_node.cap(AnalysisMode::kMin, TransType::kFall)};

auto& net_wire_edge = timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
net_wire_edge._edge_feature._edge_resistance = wire_edge->get_res();

net_wire_edge._is_net_edge = true;
}
} else {
auto wire_from_node_index = create_inst_node(the_arc->get_src());
auto wire_to_node_index = create_inst_node(the_arc->get_snk());

auto& inst_wire_edge = timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
inst_wire_edge._is_net_edge = true;
auto& net_edge = timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
net_edge._is_net_edge = true;
}

} else {
} else if (the_arc->isInstArc() && the_arc->isDelayArc()) {
auto wire_from_node_index = create_inst_node(the_arc->get_src());
auto wire_to_node_index = create_inst_node(the_arc->get_snk());

auto& inst_wire_edge = timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
inst_wire_edge._is_net_edge = false;
auto& inst_arc_edge = timing_wire_graph.addEdge(wire_from_node_index, wire_to_node_index);
inst_arc_edge._is_net_edge = false;

TimingEdgeFeature edge_feature;

double max_rise_delay = FS_TO_NS(the_arc->get_arc_delay(AnalysisMode::kMax, TransType::kRise));
double max_fall_delay = FS_TO_NS(the_arc->get_arc_delay(AnalysisMode::kMax, TransType::kFall));
double min_rise_delay = FS_TO_NS(the_arc->get_arc_delay(AnalysisMode::kMin, TransType::kRise));
double min_fall_delay = FS_TO_NS(the_arc->get_arc_delay(AnalysisMode::kMin, TransType::kFall));

edge_feature._edge_delay = {max_rise_delay, max_fall_delay, min_rise_delay, min_fall_delay};

// dump power feature
PowerEdgeFeature edge_power_feature;

auto* the_pwr_arc = ipower->get_power_graph().staToPwrArc(the_arc);
if (the_pwr_arc) {
edge_power_feature._inst_arc_internal_power = dynamic_cast<ipower::PwrInstArc*>(the_pwr_arc)->getInternalPower();
}

inst_arc_edge._edge_feature = edge_feature;
inst_arc_edge._power_feature = edge_power_feature;
}
}

@@ -1070,6 +1349,7 @@ TimingInstanceGraph InitSTA::getTimingInstanceGraph()

auto* ista = STA_INST->get_ista();
LOG_ERROR_IF(!ista->isBuildGraph()) << "timing graph is not build";
auto* ipower = PW_INST->get_power();

auto* the_timing_graph = &(ista->get_graph());

@@ -1077,12 +1357,19 @@ TimingInstanceGraph InitSTA::getTimingInstanceGraph()
timing_instance_graph._nodes.reserve(the_timing_graph->get_vertexes().size() * 10);

/// create node in instance graph
auto create_node = [&timing_instance_graph](std::string& node_name) -> unsigned {
auto create_node = [&timing_instance_graph, ipower](
std::string& node_name,
ista::DesignObject* obj) -> unsigned {
auto index = timing_instance_graph.findNode(node_name);
if (!index) {
TimingInstanceNode the_node;
the_node._name = node_name;

auto* power_data = ipower->getObjData(obj);
double leakage_power = power_data->get_leakage_power();

the_node._node_feature._leakage_power = leakage_power;

index = timing_instance_graph.addNode(the_node);
}

@@ -1105,8 +1392,8 @@ TimingInstanceGraph InitSTA::getTimingInstanceGraph()
auto src_instance_name = src_instance->getFullName();
auto snk_instance_name = snk_instance->getFullName();

unsigned src_node_index = create_node(src_instance_name);
unsigned snk_node_index = create_node(snk_instance_name);
unsigned src_node_index = create_node(src_instance_name, src_instance);
unsigned snk_node_index = create_node(snk_instance_name, snk_instance);

timing_instance_graph.addEdge(src_node_index, snk_node_index);
}
@@ -1136,10 +1423,10 @@ bool InitSTA::getRcNet(const std::string& net_name)
return rc_net ? true : false;
}

/// @brief Save wire timing graph to yaml file.
/// @brief Save wire timing graph to json file.
void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string& json_file_name)
{
LOG_INFO << "save wire timing graph start";
LOG_INFO << "save wire timing graph start";

json nodes_json;
json edges_json;
@@ -1149,7 +1436,38 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string
json j = json::array();
for (unsigned node_id = 0; auto& node : timing_wire_graph._nodes) {
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}});
auto& node_feature = node._node_feature;
json node_feature_json;
node_feature_json["is_input"] = node_feature._is_input;
node_feature_json["fanout_num"] = node_feature._fanout_num;
node_feature_json["is_input"] = node_feature._is_input;
node_feature_json["is_endpoint"] = node_feature._is_endpoint;
node_feature_json["cell_name"] = node_feature._cell_name;
node_feature_json["sizer_cells"] = node_feature._sizer_cells;

node_feature_json["node_coord"] = json::array({node_feature._node_coord.first, node_feature._node_coord.second});
node_feature_json["node_slews"] = json::array({std::get<0>(node_feature._node_slews), std::get<1>(node_feature._node_slews),
std::get<2>(node_feature._node_slews), std::get<3>(node_feature._node_slews)});
node_feature_json["node_capacitances"] = json::array({std::get<0>(node_feature._node_caps), std::get<1>(node_feature._node_caps),
std::get<2>(node_feature._node_caps), std::get<3>(node_feature._node_caps)});
node_feature_json["node_arrive_times"] = json::array({std::get<0>(node_feature._node_ats), std::get<1>(node_feature._node_ats),
std::get<2>(node_feature._node_ats), std::get<3>(node_feature._node_ats)});
node_feature_json["node_required_times"] = json::array({std::get<0>(node_feature._node_rats), std::get<1>(node_feature._node_rats),
std::get<2>(node_feature._node_rats), std::get<3>(node_feature._node_rats)});
node_feature_json["node_net_load_delays"] = json::array(
{std::get<0>(node_feature._node_net_delays), std::get<1>(node_feature._node_net_delays),
std::get<2>(node_feature._node_net_delays), std::get<3>(node_feature._node_net_delays)});

node_feature_json["node_toggle"] = node._power_feature._toggle;
node_feature_json["node_sp"] = node._power_feature._sp;
node_feature_json["node_internal_power"] = node._power_feature._node_internal_power;
node_feature_json["node_net_power"] = node._power_feature._node_net_power;

j.push_back({{"id", node_id_str},
{"name", node._name},
{"is_pin", node._is_pin},
{"is_port", node._is_port},
{"node_feature", node_feature_json}});
}
nodes_json = j;
});
@@ -1159,7 +1477,21 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string
json j = json::array();
for (unsigned edge_id = 0; auto& edge : timing_wire_graph._edges) {
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}});
auto& edge_feature = edge._edge_feature;
json edge_feature_json;
edge_feature_json["edge_delay"] = json::array({std::get<0>(edge_feature._edge_delay), std::get<1>(edge_feature._edge_delay),
std::get<2>(edge_feature._edge_delay), std::get<3>(edge_feature._edge_delay)});
edge_feature_json["edge_resistance"] = edge_feature._edge_resistance;

auto& edge_power_feature = edge._power_feature;
edge_feature_json["inst_arc_internal_power"] = edge_power_feature._inst_arc_internal_power;


j.push_back({{"id", edge_id_str},
{"from_node", edge._from_node},
{"to_node", edge._to_node},
{"is_net_edge", edge._is_net_edge},
{"edge_feature", edge_feature_json}});
}
edges_json = j;
});
@@ -1168,12 +1500,12 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string
t1.join();
t2.join();

// merge
// merge
json graph_json;
graph_json["nodes"] = nodes_json;
graph_json["edges"] = edges_json;

std::ofstream file(json_file_name, std::ios::trunc);
std::ofstream file(json_file_name, std::ios::trunc);
file << graph_json.dump(4) << std::endl;

file.close();
@@ -1182,9 +1514,10 @@ void SaveTimingGraph(const TimingWireGraph& timing_wire_graph, const std::string
LOG_INFO << "save wire timing graph end";
}

/// @brief Save wire timing instance graph to json file.
void SaveTimingInstanceGraph(const TimingInstanceGraph& timing_instance_graph, const std::string& json_file_name)
{
LOG_INFO << "save instance timing graph start";
LOG_INFO << "save instance timing graph start";

json nodes_json;
json edges_json;
@@ -1194,7 +1527,10 @@ void SaveTimingInstanceGraph(const TimingInstanceGraph& timing_instance_graph, c
json j = json::array();
for (unsigned node_id = 0; auto& node : timing_instance_graph._nodes) {
std::string id_str = "node_" + std::to_string(node_id++);
j.push_back({{"id", id_str}, {"name", node._name}});
j.push_back({{"id", id_str},
{"name", node._name},
{"leakage_power",
node._node_feature._leakage_power}});
}
nodes_json = j;
});
@@ -1213,11 +1549,11 @@ void SaveTimingInstanceGraph(const TimingInstanceGraph& timing_instance_graph, c
t1.join();
t2.join();

// merge
// merge
json graph_json;
graph_json["nodes"] = nodes_json;
graph_json["edges"] = edges_json;
std::ofstream file(json_file_name, std::ios::trunc);
file << graph_json.dump(4) << std::endl;

@@ -1433,13 +1769,13 @@ std::map<int, double> InitSTA::patchTimingMap(std::map<int, std::pair<std::pair<
// 预处理:将实例坐标转换并按x坐标排序,提升查找性能
std::vector<std::tuple<int64_t, int64_t, double>> sorted_instances;
sorted_instances.reserve(inst_timing_map.size());
for (const auto& [coord, slack] : inst_timing_map) {
int64_t inst_x = static_cast<int64_t>(coord.first * dbu);
int64_t inst_y = static_cast<int64_t>(coord.second * dbu);
sorted_instances.emplace_back(inst_x, inst_y, slack);
}
// 按x坐标排序,便于后续二分查找
std::sort(sorted_instances.begin(), sorted_instances.end());

@@ -1447,23 +1783,21 @@ std::map<int, double> InitSTA::patchTimingMap(std::map<int, std::pair<std::pair<
auto [l_range, u_range] = coord;
const int64_t patch_lx = static_cast<int64_t>(l_range.first);
const int64_t patch_ly = static_cast<int64_t>(l_range.second);
const int64_t patch_ux = static_cast<int64_t>(u_range.first);
const int64_t patch_uy = static_cast<int64_t>(u_range.second);
const int64_t patch_ux = static_cast<int64_t>(u_range.first);
const int64_t patch_uy = static_cast<int64_t>(u_range.second);

double min_slack = std::numeric_limits<double>::max();
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));
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;
@@ -1501,36 +1835,34 @@ std::map<int, double> InitSTA::patchPowerMap(std::map<int, std::pair<std::pair<i
// 预处理:将实例坐标转换并按x坐标排序,提升查找性能
std::vector<std::tuple<int64_t, int64_t, double>> sorted_instances;
sorted_instances.reserve(inst_power_map.size());
for (const auto& [coord, power] : inst_power_map) {
int64_t inst_x = static_cast<int64_t>(coord.first * dbu);
int64_t inst_y = static_cast<int64_t>(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<int64_t>(l_range.first);
const int64_t patch_ly = static_cast<int64_t>(l_range.second);
const int64_t patch_ux = static_cast<int64_t>(u_range.first);
const int64_t patch_uy = static_cast<int64_t>(u_range.second);
const int64_t patch_ly = static_cast<int64_t>(l_range.second);
const int64_t patch_ux = static_cast<int64_t>(u_range.first);
const int64_t patch_uy = static_cast<int64_t>(u_range.second);

double total_power = 0.0;

// 使用二分查找确定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));
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;
}
@@ -1561,7 +1893,7 @@ std::map<int, double> InitSTA::patchIRDropMap(std::map<int, std::pair<std::pair<
auto instance_to_ir_drop = PW_INST->getInstanceIRDrop();

if (instance_to_ir_drop.empty()) {
LOG_WARNING << "No IR drop data available, returning zero values for all patches";
LOG_ERROR << "No IR drop data available, returning zero values for all patches";
return patch_ir_drop_map;
}

@@ -1571,14 +1903,14 @@ std::map<int, double> InitSTA::patchIRDropMap(std::map<int, std::pair<std::pair<
// 预处理:将实例坐标转换并按x坐标排序,提升查找性能
std::vector<std::tuple<int64_t, int64_t, double>> 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 inst_x = static_cast<int64_t>(coord.first * dbu);
int64_t inst_y = static_cast<int64_t>(coord.second * dbu);
sorted_instances.emplace_back(inst_x, inst_y, ir_drop);
}
// 按x坐标排序,便于后续二分查找
std::sort(sorted_instances.begin(), sorted_instances.end());

@@ -1593,16 +1925,14 @@ std::map<int, double> InitSTA::patchIRDropMap(std::map<int, std::pair<std::pair<
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));
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;


+ 70
- 2
src/evaluation/src/util/init_sta.hh View File

@@ -26,6 +26,7 @@
#include <map>
#include <memory>
#include <string>
#include <string>
#include <unordered_map>
#include <vector>
#include <optional>
@@ -45,12 +46,64 @@ namespace ieval {

struct TimingNet;

/// @brief The timing node features.
struct TimingNodeFeature {
using Coord = std::pair<double, double>;
/// quad data, assume order is max rise, max fall, min rise, min fall.
using QuadData = std::tuple<double, double, double, double>;

unsigned _fanout_num = 1;

bool _is_input = false;
bool _is_endpoint = false;
std::string _cell_name;
std::vector<std::string> _sizer_cells;

Coord _node_coord = {0.0, 0.0};
QuadData _node_slews = {0.0, 0.0, 0.0, 0.0};
QuadData _node_caps = {0.0, 0.0, 0.0, 0.0};
/// node arrive time
QuadData _node_ats = {0.0, 0.0, 0.0, 0.0};
/// node required time
QuadData _node_rats = {0.0, 0.0, 0.0, 0.0};
/// node net load delays.
QuadData _node_net_delays = {0.0, 0.0, 0.0, 0.0};
};

/// @brief The power node features.
struct PowerNodeFeature {
using QuadData = std::tuple<double, double, double, double>;

double _toggle = 0.125;
double _sp = 0.5;
// input pin internal power.
double _node_internal_power = 0.0;
// net power annotated to the driver node.
double _node_net_power = 0.0;
};

/// @brief The timing wire graph for weiguo used.
struct TimingWireNode
{
struct TimingWireNode {
std::string _name; //!< for pin/port name or node id.
bool _is_pin = false;
bool _is_port = false;

TimingNodeFeature _node_feature;
PowerNodeFeature _power_feature;
};

/// @brief The timing edge feature.
struct TimingEdgeFeature {
using QuadData = std::tuple<double, double, double, double>;

QuadData _edge_delay = {0.0, 0.0, 0.0, 0.0};
double _edge_resistance = 0.0;
};

/// @brief The power edge feature.
struct PowerEdgeFeature {
double _inst_arc_internal_power = 0.0;
};

struct TimingWireEdge
@@ -58,12 +111,22 @@ struct TimingWireEdge
int64_t _from_node = -1;
int64_t _to_node = -1;
bool _is_net_edge = true;

TimingEdgeFeature _edge_feature;
PowerEdgeFeature _power_feature;
};

///@brief The timing instance node feature.
struct TimingInstanceNodeFeature {
double _leakage_power = 0.0;
};


/// @brief The timing instance node for wangrui used.
struct TimingInstanceNode {
std::string _name; //!< instance name

TimingInstanceNodeFeature _node_feature;
};

struct TimingNetEdge {
@@ -99,6 +162,7 @@ struct TimingGraph

return index;
}
auto& getNode(unsigned index) { return _nodes[index]; }

U* findEdge(unsigned wire_from_node_index, unsigned wire_to_node_index)
{
@@ -167,6 +231,9 @@ class InitSTA

void runSTA();
void runVecSTA(ivec::VecLayout* vec_layout, std::string work_dir);
void runPlaceVecSTA(const std::string& routing_type, const bool& rt_done, std::string work_dir);
void runSpefVecSTA(std::string work_dir);
void saveTimingPowerBenchmark();
void evalTiming(const std::string& routing_type, const bool& rt_done = false);

std::map<std::string, std::map<std::string, std::map<std::string, double>>> getTiming() const { return _timing; }
@@ -204,6 +271,7 @@ class InitSTA

void buildRCTree(const std::string& routing_type);
void buildVecRCTree(ivec::VecLayout* vec_layout, std::string work_dir);
void buildSpefRCTree(std::string work_dir);
void updateTiming(const std::vector<TimingNet*>& timing_net_list, int32_t dbu_unit);
void updateTiming(const std::vector<TimingNet*>& timing_net_list, const std::vector<std::string>& name_list, const int& propagation_level,
int32_t dbu_unit);


+ 1
- 1
src/interface/python/py_vec/py_register_vec.h View File

@@ -26,7 +26,7 @@ void register_vectorization(py::module& m)
{
m.def("layout_patchs", layout_patchs, py::arg("path"));
m.def("layout_graph", layout_graph, py::arg("path"));
m.def("generate_vectors", generate_vectors, py::arg("dir"), py::arg("patch_row_step") = 9, py::arg("patch_col_step") = 9, py::arg("batch_mode") = true);
m.def("generate_vectors", generate_vectors, py::arg("dir"), py::arg("patch_row_step") = 9, py::arg("patch_col_step") = 9, py::arg("batch_mode") = true, py::arg("is_placement_mode") = false, py::arg("sta_mode") = 0);
m.def("read_vectors_nets", read_vectors_nets, py::arg("dir"));
m.def("read_vectors_nets_patterns", read_vectors_nets_patterns, py::arg("path"));



+ 2
- 2
src/interface/python/py_vec/py_vec.cpp View File

@@ -35,13 +35,13 @@ bool layout_graph(const std::string& path)
return lm_api.buildVectorizationGraphData(path);
}

bool generate_vectors(std::string dir, int patch_row_step, int patch_col_step, bool batch_mode)
bool generate_vectors(std::string dir, int patch_row_step, int patch_col_step, bool batch_mode, bool is_placement_mode, int sta_mode)
{
if (dir == "") {
dir = "./vectors";
}
ivec::VectorizationApi lm_api;
return lm_api.buildVectorizationFeature(dir, patch_row_step, patch_col_step, batch_mode);
return lm_api.buildVectorizationFeature(dir, patch_row_step, patch_col_step, batch_mode, is_placement_mode, sta_mode);
}

ieval::TimingWireGraph get_timing_wire_graph(std::string wire_graph_path)


+ 1
- 1
src/interface/python/py_vec/py_vec.h View File

@@ -24,7 +24,7 @@ namespace python_interface {

bool layout_patchs(const std::string& path);
bool layout_graph(const std::string& path);
bool generate_vectors(std::string dir, int patch_row_step, int patch_col_step, bool batch_mode);
bool generate_vectors(std::string dir, int patch_row_step, int patch_col_step, bool batch_mode, bool is_placement_mode = false, int sta_mode = 0);
bool read_vectors_nets(std::string dir);
bool read_vectors_nets_patterns(std::string path);



+ 2
- 2
src/operation/iCTS/source/data_manager/database/CtsNet.cc View File

@@ -19,7 +19,7 @@
* @author Dawn Li (dawnli619215645@gmail.com)
*/
#include "CtsNet.hh"
#include <algorithm>
#include <set>

#include "log/Log.hh"
@@ -140,4 +140,4 @@ CtsInstance* CtsNet::findInstance(const std::string& inst_name)
}
return nullptr;
}
} // namespace icts
} // namespace icts

+ 28
- 1
src/operation/iPA/api/Power.hh View File

@@ -87,6 +87,30 @@ class Power {
auto& get_leakage_powers() { return _leakage_powers; }
auto& get_internal_powers() { return _internal_powers; }
auto& get_switch_powers() { return _switch_powers; }

double getSumLeakagePower() {
return std::accumulate(
_leakage_powers.begin(), _leakage_powers.end(), 0.0,
[](double sum, auto& power_data) {
return sum + power_data->getPowerDataValue();
});
}

double getSumInternalPower() {
return std::accumulate(
_internal_powers.begin(), _internal_powers.end(), 0.0,
[](double sum, auto& power_data) {
return sum + power_data->getPowerDataValue();
});
}

double getSumSwitchPower() {
return std::accumulate(
_switch_powers.begin(), _switch_powers.end(), 0.0,
[](double sum, auto& power_data) {
return sum + power_data->getPowerDataValue();
});
}
auto& get_obj_to_datas() { return _obj_to_datas; }
auto* getObjData(DesignObject* design_obj) {
return _obj_to_datas.contains(design_obj) ? _obj_to_datas[design_obj].get()
@@ -159,7 +183,10 @@ class Power {
}
auto getInstanceIRDrop(std::string power_net_name) {
auto& net_to_instance_ir_drop = _ir_analysis.get_net_to_instance_ir_drop();
return net_to_instance_ir_drop.at(power_net_name);
if (!net_to_instance_ir_drop.contains(power_net_name)) {
return std::map<std::string, double>();
}
return net_to_instance_ir_drop[power_net_name];
}

void setBumpNodeLocs(


+ 13
- 0
src/operation/iPA/source/module/core/PwrGraph.hh View File

@@ -90,6 +90,15 @@ class PwrGraph {
return _vertex_pwr_to_sta[pwr_vertex];
}

void addStaAndPwrArc(StaArc* sta_arc, PwrArc* pwr_arc) {
_arc_sta_to_pwr[sta_arc] = pwr_arc;
_arc_pwr_to_sta[pwr_arc] = sta_arc;
}

PwrArc* staToPwrArc(StaArc* sta_arc) { return _arc_sta_to_pwr.contains(sta_arc) ? _arc_sta_to_pwr[sta_arc] : nullptr; }
StaArc* pwrToStaArc(PwrArc* pwr_arc) { return _arc_pwr_to_sta.contains(pwr_arc) ? _arc_pwr_to_sta[pwr_arc] : nullptr; }

void addPowerArc(std::unique_ptr<PwrArc> arc) {
_arcs.emplace_back(std::move(arc));
}
@@ -161,6 +170,10 @@ class PwrGraph {
std::unordered_map<StaVertex*, PwrVertex*>
_vertex_sta_to_pwr; //!< The sta and pwr vertex crossref.
std::unordered_map<PwrVertex*, StaVertex*> _vertex_pwr_to_sta;

std::unordered_map<PwrArc*, StaArc*> _arc_pwr_to_sta; //!< The pwr and sta arc crossref.
std::unordered_map<StaArc*, PwrArc*> _arc_sta_to_pwr;

PwrVertexSet _input_port_vertexes; //<! The input port vertexes of the
// propagation path.
PwrVertexSet _output_port_vertexes; //<! The output port vertexes of the


+ 3
- 0
src/operation/iPA/source/module/ops/build_graph/PwrBuildGraph.cc View File

@@ -131,6 +131,9 @@ unsigned PwrBuildGraph::operator()(StaGraph* sta_graph) {
if (power_arc) {
pwr_src_vertex->addSrcArc(power_arc.get());
pwr_snk_vertex->addSnkArc(power_arc.get());

_power_graph.addStaAndPwrArc(sta_arc, power_arc.get());

_power_graph.addPowerArc(std::move(power_arc));
}
}


+ 7
- 7
src/operation/iPA/source/module/ops/calc_power/PwrCalcInternalPower.cc View File

@@ -101,7 +101,7 @@ double PwrCalcInternalPower::calcCombInputPinPower(Instance* inst,
}

double rise_power =
internal_power->gatePower(TransType::kRise, *rise_slew, std ::nullopt);
internal_power->gatePower(TransType::kRise, rise_slew.value_or(0.0), std ::nullopt);
double rise_power_mw = lib_cell->convertTablePowerToMw(rise_power);
// fall power
auto fall_slew = (*the_input_sta_vertex)
@@ -109,7 +109,7 @@ double PwrCalcInternalPower::calcCombInputPinPower(Instance* inst,
LOG_FATAL_IF(!fall_slew)
<< (*the_input_sta_vertex)->getName() << " fall slew is not exist.";
double fall_power =
internal_power->gatePower(TransType::kFall, *fall_slew, std ::nullopt);
internal_power->gatePower(TransType::kFall, fall_slew.value_or(0.0), std ::nullopt);
double fall_power_mw = lib_cell->convertTablePowerToMw(fall_power);

// When the input causes the output to be flipped, the toggle needs to
@@ -211,7 +211,7 @@ double PwrCalcInternalPower::calcOutputPinPower(Instance* inst,
double output_load = convert_load_to_lib_unit(power_arc, output_load_pf);
// lut power
double internal_power_value = internal_power_info->gatePower(
trans_type, *input_slew_ns, output_load);
trans_type, input_slew_ns.value_or(0.0), output_load);

double internal_power_value_mw =
power_arc->get_owner_cell()->convertTablePowerToMw(
@@ -322,7 +322,7 @@ double PwrCalcInternalPower::calcClockPinPower(Instance* inst, Pin* clock_pin,
}

double rise_power =
internal_power->gatePower(TransType::kRise, *rise_slew, std ::nullopt);
internal_power->gatePower(TransType::kRise, rise_slew.value_or(0.0), std ::nullopt);
double rise_power_mw = lib_cell->convertTablePowerToMw(rise_power);
// fall power
auto fall_slew = (*the_clock_sta_vertex)
@@ -334,7 +334,7 @@ double PwrCalcInternalPower::calcClockPinPower(Instance* inst, Pin* clock_pin,
}

double fall_power =
internal_power->gatePower(TransType::kFall, *fall_slew, std ::nullopt);
internal_power->gatePower(TransType::kFall, fall_slew.value_or(0.0), std ::nullopt);
double fall_power_mw = lib_cell->convertTablePowerToMw(fall_power);

double average_power_mw = CalcAveragePower(rise_power_mw, fall_power_mw);
@@ -408,7 +408,7 @@ double PwrCalcInternalPower::calcSeqInputPinPower(Instance* inst,
<< (*the_input_sta_vertex)->getName() << " rise slew is not exist.";
if (rise_slew) {
double rise_power = internal_power->gatePower(TransType::kRise,
*rise_slew, std ::nullopt);
rise_slew.value_or(0.0), std ::nullopt);
rise_power_mw = lib_cell->convertTablePowerToMw(rise_power);
}

@@ -420,7 +420,7 @@ double PwrCalcInternalPower::calcSeqInputPinPower(Instance* inst,
double fall_power_mw = rise_power_mw;
if (fall_slew) {
double fall_power = internal_power->gatePower(TransType::kFall,
*fall_slew, std ::nullopt);
fall_slew.value_or(0.0), std ::nullopt);
fall_power_mw = lib_cell->convertTablePowerToMw(fall_power);
}



+ 11
- 14
src/operation/iPDN/source/module/pdn_plan/pdn_plan.cpp View File

@@ -35,10 +35,10 @@ PdnPlan::~PdnPlan()

int32_t PdnPlan::transUnitDB(double value)
{
auto idb_design = dmInst->get_idb_design(); //return IdbDesign* _idb_def_service->get_design()
auto idb_layout = idb_design->get_layout(); //class IdbDefService -> get_layout(), return IdbLayout* _layout
auto idb_design = dmInst->get_idb_design(); // return IdbDesign* _idb_def_service->get_design()
auto idb_layout = idb_design->get_layout(); // class IdbDefService -> get_layout(), return IdbLayout* _layout

return idb_layout != nullptr ? idb_layout->transUnitDB(value) : -1; //IdbLayout -> transUnitDB(double value), 即_micron_dbu微米数*value
return idb_layout != nullptr ? idb_layout->transUnitDB(value) : -1; // IdbLayout -> transUnitDB(double value), 即_micron_dbu微米数*value
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -639,27 +639,25 @@ void PdnPlan::connectTwoLayerForWire(idb::IdbSpecialWire* wire, std::vector<idb:
= dynamic_cast<idb::IdbLayerRouting*>(idb_layer_list->find_layer(segment_list_bottom[0]->get_layer()->get_name()));
idb::IdbLayerRouting* layer_top_routing
= dynamic_cast<idb::IdbLayerRouting*>(idb_layer_list->find_layer(segment_list_top[0]->get_layer()->get_name()));

for (idb::IdbSpecialWireSegment* segment_top : segment_list_top) {
for (idb::IdbSpecialWireSegment* segment_bottom : segment_list_bottom) {
/// calculate intersection between layer stripe
idb::IdbRect coordinate;
// if (segment_top->get_intersect_coordinate(segment_bottom, coordinate))
// {
if (_cut_stripe->get_intersect_coordinate(segment_top, segment_bottom, coordinate)) {
// for (IdbVia *via : via_list) {
// IdbLayer * layer_top =
// via->get_top_layer_shape().get_layer();
/// if the connecting 2 layers not neighbour layer, use bottom direction as enclosure direction
auto align_direciton = (layer_top_routing->get_order() - layer_bottom_routing->get_order()) > 2
? layer_bottom_routing->get_direction()
: idb::IdbLayerDirection::kNone;

for (int32_t layer_order = layer_bottom_routing->get_order(); layer_order <= (layer_top_routing->get_order() - 2);) {
// int32_t layer_order_bottom = layer_bottom_routing->get_order();
idb::IdbLayerCut* layer_cut_find = dynamic_cast<idb::IdbLayerCut*>(idb_layer_list->find_layer_by_order(layer_order + 1));
if (layer_cut_find == nullptr) {
std::cout << "Error : layer input illegal." << std::endl;
return;
}
// IdbVia *via_find = via_listt->find_via_generate(
// layer_cut_find, coordinate.get_width(),
// coordinate.get_height());
idb::IdbVia* via_find = pdn_via.findVia(layer_cut_find, coordinate.get_width(), coordinate.get_height());

idb::IdbVia* via_find = pdn_via.findVia(layer_cut_find, coordinate.get_width(), coordinate.get_height(), align_direciton);
if (via_find == nullptr) {
std::cout << "Error : can not find VIA matchs." << std::endl;
continue;
@@ -675,7 +673,6 @@ void PdnPlan::connectTwoLayerForWire(idb::IdbSpecialWire* wire, std::vector<idb:
std::cout << "-";
}
layer_order += 2;
// }
}
}
}


+ 1
- 0
src/operation/iPDN/source/module/pdn_via/CMakeLists.txt View File

@@ -6,6 +6,7 @@ add_library(ipdn_via
target_link_libraries(ipdn_via
PUBLIC
idm
idb
)

target_include_directories(ipdn_via


+ 11
- 7
src/operation/iPDN/source/module/pdn_via/pdn_via.cpp View File

@@ -35,17 +35,21 @@ int32_t PdnVia::transUnitDB(double value)
* @param layer_cut
* @param width_design
* @param height_design
* @param direction
* @return IdbVia*
*/
idb::IdbVia* PdnVia::findVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design)
idb::IdbVia* PdnVia::findVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design, idb::IdbLayerDirection direction)
{
auto idb_design = dmInst->get_idb_design();
auto via_list = idb_design->get_via_list();

std::string via_name = layer_cut->get_name() + "_" + std::to_string(width_design) + "x" + std::to_string(height_design);
auto direction_str = direction == IdbLayerDirection::kNone ? "" : (direction == IdbLayerDirection::kHorizontal ? "_h" : "_v");

std::string via_name = layer_cut->get_name() + "_" + std::to_string(width_design) + "x" + std::to_string(height_design) + direction_str;

idb::IdbVia* via_find = via_list->find_via(via_name);
if (via_find == nullptr) {
via_find = createVia(layer_cut, width_design, height_design, via_name);
via_find = createVia(layer_cut, width_design, height_design, via_name, direction);
}
return via_find;
}
@@ -56,17 +60,17 @@ idb::IdbVia* PdnVia::findVia(idb::IdbLayerCut* layer_cut, int32_t width_design,
* @param layer_cut
* @param width_design
* @param height_design
* @param direction
* @param via_name
* @return IdbVia*
*/
idb::IdbVia* PdnVia::createVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design, std::string via_name)
idb::IdbVia* PdnVia::createVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design, std::string via_name,
idb::IdbLayerDirection direction)
{
auto idb_design = dmInst->get_idb_design();
auto via_list = idb_design->get_via_list();

via_name = layer_cut->get_name() + "_" + std::to_string(width_design) + "x" + std::to_string(height_design);

return via_list->createVia(via_name, layer_cut, width_design, height_design);
return via_list->createVia(via_name, layer_cut, width_design, height_design, direction);
}

/**


+ 6
- 2
src/operation/iPDN/source/module/pdn_via/pdn_via.h View File

@@ -20,6 +20,8 @@
#include <string>
#include <vector>

#include "IdbEnum.h"

namespace idb {
class IdbLayer;
class IdbSpecialWireSegment;
@@ -49,8 +51,10 @@ class PdnVia

/// operator

idb::IdbVia* findVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design);
idb::IdbVia* createVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design, std::string via_name);
idb::IdbVia* findVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design,
idb::IdbLayerDirection direction = idb::IdbLayerDirection::kNone);
idb::IdbVia* createVia(idb::IdbLayerCut* layer_cut, int32_t width_design, int32_t height_design, std::string via_name,
idb::IdbLayerDirection direction = idb::IdbLayerDirection::kNone);
idb::IdbSpecialWireSegment* createSpecialWireVia(idb::IdbLayer* layer, int32_t route_width, idb::IdbWireShapeType wire_shape_type,
idb::IdbCoordinate<int32_t>* coord, idb::IdbVia* via);



+ 2
- 2
src/operation/iPL/source/module/detail_placer/database/DPRow.cc View File

@@ -15,7 +15,7 @@
// See the Mulan PSL v2 for more details.
// ***************************************************************************************
#include <cmath>
#include <algorithm>
#include "DPRow.hh"
#include "DPSegment.hh"
#include "DPBin.hh"
@@ -249,4 +249,4 @@ int64_t DPRow::computeDisplacementY(const int64_t pos_y)
return std::abs(_bound.get_ll_y() - pos_y);
}

}
}

+ 2
- 1
src/operation/iPL/source/module/topology_manager/TopologyManager.cc View File

@@ -30,6 +30,7 @@
#include <queue>
#include <tuple>
#include <set>
#include <algorithm>

#include "Log.hh"

@@ -313,4 +314,4 @@ void TopologyManager::sortArcList(){
});
}

} // namespace ipl
} // namespace ipl

+ 2
- 1
src/operation/iPL/source/utility/Geometry.hh View File

@@ -11,6 +11,7 @@
#ifndef IPL_GEOMETRY_HH
#define IPL_GEOMETRY_HH
#include <vector>
using std::size_t;
using std::vector;
namespace ipl {
template <typename T>
@@ -164,4 +165,4 @@ Ploygon<T> Ploygon<T>::PloygonClip(const Ploygon<T>& lhs, const Ploygon<T>& rhs)
}
} // namespace ipl

#endif
#endif

+ 16
- 8
src/operation/iSTA/api/TimingEngine.cc View File

@@ -1769,15 +1769,23 @@ unsigned TimingEngine::isSequentialCell(const char* instance_name) {
auto* design_netlist = _ista->get_netlist();
auto* design_instance = design_netlist->findInstance(instance_name);

Pin* design_pin;
FOREACH_INSTANCE_PIN(design_instance, design_pin) {
auto* the_vertex = _ista->findVertex(design_pin);
if (the_vertex->is_clock()) {
return 1;
}
}
auto* lib_cell = design_instance->get_inst_cell();
bool is_sequential = lib_cell->isSequentialCell();

return is_sequential;
}

/**
* @brief judge cell whether sequential.
*
* @param cell_name lib cell name.
* @return unsigned
*/
unsigned TimingEngine::isSeqCell(const char* cell_name) {
auto* lib_cell = _ista->findLibertyCell(cell_name);
bool is_sequential = lib_cell->isSequentialCell();

return 0;
return is_sequential;
}

/**


+ 8
- 2
src/operation/iSTA/api/TimingEngine.hh View File

@@ -367,13 +367,18 @@ class TimingEngine {
StaClock *getPropClock(const char *clock_pin_name);
StaSeqPathData *getWorstSeqData(StaVertex *vertex, AnalysisMode mode,
TransType trans_type) {
return _ista->getWorstSeqData(vertex, mode, trans_type);
return _ista->getWorstSeqData(vertex, mode, trans_type).front();
}

StaSeqPathData *getWorstSeqData(AnalysisMode mode, TransType trans_type) {
return _ista->getWorstSeqData(std::nullopt, mode, trans_type);
return _ista->getWorstSeqData(mode, trans_type);
}

std::vector<StaSeqPathData *> getTopNWorstSeqPaths(AnalysisMode mode,
unsigned top_n_path) {
return _ista->getTopNWorstSeqPaths(mode, top_n_path);

}
double getWorstArriveTime(AnalysisMode mode = AnalysisMode::kMax) {
double rise_AT = getWorstSeqData(mode, TransType::kRise)->getArriveTimeNs();
double fall_AT = getWorstSeqData(mode, TransType::kFall)->getArriveTimeNs();
@@ -397,6 +402,7 @@ class TimingEngine {
std::vector<StaVertex *> getFanoutVertexs(StaVertex *driver_vertex);

unsigned isSequentialCell(const char *instance_name);
unsigned isSeqCell(const char* cell_name);
std::string getCellType(const char *cell_name);
double getCellArea(const char *cell_name);
unsigned isClock(const char *pin_name) const;


+ 1
- 0
src/operation/iSTA/source/module/AI-inference/AISta.hh View File

@@ -35,6 +35,7 @@ class AISta {
virtual std::vector<float> getOutputResult(
std::vector<Ort::Value>& output_tensor) {
LOG_FATAL << "The func is not implemented";
return {};
}
};



+ 1
- 0
src/operation/iSTA/source/module/delay/ElmoreDelayCalc.cc View File

@@ -1276,6 +1276,7 @@ double RcNet::getNodeResistance(const char* node_name) {

if (auto* rc_tree = rct(); rc_tree) {
auto* node = rc_tree->node(node_name);
LOG_FATAL_IF(!node) << "node " << node_name << " not found in the RC Tree.";
res = node->_res;
}



+ 36
- 11
src/operation/iSTA/source/module/sta/Sta.cc View File

@@ -1877,7 +1877,9 @@ unsigned Sta::reportPath(const char *rpt_file_name, bool is_derate,

for (auto *report_fun : report_funcs) {
if (only_wire_path) {
if (dynamic_cast<StaReportWirePathJson *>(report_fun)) {
if (dynamic_cast<StaReportWirePathJson *>(report_fun) ||
dynamic_cast<StaReportPathSummary *>(report_fun) ||
dynamic_cast<StaReportClockTNS *>(report_fun)) {
is_ok = report_path(*report_fun);
}

@@ -2452,8 +2454,9 @@ std::multimap<std::string, std::string> Sta::getSkewRelatedSink(
* @param trans_type
* @return StaSeqPathData*
*/
StaSeqPathData *Sta::getWorstSeqData(std::optional<StaVertex *> vertex,
AnalysisMode mode, TransType trans_type) {
std::vector<StaSeqPathData *> Sta::getWorstSeqData(
std::optional<StaVertex *> vertex, AnalysisMode mode, TransType trans_type,
unsigned top_n_path) {
auto cmp = [](StaPathData *left, StaPathData *right) -> bool {
int left_slack = left->getSlack();
int right_slack = right->getSlack();
@@ -2475,18 +2478,24 @@ StaSeqPathData *Sta::getWorstSeqData(std::optional<StaVertex *> vertex,
}
}

StaSeqPathData *seq_path_data = nullptr;
std::vector<StaSeqPathData *> seq_path_datas;
unsigned i = 0;
while (!seq_data_queue.empty()) {
seq_path_data = dynamic_cast<StaSeqPathData *>(seq_data_queue.top());
auto *seq_path_data = dynamic_cast<StaSeqPathData *>(seq_data_queue.top());

if ((seq_path_data->get_delay_data()->get_trans_type() == trans_type) ||
(trans_type == TransType::kRiseFall)) {
break;
seq_path_datas.push_back(seq_path_data);
++i;

if (i >= top_n_path) {
break;
}
}
seq_data_queue.pop();
}

return seq_path_data;
return seq_path_datas;
}

/**
@@ -2497,7 +2506,21 @@ StaSeqPathData *Sta::getWorstSeqData(std::optional<StaVertex *> vertex,
* @return StaSeqPathData*
*/
StaSeqPathData *Sta::getWorstSeqData(AnalysisMode mode, TransType trans_type) {
return getWorstSeqData(std::nullopt, mode, trans_type);
auto worst_seq_datas = getWorstSeqData(std::nullopt, mode, trans_type);
return worst_seq_datas.empty() ? nullptr : worst_seq_datas[0];
}

/**
* @brief Get the top n worst slack path.
*
* @param mode
* @return StaSeqPathData*
*/
std::vector<StaSeqPathData *> Sta::getTopNWorstSeqPaths(AnalysisMode mode,
unsigned top_n_path) {
auto worst_seq_datas =
getWorstSeqData(std::nullopt, mode, TransType::kRiseFall, top_n_path);
return worst_seq_datas;
}

/**
@@ -2768,8 +2791,9 @@ Sta::getWorstSlackBetweenTwoSinks(AnalysisMode mode) {
*/
int Sta::getWorstSlack(StaVertex *end_vertex, AnalysisMode mode,
TransType trans_type) {
auto *the_worst_seq_path_data = getWorstSeqData(end_vertex, mode, trans_type);
return the_worst_seq_path_data->getSlack();
auto the_worst_seq_path_data = getWorstSeqData(end_vertex, mode, trans_type);
LOG_FATAL_IF(the_worst_seq_path_data.empty()) << "no seq data found.";
return the_worst_seq_path_data.front()->getSlack();
}

/**
@@ -3587,7 +3611,8 @@ void Sta::printFlattenData() {
auto *src_vertex = getVertex(at_data._src_vertex_id);
output_file << " src_vertex: " << src_vertex->getName() << std::endl;
} else {
output_file << " src_vertex: " << "NA" << std::endl;
output_file << " src_vertex: "
<< "NA" << std::endl;
}

output_file << " src_data_index: " << at_data._src_data_index << std::endl;


+ 7
- 5
src/operation/iSTA/source/module/sta/Sta.hh View File

@@ -225,7 +225,7 @@ class Sta {
void set_design_name(const char* design_name) {
_netlist.set_name(design_name);
}
std::string get_design_name() { return _netlist.get_name(); }
std::string& get_design_name() { return _netlist.getObjName(); }

auto& get_constrains() { return _constrains; }
void resetConstraint();
@@ -545,10 +545,12 @@ class Sta {
TransType trans_type);
std::multimap<std::string, std::string> getSkewRelatedSink(
AnalysisMode mode, TransType trans_type);
StaSeqPathData* getWorstSeqData(std::optional<StaVertex*> vertex,
AnalysisMode mode, TransType trans_type);
std::vector<StaSeqPathData*> getWorstSeqData(std::optional<StaVertex*> vertex,
AnalysisMode mode, TransType trans_type,
unsigned top_n_path = 1);
StaSeqPathData* getWorstSeqData(AnalysisMode mode, TransType trans_type);
std::vector<StaSeqPathData*> getTopNWorstSeqPaths(AnalysisMode mode,
unsigned top_n_path);

std::vector<std::tuple<std::string, std::string, double>>
getStartEndSlackPairsOfTopNPaths(int top_n, AnalysisMode mode,
@@ -714,7 +716,7 @@ class Sta {

using json = nlohmann::ordered_json;

bool _is_json_report_enabled = true; //!< The json report enable flag.
bool _is_json_report_enabled = false; //!< The json report enable flag.
json _summary_json_report = json::array(); //!< The json data
json _slack_json_report = json::array(); //!< The json data
json _detail_json_report =


+ 1
- 0
src/operation/iSTA/source/module/sta/StaPathData.hh View File

@@ -89,6 +89,7 @@ class StaPathData {
AnalysisMode getDelayType() { return _delay_data->get_delay_type(); }

StaPathDelayData* get_delay_data() { return _delay_data; }
StaVertex* getEndVertex() { return _delay_data->get_own_vertex(); }
StaClockData* get_launch_clock_data() { return _launch_clock_data; }
StaClockData* get_capture_clock_data() { return _capture_clock_data; }



+ 2
- 3
src/operation/iSTA/source/module/sta/StaReport.cc View File

@@ -873,9 +873,8 @@ unsigned StaReportPathDetailJson::operator()(StaSeqPathData* seq_path_data) {
path_json["clock_field"] = capture_clock->get_clock_name();

// Determain the delay type
auto* check_arc = seq_path_data->get_check_arc();
path_json["type"] = check_arc->isSetupArc() ? "setup" : "hold";

auto check_arc = seq_path_data->getDelayType();
path_json["type"] = (check_arc == AnalysisMode::kMax) ? "max" : "min";
// Set the path delay
auto slack = seq_path_data->getSlack();
path_json["slack"] = fix_point_str(FS_TO_NS(slack));


+ 4
- 4
src/operation/iSTA/source/module/sta/StaVertex.cc View File

@@ -994,10 +994,10 @@ void StaVertex::getPathDepth(
unsigned StaVertex::GetWorstPathDepth(AnalysisMode analysis_mode) {
auto* ista = Sta::getOrCreateSta();

auto rise_worst_seq_data =
ista->getWorstSeqData(this, analysis_mode, TransType::kRise);
auto fall_worst_seq_data =
ista->getWorstSeqData(this, analysis_mode, TransType::kFall);
auto* rise_worst_seq_data =
ista->getWorstSeqData(this, analysis_mode, TransType::kRise).front();
auto* fall_worst_seq_data =
ista->getWorstSeqData(this, analysis_mode, TransType::kFall).front();

auto rise_depth = rise_worst_seq_data->getPathDelayData().size();
auto fall_depth = fall_worst_seq_data->getPathDelayData().size();


+ 1
- 1
src/operation/iSTA/test/AIModelTest.cc View File

@@ -64,7 +64,7 @@ TEST_F(AIModelTest, calibration) {
timing_engine->reportTiming();

auto* worst_path = timing_engine->get_ista()->getWorstSeqData(
std::nullopt, AnalysisMode::kMax, TransType::kRiseFall);
AnalysisMode::kMax, TransType::kRiseFall);

std::map<AICalibratePathDelay::AIModeType, std::string> model_to_path{
{AICalibratePathDelay::AIModeType::kSky130CalibratePathDelay,


+ 1
- 0
src/platform/data_manager/config/dm_config.cpp View File

@@ -72,6 +72,7 @@ bool DataConfig::initConfig(string config_path)
set_lib_paths(lib_paths);

set_sdc_path(ieda::getJsonData(json, {"INPUT", "sdc_path"}));
set_spef_path(ieda::getJsonData(json, {"INPUT", "spef_path"}));

set_output_path(ieda::getJsonData(json, {"OUTPUT", "output_dir_path"}));



+ 12
- 0
src/platform/tool_manager/tool_api/ista_io/ista_io.cpp View File

@@ -114,9 +114,21 @@ bool StaIO::initSTA(std::string path, bool init_log)
readIdb();
runSDC();

set_instance_flip_flop();

return true;
}

void StaIO::set_instance_flip_flop()
{
auto* idb_instances = dmInst->get_idb_design()->get_instance_list();
for (auto* idb_inst : idb_instances->get_instance_list()) {
if (isSequentialCell(idb_inst->get_name())) {
idb_inst->set_as_flip_flop_flag();
}
}
}

/**
* @brief Judge whether timing_engine is init.
*


+ 2
- 0
src/platform/tool_manager/tool_api/ista_io/ista_io.h View File

@@ -91,6 +91,8 @@ class StaIO

StaIO() {}
~StaIO() = default;

void set_instance_flip_flop();
};

} // namespace iplf

+ 1
- 1
src/third_party/LSAssigner4iEDA

@@ -1 +1 @@
Subproject commit acb8e662dc886c24e64ea49a3dde0562becdb770
Subproject commit 63bd10767379c47e0c0f268e08a0a09067da9993

+ 2
- 2
src/vectorization/api/vec_api.cpp View File

@@ -47,11 +47,11 @@ std::map<int, VecNet> VectorizationApi::getGraph(std::string path)
return vectorization.getGraph(path);
}

bool VectorizationApi::buildVectorizationFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode)
bool VectorizationApi::buildVectorizationFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode, bool is_placement_mode, int sta_mode)
{
Vectorization vectorization;

vectorization.buildFeature(dir, patch_row_step, patch_col_step, batch_mode);
vectorization.buildFeature(dir, patch_row_step, patch_col_step, batch_mode, is_placement_mode, sta_mode);

return true;
}


+ 1
- 1
src/vectorization/api/vec_api.h View File

@@ -29,7 +29,7 @@ class VectorizationApi

bool buildVectorizationLayoutData(const std::string path);
bool buildVectorizationGraphData(const std::string path);
bool buildVectorizationFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode = true);
bool buildVectorizationFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode = true, bool is_placement_mode = false, int sta_mode = 0);

// run the vectorization sta for get timing data.
bool runVecSTA(const std::string dir = "VEC_STA");


+ 1
- 0
src/vectorization/database/vec_net.cpp View File

@@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include "vec_net.h"

#include "Log.hh"


+ 11
- 9
src/vectorization/src/data_manager/vec_dm.cpp View File

@@ -26,15 +26,15 @@

namespace ivec {

bool VecDataManager::buildLayoutData()
bool VecDataManager::buildLayoutData(bool is_placement_mode)
{
return layout_dm.buildLayoutData();
return layout_dm.buildLayoutData(is_placement_mode);
}

bool VecDataManager::buildGraphData()
bool VecDataManager::buildGraphData(bool is_placement_mode)
{
VecGraphDataManager graph_dm(&layout_dm.get_layout());
bool b_success = graph_dm.buildGraphData();
bool b_success = graph_dm.buildGraphData(is_placement_mode);

return b_success;
}
@@ -47,16 +47,16 @@ bool VecDataManager::buildPatternData()
return true;
}

bool VecDataManager::buildPatchData(const std::string dir)
bool VecDataManager::buildPatchData(const std::string dir, bool is_placement_mode)
{
patch_dm = new VecPatchDataManager(&layout_dm.get_layout());
return patch_dm->buildPatchData();
return patch_dm->buildPatchData(is_placement_mode);
}

bool VecDataManager::buildPatchData(const std::string dir, int patch_row_step, int patch_col_step)
bool VecDataManager::buildPatchData(const std::string dir, int patch_row_step, int patch_col_step, bool is_placement_mode)
{
patch_dm = new VecPatchDataManager(&layout_dm.get_layout());
return patch_dm->buildPatchData(patch_row_step, patch_col_step);
return patch_dm->buildPatchData(patch_row_step, patch_col_step, is_placement_mode);
}

bool VecDataManager::checkData()
@@ -78,8 +78,10 @@ std::map<int, VecNet> VecDataManager::getGraph(std::string path)
return layout_dm.get_graph();
}

void VecDataManager::saveData(const std::string dir, bool batch_mode)
void VecDataManager::saveData(const std::string dir, bool batch_mode, bool is_placement_mode)
{
// Always pass patch_grid if it exists, regardless of placement mode
// This ensures patch data is saved in both placement and routing modes
VecLayoutFileIO file_io(dir, &layout_dm.get_layout(), &patch_dm->get_patch_grid());
file_io.saveJson(batch_mode);
}


+ 5
- 5
src/vectorization/src/data_manager/vec_dm.h View File

@@ -35,15 +35,15 @@ class VecDataManager
}
}

bool buildLayoutData();
bool buildGraphData();
bool buildLayoutData(bool is_placement_mode = false);
bool buildGraphData(bool is_placement_mode = false);
bool buildPatternData();
bool buildPatchData(const std::string dir);
bool buildPatchData(const std::string dir, int patch_row_step, int patch_col_step);
bool buildPatchData(const std::string dir, bool is_placement_mode = false);
bool buildPatchData(const std::string dir, int patch_row_step, int patch_col_step, bool is_placement_mode = false);
std::map<int, VecNet> getGraph(std::string path);

bool checkData();
void saveData(const std::string dir, bool batch_mode = true);
void saveData(const std::string dir, bool batch_mode = true, bool is_placement_mode = false);
bool readNetsToIDB(std::string dir);
bool readNetsPatternToIDB(std::string path);



+ 1
- 0
src/vectorization/src/data_manager/vec_file.cpp View File

@@ -373,6 +373,7 @@ bool VecLayoutFileIO::saveJsonPatchs(bool batch_mode)
makeDir(_path + "/patchs/");

if (!_patch_grid) {
LOG_INFO << "There is no patch grid, exit...";
return false;
}



+ 2
- 2
src/vectorization/src/feature/vec_feature.cpp View File

@@ -42,14 +42,14 @@ void VecFeature::buildFeatureDrc(std::string drc_path)

void VecFeature::buildFeatureTiming()
{
VecFeatureTiming feature_timing(_layout, _dir);
VecFeatureTiming feature_timing(_layout, _dir, _is_placement_mode, _sta_mode);

feature_timing.build();
}

void VecFeature::buildFeatureStatis()
{
VecFeatureStatis feature_statis(_layout, _patch_grid);
VecFeatureStatis feature_statis(_layout, _patch_grid, _is_placement_mode);

feature_statis.build();
}

+ 5
- 1
src/vectorization/src/feature/vec_feature.h View File

@@ -27,11 +27,13 @@ namespace ivec {
class VecFeature
{
public:
VecFeature(VecLayout* layout, VecPatchGrid* patch_grid, std::string dir)
VecFeature(VecLayout* layout, VecPatchGrid* patch_grid, std::string dir, bool is_placement_mode = false, int sta_mode = 0)
{
_layout = layout;
_patch_grid = patch_grid;
_dir = dir; /// feature directory
_is_placement_mode = is_placement_mode;
_sta_mode = sta_mode;
}
~VecFeature() {}

@@ -43,6 +45,8 @@ class VecFeature
VecLayout* _layout;
VecPatchGrid* _patch_grid;
std::string _dir;
bool _is_placement_mode;
int _sta_mode;
};

} // namespace ivec

+ 122
- 88
src/vectorization/src/feature/vec_feature_statis.cpp View File

@@ -100,102 +100,105 @@ void VecFeatureStatis::feature_graph()
std::vector<double> 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);

for (auto& [node1, node2] : wire.get_paths()) {
if (node1->get_layer_id() == node2->get_layer_id()) {
auto order = node1->get_layer_id();
auto* layout_layer = layout_layers.findLayoutLayer(order);
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);

/// set feature
wire_feature->wire_width = layout_layer->get_wire_width();

int min_row = std::min(node1->get_row_id(), node2->get_row_id());
int max_row = std::max(node1->get_row_id(), node2->get_row_id());
int min_col = std::min(node1->get_col_id(), node2->get_col_id());
int max_col = std::max(node1->get_col_id(), node2->get_col_id());

net_row_min = std::min(net_row_min, min_row);
net_row_max = std::max(net_row_max, max_row);
net_col_min = std::min(net_col_min, min_col);
net_col_max = std::max(net_col_max, max_col);

// transform the row and col index of node to the row and col index of egr_layer_map
int min_node_x = std::min(node1->get_x(), node2->get_x());
int max_node_x = std::max(node1->get_x(), node2->get_x());
int min_node_y = std::min(node1->get_y(), node2->get_y());
int max_node_y = std::max(node1->get_y(), node2->get_y());

int trans_min_row = static_cast<int>(min_node_y / row_factor);
int trans_max_row = static_cast<int>(max_node_y / row_factor);
int trans_min_col = static_cast<int>(min_node_x / col_factor);
int trans_max_col = static_cast<int>(max_node_x / col_factor);

/// congestion
int sum_congestion = 0;
int trans_grid_count = 0;

for (int r = trans_min_row; r <= trans_max_row; ++r) {
for (int c = trans_min_col; c <= trans_max_col; ++c) {
sum_congestion += egr_layer_map[layer_name][r][c];
trans_grid_count++;
// Process wire information only in non-placement mode
if (!_is_placement_mode) {
for (auto& wire : vec_net.get_wires()) {
auto* wire_feature = wire.get_feature(true);

for (auto& [node1, node2] : wire.get_paths()) {
if (node1->get_layer_id() == node2->get_layer_id()) {
auto order = node1->get_layer_id();
auto* layout_layer = layout_layers.findLayoutLayer(order);
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);

/// set feature
wire_feature->wire_width = layout_layer->get_wire_width();

int min_row = std::min(node1->get_row_id(), node2->get_row_id());
int max_row = std::max(node1->get_row_id(), node2->get_row_id());
int min_col = std::min(node1->get_col_id(), node2->get_col_id());
int max_col = std::max(node1->get_col_id(), node2->get_col_id());

net_row_min = std::min(net_row_min, min_row);
net_row_max = std::max(net_row_max, max_row);
net_col_min = std::min(net_col_min, min_col);
net_col_max = std::max(net_col_max, max_col);

// transform the row and col index of node to the row and col index of egr_layer_map
int min_node_x = std::min(node1->get_x(), node2->get_x());
int max_node_x = std::max(node1->get_x(), node2->get_x());
int min_node_y = std::min(node1->get_y(), node2->get_y());
int max_node_y = std::max(node1->get_y(), node2->get_y());

int trans_min_row = static_cast<int>(min_node_y / row_factor);
int trans_max_row = static_cast<int>(max_node_y / row_factor);
int trans_min_col = static_cast<int>(min_node_x / col_factor);
int trans_max_col = static_cast<int>(max_node_x / col_factor);

/// congestion
int sum_congestion = 0;
int trans_grid_count = 0;

for (int r = trans_min_row; r <= trans_max_row; ++r) {
for (int c = trans_min_col; c <= trans_max_col; ++c) {
sum_congestion += egr_layer_map[layer_name][r][c];
trans_grid_count++;
}
}
}

if (trans_grid_count > 0) {
wire_feature->congestion += ((double) sum_congestion / trans_grid_count);
} else {
wire_feature->congestion = 0;
}
if (trans_grid_count > 0) {
wire_feature->congestion += ((double) sum_congestion / trans_grid_count);
} else {
wire_feature->congestion = 0;
}

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;
}
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 += segment_length;
wire_feature->wire_density = wire_feature->wire_len * wire_feature->wire_width / static_cast<double>(net_feature->area);
wire_feature->wire_len += segment_length;
wire_feature->wire_density = wire_feature->wire_len * wire_feature->wire_width / static_cast<double>(net_feature->area);

/// some feature label on node
for (int row = min_row; row <= max_row; ++row) {
for (int col = min_col; col <= max_col; ++col) {
auto* node = grid.get_node(row, col);
if (node == nullptr || node->get_node_data() == nullptr) {
continue;
/// some feature label on node
for (int row = min_row; row <= max_row; ++row) {
for (int col = min_col; col <= max_col; ++col) {
auto* node = grid.get_node(row, col);
if (node == nullptr || node->get_node_data() == nullptr) {
continue;
}
}
}
} else {
/// via feature
net_feature->via_num += 1;
}
} else {
/// via feature
net_feature->via_num += 1;
}
}

net_feature->wire_len += wire_feature->wire_len;
net_feature->llx = gridInfoInst.calculate_x(net_col_min);
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->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<double>(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<double>(net_feature->width));
}
net_feature->wire_len += wire_feature->wire_len;
net_feature->llx = gridInfoInst.calculate_x(net_col_min);
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->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<double>(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<double>(net_feature->width));
}
}
}

if (total_wire_length > 0) {
@@ -251,7 +254,9 @@ void VecFeatureStatis::feature_patch()
// key is patch_id, value is the corresponding map value.
std::map<int, double> cell_power_map = TimingPower_API_INST->patchPowerMap(patch_xy_map);
std::map<int, double> cell_timing_map = TimingPower_API_INST->patchTimingMap(patch_xy_map);
std::map<int, double> cell_ir_map = TimingPower_API_INST->patchIRDropMap(patch_xy_map);
std::map<int, double> cell_ir_map; // mask for contest.
// std::map<int, double> cell_ir_map = TimingPower_API_INST->patchIRDropMap(patch_xy_map);

std::map<int, int> pin_density_map = DENSITY_API_INST->patchPinDensity(patch_xy_map);
std::map<int, double> cell_density_map = DENSITY_API_INST->patchCellDensity(patch_xy_map);
std::map<int, double> net_density_map = DENSITY_API_INST->patchNetDensity(patch_xy_map);
@@ -269,7 +274,16 @@ void VecFeatureStatis::feature_patch()

patch.pin_density = pin_density_map[patch_id];
patch.cell_density = cell_density_map[patch_id];
patch.net_density = net_density_map[patch_id];
// In placement mode, use original net_density calculation
// In routing mode, calculate net_density using real wire density (max across all layers)
if (_is_placement_mode) {
patch.net_density = net_density_map[patch_id];
} else {
// Will be calculated later using real wire data
patch.net_density = 0.0;
}
patch.macro_margin = macro_margin_map[patch_id];
patch.RUDY_congestion = rudy_congestion_map[patch_id];
patch.EGR_congestion = egr_congestion_map[patch_id];
@@ -319,6 +333,26 @@ void VecFeatureStatis::feature_patch()
}
}

// Calculate net_density for routing mode using real wire data
if (!_is_placement_mode) {
double sum_wire_density = 0.0;
// Calculate patch area
int patch_width = (patch.colIdMax - patch.colIdMin) * gridInfoInst.x_step;
int patch_height = (patch.rowIdMax - patch.rowIdMin) * gridInfoInst.y_step;
double patch_area = static_cast<double>(patch_width) * patch_height;
// Calculate wire density for each layer and find maximum
for (auto& [layer_id, patch_layer] : patch.get_layer_map()) {
double wire_density = 0.0;
// Wire density = (wire_length * wire_width) / patch_area
wire_density = (static_cast<double>(patch_layer.wire_len) * patch_layer.wire_width) / patch_area;
sum_wire_density += wire_density;
}
patch.net_density = sum_wire_density;
}

if (i % 1000 == 0) {
LOG_INFO << "Feature patch : " << i << " / " << patchs.size();
}


+ 3
- 1
src/vectorization/src/feature/vec_feature_statis.h View File

@@ -26,10 +26,11 @@ namespace ivec {
class VecFeatureStatis
{
public:
VecFeatureStatis(VecLayout* layout, VecPatchGrid* patch_grid)
VecFeatureStatis(VecLayout* layout, VecPatchGrid* patch_grid, bool is_placement_mode = false)
{
_layout = layout;
_patch_grid = patch_grid;
_is_placement_mode = is_placement_mode;
}
~VecFeatureStatis() {}

@@ -38,6 +39,7 @@ class VecFeatureStatis
private:
VecLayout* _layout;
VecPatchGrid* _patch_grid;
bool _is_placement_mode;

void feature_graph();
void feature_patch();


+ 21
- 3
src/vectorization/src/feature/vec_feature_timing.cpp View File

@@ -34,9 +34,27 @@ void VecFeatureTiming::build()
{
auto* eval_tp = ieval::InitSTA::getInst(); // evaluate timing and power.

eval_tp->runVecSTA(_layout, _dir);

buildNetTimingPowerFeature();
if (_is_placement_mode) {
// In placement mode, use EGR estimation for timing calculation
eval_tp->runPlaceVecSTA("HPWL", false, _dir);
} else {
// In routing mode, user can choose between VEC_STA and SPEF_STA
switch (_sta_mode) {
case 0:
// Use actual wire information from layout (VEC_STA mode)
eval_tp->runVecSTA(_layout, _dir);
buildNetTimingPowerFeature();
break;
case 1:
// Use SPEF file for timing analysis (SPEF_STA mode)
eval_tp->runSpefVecSTA(_dir);
break;
default:
// Default to VEC_STA mode
eval_tp->runVecSTA(_layout, _dir);
break;
}
}

auto timing_wire_graph = eval_tp->getTimingWireGraph();



+ 4
- 1
src/vectorization/src/feature/vec_feature_timing.h View File

@@ -24,7 +24,8 @@ namespace ivec {
class VecFeatureTiming
{
public:
VecFeatureTiming(VecLayout* layout, std::string dir) : _layout(layout), _dir(dir) {}
VecFeatureTiming(VecLayout* layout, std::string dir, bool is_placement_mode = false, int sta_mode = 0)
: _layout(layout), _dir(dir), _is_placement_mode(is_placement_mode), _sta_mode(sta_mode) {}
~VecFeatureTiming() {}

void build();
@@ -32,6 +33,8 @@ class VecFeatureTiming
private:
VecLayout* _layout;
std::string _dir; //!< The directory for the path.
bool _is_placement_mode;
int _sta_mode;

void buildWireTimingPowerFeature(VecNet* vec_net, const std::string& net_name);
void buildNetTimingPowerFeature();


+ 7
- 1
src/vectorization/src/graph/data_manager/vec_graph_dm.cpp View File

@@ -29,8 +29,14 @@ namespace ivec {

#define debug_error 0

bool VecGraphDataManager::buildGraphData()
bool VecGraphDataManager::buildGraphData(bool is_placement_mode)
{
// In placement mode, skip wire processing since place.def doesn't contain routing information
if (is_placement_mode) {
LOG_INFO << "Placement mode: skipping wire graph construction";
return true;
}

auto get_nodes
= [&](int x1, int y1, int layer1, int x2, int y2, int layer2, VecLayoutLayers& layout_layers) -> std::pair<VecNode*, VecNode*> {
if (layer1 == layer2) {


+ 1
- 1
src/vectorization/src/graph/data_manager/vec_graph_dm.h View File

@@ -30,7 +30,7 @@ class VecGraphDataManager

std::map<int, VecNet>& get_graph() { return _layout->get_graph().get_net_map(); }

bool buildGraphData();
bool buildGraphData(bool is_placement_mode = false);

private:
VecLayout* _layout;


+ 4
- 4
src/vectorization/src/layout/data_manager/vec_layout_dm.cpp View File

@@ -22,17 +22,17 @@
#include "vec_layout_init.h"

namespace ivec {
bool VecLayoutDataManager::buildLayoutData()
bool VecLayoutDataManager::buildLayoutData(bool is_placement_mode)
{
init();
init(is_placement_mode);

return true;
}

void VecLayoutDataManager::init()
void VecLayoutDataManager::init(bool is_placement_mode)
{
VecLayoutInit layout_init(&_layout);
layout_init.init();
layout_init.init(is_placement_mode);
}

} // namespace ivec

+ 2
- 2
src/vectorization/src/layout/data_manager/vec_layout_dm.h View File

@@ -31,12 +31,12 @@ class VecLayoutDataManager
VecLayout& get_layout() { return _layout; }
std::map<int, VecNet>& get_graph() { return _layout.get_graph().get_net_map(); }

bool buildLayoutData();
bool buildLayoutData(bool is_placement_mode = false);

private:
VecLayout _layout;

void init();
void init(bool is_placement_mode = false);
};

} // namespace ivec

+ 48
- 43
src/vectorization/src/layout/data_manager/vec_layout_init.cpp View File

@@ -34,9 +34,11 @@

namespace ivec {

void VecLayoutInit::init()
void VecLayoutInit::init(bool is_placement_mode)
{
initViaIds();
if (!is_placement_mode){
initViaIds();
}

initCells();
initLayers();
@@ -46,7 +48,8 @@ void VecLayoutInit::init()
initInstances();
// initIOPins();

initNets();
// Initialize nets, but skip wire processing in placement mode
initNets(is_placement_mode);
}

void VecLayoutInit::initViaIds()
@@ -68,7 +71,7 @@ void VecLayoutInit::initViaIds()
LOG_INFO << "Via number : " << index;
}

void VecLayoutInit::initDie()
void VecLayoutInit:: initDie()
{
auto* idb_layout = dmInst->get_idb_layout();
auto* idb_die = idb_layout->get_die();
@@ -706,7 +709,7 @@ void VecLayoutInit::transNetDelta(int32_t ll_x, int32_t ll_y, int32_t ur_x, int3
}
}

void VecLayoutInit::initNets()
void VecLayoutInit::initNets(bool is_placement_mode)
{
ieda::Stats stats;

@@ -796,50 +799,52 @@ void VecLayoutInit::initNets()
transPin(io_pin, net_id, VecNodeTYpe::vec_net, -1, pin_id, true);
}

/// init wires
auto* idb_wires = idb_net->get_wire_list();
for (auto* idb_wire : idb_wires->get_wire_list()) {
for (auto* idb_segment : idb_wire->get_segment_list()) {
/// wire
if (idb_segment->is_via()) {
for (auto* idb_via : idb_segment->get_via_list()) {
transVia(idb_via, net_id, VecNodeTYpe::vec_net);
/// init wires - skip in placement mode as there are no wire information
if (!is_placement_mode) {
auto* idb_wires = idb_net->get_wire_list();
for (auto* idb_wire : idb_wires->get_wire_list()) {
for (auto* idb_segment : idb_wire->get_segment_list()) {
/// wire
if (idb_segment->is_via()) {
for (auto* idb_via : idb_segment->get_via_list()) {
transVia(idb_via, net_id, VecNodeTYpe::vec_net);
}
} else if (idb_segment->is_rect()) {
/// wire patch
auto* coordinate = idb_segment->get_point_start();
auto* rect_delta = idb_segment->get_delta_rect();
IdbRect* rect = new IdbRect(rect_delta);
rect->moveByStep(coordinate->get_x(), coordinate->get_y());

/// build grid
transNetDelta(rect->get_low_x(), rect->get_low_y(), rect->get_high_x(), rect->get_high_y(), idb_segment->get_layer()->get_name(),
net_id, VecNodeTYpe::vec_net);

delete rect;
} else {
/// nothing to do
}
} else if (idb_segment->is_rect()) {
/// wire patch
auto* coordinate = idb_segment->get_point_start();
auto* rect_delta = idb_segment->get_delta_rect();
IdbRect* rect = new IdbRect(rect_delta);
rect->moveByStep(coordinate->get_x(), coordinate->get_y());

/// build grid
transNetDelta(rect->get_low_x(), rect->get_low_y(), rect->get_high_x(), rect->get_high_y(), idb_segment->get_layer()->get_name(),
net_id, VecNodeTYpe::vec_net);

delete rect;
} else {
/// nothing to do
}

/// build wire
if (idb_segment->get_point_number() >= 2) {
auto* routing_layer = dynamic_cast<IdbLayerRouting*>(idb_segment->get_layer());
/// build wire
if (idb_segment->get_point_number() >= 2) {
auto* routing_layer = dynamic_cast<IdbLayerRouting*>(idb_segment->get_layer());

/// get bounding box
auto* point_1 = idb_segment->get_point_start();
auto* point_2 = idb_segment->get_point_second();
/// get bounding box
auto* point_1 = idb_segment->get_point_start();
auto* point_2 = idb_segment->get_point_second();

int32_t ll_x = std::min(point_1->get_x(), point_2->get_x());
int32_t ll_y = std::min(point_1->get_y(), point_2->get_y());
int32_t ur_x = std::max(point_1->get_x(), point_2->get_x());
int32_t ur_y = std::max(point_1->get_y(), point_2->get_y());
int32_t ll_x = std::min(point_1->get_x(), point_2->get_x());
int32_t ll_y = std::min(point_1->get_y(), point_2->get_y());
int32_t ur_x = std::max(point_1->get_x(), point_2->get_x());
int32_t ur_y = std::max(point_1->get_y(), point_2->get_y());

/// build grid
transNetRect(ll_x, ll_y, ur_x, ur_y, routing_layer->get_name(), net_id, VecNodeTYpe::vec_net);
/// build grid
transNetRect(ll_x, ll_y, ur_x, ur_y, routing_layer->get_name(), net_id, VecNodeTYpe::vec_net);
}
}
if (net_id % 1000 == 0) {
LOG_INFO << "Read nets : " << net_id << " / " << (int) idb_nets->get_net_list().size();
}
}
if (net_id % 1000 == 0) {
LOG_INFO << "Read nets : " << net_id << " / " << (int) idb_nets->get_net_list().size();
}
}
}


+ 2
- 2
src/vectorization/src/layout/data_manager/vec_layout_init.h View File

@@ -32,7 +32,7 @@ class VecLayoutInit
public:
VecLayoutInit(VecLayout* layout) : _layout(layout) {}
~VecLayoutInit() {}
void init();
void init(bool is_placement_mode = false);

private:
VecLayout* _layout;
@@ -49,7 +49,7 @@ class VecLayoutInit
void initPDN();
void initInstances();
void initIOPins();
void initNets();
void initNets(bool is_placement_mode = false);

void transPin(idb::IdbPin* idb_pin, int net_id, VecNodeTYpe type, int instance_id = -1, int pin_id = -1, bool b_io = false);
void transVia(idb::IdbVia* idb_via, int net_id, VecNodeTYpe type);


+ 8
- 8
src/vectorization/src/patch/data_manager/vec_patch_dm.cpp View File

@@ -24,33 +24,33 @@

namespace ivec {

bool VecPatchDataManager::buildPatchData()
bool VecPatchDataManager::buildPatchData(bool is_placement_mode)
{
init();
init(is_placement_mode);

return true;
}

bool VecPatchDataManager::buildPatchData(int patch_row_step, int patch_col_step)
bool VecPatchDataManager::buildPatchData(int patch_row_step, int patch_col_step, bool is_placement_mode)
{
init(patch_row_step, patch_col_step);
init(patch_row_step, patch_col_step, is_placement_mode);

return true;
}


void VecPatchDataManager::init()
void VecPatchDataManager::init(bool is_placement_mode)
{
VecPatchInit patch_init(_layout, &_patch_grid);
patch_init.init();
patch_init.init(is_placement_mode);
}

void VecPatchDataManager::init(int patch_row_step, int patch_col_step)
void VecPatchDataManager::init(int patch_row_step, int patch_col_step, bool is_placement_mode)
{
VecPatchInfo::getInst(patch_row_step, patch_col_step);

VecPatchInit patch_init(_layout, &_patch_grid);
patch_init.init();
patch_init.init(is_placement_mode);
}



+ 4
- 4
src/vectorization/src/patch/data_manager/vec_patch_dm.h View File

@@ -31,15 +31,15 @@ class VecPatchDataManager

VecPatchGrid& get_patch_grid() { return _patch_grid; }

bool buildPatchData();
bool buildPatchData(int patch_row_step, int patch_col_step);
bool buildPatchData(bool is_placement_mode = false);
bool buildPatchData(int patch_row_step, int patch_col_step, bool is_placement_mode = false);

private:
VecLayout* _layout = nullptr;
VecPatchGrid _patch_grid;

void init();
void init(int patch_row_step, int patch_col_step);
void init(bool is_placement_mode = false);
void init(int patch_row_step, int patch_col_step, bool is_placement_mode = false);
};

} // namespace ivec

+ 6
- 2
src/vectorization/src/patch/data_manager/vec_patch_init.cpp View File

@@ -25,10 +25,14 @@

namespace ivec {

void VecPatchInit::init()
void VecPatchInit::init(bool is_placement_mode)
{
init_patch_grid();
initSubNet();
// In placement mode, skip subnet initialization as there are no wire information
if (!is_placement_mode) {
initSubNet();
}
}

void VecPatchInit::init_patch_grid()


+ 1
- 1
src/vectorization/src/patch/data_manager/vec_patch_init.h View File

@@ -29,7 +29,7 @@ class VecPatchInit
public:
VecPatchInit(VecLayout* layout, VecPatchGrid* patch_grid) : _layout(layout), _patch_grid(patch_grid) {}
~VecPatchInit() {}
void init();
void init(bool is_placement_mode = false);

private:
VecLayout* _layout;


+ 22
- 19
src/vectorization/src/vectorization.cpp View File

@@ -48,20 +48,20 @@ bool Vectorization::buildLayoutData(const std::string path)
return b_success;
}

bool Vectorization::buildGraphData(const std::string path)
bool Vectorization::buildGraphData(const std::string path, bool is_placement_mode)
{
bool b_success = _data_manager.buildGraphData();
bool b_success = _data_manager.buildGraphData(is_placement_mode);

_data_manager.checkData();

_data_manager.saveData(path);
_data_manager.saveData(path, true, is_placement_mode);

return b_success;
}

bool Vectorization::buildGraphDataWithoutSave(const std::string path)
bool Vectorization::buildGraphDataWithoutSave(const std::string path, bool is_placement_mode)
{
bool b_success = _data_manager.buildGraphData();
bool b_success = _data_manager.buildGraphData(is_placement_mode);
return b_success;
}

@@ -70,25 +70,25 @@ std::map<int, VecNet> Vectorization::getGraph(std::string path)
return _data_manager.getGraph(path);
}

void Vectorization::buildFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode)
void Vectorization::buildFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode, bool is_placement_mode, int sta_mode)
{
{
/// build layout data
MemoryMonitor monitor("buildLayoutData", "./memory_usage.log");
_data_manager.buildLayoutData();
_data_manager.buildLayoutData(is_placement_mode);
}

{
/// build graph
MemoryMonitor monitor("buildGraphData", "./memory_usage.log");
_data_manager.buildGraphData();
_data_manager.buildGraphData(is_placement_mode);
}

{
/// build patch data
MemoryMonitor monitor("buildPatchData", "./memory_usage.log");
// buildPatchData(dir);
buildPatchData(dir, patch_row_step, patch_col_step); // default patch size
buildPatchData(dir, patch_row_step, patch_col_step, is_placement_mode); // default patch size
}
// build pattern
// _data_manager.buildPatternData();
@@ -97,21 +97,24 @@ void Vectorization::buildFeature(const std::string dir, int patch_row_step, int
bool check_ok = _data_manager.checkData();

/// build feature
generateFeature(dir);
generateFeature(dir, is_placement_mode, sta_mode);

/// save
_data_manager.saveData(dir, batch_mode);
_data_manager.saveData(dir, batch_mode, is_placement_mode);
}

void Vectorization::generateFeature(const std::string dir)
void Vectorization::generateFeature(const std::string dir, bool is_placement_mode, int sta_mode)
{
auto* patch_grid = _data_manager.patch_dm == nullptr ? nullptr : &_data_manager.patch_dm->get_patch_grid();
VecFeature feature(&_data_manager.layout_dm.get_layout(), patch_grid, dir);
auto* patch_grid = _data_manager.patch_dm == nullptr ? nullptr : &_data_manager.patch_dm->get_patch_grid();
VecFeature feature(&_data_manager.layout_dm.get_layout(), patch_grid, dir, is_placement_mode, sta_mode);
{
MemoryMonitor monitor("buildFeatureTiming", "./memory_usage.log");
feature.buildFeatureTiming();
}
{
// Skip DRC feature in placement mode as it requires wire information
if (!is_placement_mode) {
MemoryMonitor monitor("buildFeatureDrc", "./memory_usage.log");
feature.buildFeatureDrc();
}
@@ -131,14 +134,14 @@ bool Vectorization::runVecSTA(const std::string dir)
return true;
}

bool Vectorization::buildPatchData(const std::string dir)
bool Vectorization::buildPatchData(const std::string dir, bool is_placement_mode)
{
return _data_manager.buildPatchData(dir);
return _data_manager.buildPatchData(dir, is_placement_mode);
}

bool Vectorization::buildPatchData(const std::string dir, int patch_row_step, int patch_col_step)
bool Vectorization::buildPatchData(const std::string dir, int patch_row_step, int patch_col_step, bool is_placement_mode)
{
return _data_manager.buildPatchData(dir, patch_row_step, patch_col_step);
return _data_manager.buildPatchData(dir, patch_row_step, patch_col_step, is_placement_mode);
}

bool Vectorization::readNetsToIDB(const std::string dir)


+ 6
- 6
src/vectorization/src/vectorization.h View File

@@ -29,12 +29,12 @@ class Vectorization
~Vectorization() {}

bool buildLayoutData(const std::string path = "");
bool buildGraphData(const std::string path);
bool buildGraphDataWithoutSave(const std::string path);
bool buildGraphData(const std::string path, bool is_placement_mode = false);
bool buildGraphDataWithoutSave(const std::string path, bool is_placement_mode = false);
std::map<int, VecNet> getGraph(std::string path);
void buildFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode);
bool buildPatchData(const std::string dir);
bool buildPatchData(const std::string dir, int patch_row_step, int patch_col_step);
void buildFeature(const std::string dir, int patch_row_step, int patch_col_step, bool batch_mode, bool is_placement_mode = false, int sta_mode = 0);
bool buildPatchData(const std::string dir, bool is_placement_mode = false);
bool buildPatchData(const std::string dir, int patch_row_step, int patch_col_step, bool is_placement_mode = false);

bool runVecSTA(const std::string dir);
bool readNetsToIDB(const std::string dir);
@@ -45,7 +45,7 @@ class Vectorization

void initLog(std::string log_path = "");

void generateFeature(const std::string dir);
void generateFeature(const std::string dir, bool is_placement_mode = false, int sta_mode = 0);
};

} // namespace ivec

Loading…
Cancel
Save
Baidu
map