diff --git a/.clang-format b/.clang-format old mode 100644 new mode 100755 diff --git a/.clang-tidy b/.clang-tidy old mode 100644 new mode 100755 diff --git a/.dockerignore b/.dockerignore old mode 100644 new mode 100755 diff --git a/.gitee/ISSUE_TEMPLATE.en.md b/.gitee/ISSUE_TEMPLATE.en.md old mode 100644 new mode 100755 diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md old mode 100644 new mode 100755 diff --git a/.gitee/PULL_REQUEST_TEMPLATE.en.md b/.gitee/PULL_REQUEST_TEMPLATE.en.md old mode 100644 new mode 100755 diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.gitmodules b/.gitmodules old mode 100644 new mode 100755 diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/Dockerfile b/Dockerfile old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README-CN.md b/README-CN.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/src/evaluation/api/congestion_api.cpp b/src/evaluation/api/congestion_api.cpp index dfc5c8a9e..f1f865b60 100644 --- a/src/evaluation/api/congestion_api.cpp +++ b/src/evaluation/api/congestion_api.cpp @@ -232,7 +232,8 @@ std::string CongestionAPI::egrUnionMap(std::string stage, std::string rt_dir_pat std::map>> CongestionAPI::getEGRMap(std::string congestion_dir) { - return EVAL_CONGESTION_INST->getEGRMap(congestion_dir); + // return EVAL_CONGESTION_INST->getEGRMap(congestion_dir); + return EVAL_CONGESTION_INST->getDemandSupplyDiffMap(congestion_dir); } } // namespace ieval diff --git a/src/evaluation/src/module/congestion/congestion_eval.cpp b/src/evaluation/src/module/congestion/congestion_eval.cpp index 90e8fe692..fb8e231a5 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.cpp +++ b/src/evaluation/src/module/congestion/congestion_eval.cpp @@ -1093,4 +1093,106 @@ std::map>> CongestionEval::getEGRMap(s return egr_map; } +std::map>> CongestionEval::getDemandSupplyDiffMap(std::string congestion_dir) +{ + // 如果未指定目录,使用默认路径 + if (congestion_dir == "") { + congestion_dir = dmInst->get_config().get_output_path() + "/rt/rt_temp_directory"; + } + + setEGRDirPath(congestion_dir); + initEGR(); + destroyEGR(); + + // 构造early_router和supply_analyzer的完整路径 + std::string demand_dir = congestion_dir + "/early_router"; + std::string supply_dir = congestion_dir + "/supply_analyzer"; + + printf("demand_dir: %s\nsupply_dir: %s\n", demand_dir.c_str(), supply_dir.c_str()); + + // 用于存储最终的差值矩阵 + std::map>> diff_map; + // 临时存储demand和supply矩阵 + std::map>> demand_matrices; + std::map>> supply_matrices; + + // 读取demand矩阵 + std::filesystem::path demand_path(demand_dir); + for (const auto& entry : std::filesystem::directory_iterator(demand_path)) { + std::string filename = entry.path().filename().string(); + if (filename.find("demand_map_") == 0) { + // 提取层名 (AP, M1, M2等) + std::string layer_name = filename.substr(11, filename.length() - 15); + + // 读取文件内容 + std::ifstream file(entry.path()); + std::string line; + std::vector> matrix; + while (std::getline(file, line)) { + std::vector row; + std::istringstream iss(line); + std::string value; + while (std::getline(iss, value, ',')) { + row.push_back(std::stod(value)); + } + matrix.push_back(row); + } + demand_matrices[layer_name] = matrix; + } + } + + // 读取supply矩阵 + std::filesystem::path supply_path(supply_dir); + for (const auto& entry : std::filesystem::directory_iterator(supply_path)) { + std::string filename = entry.path().filename().string(); + if (filename.find("supply_map_") == 0) { + // 提取层名 (AP, M1, M2等) + std::string layer_name = filename.substr(11, filename.length() - 15); + + // 读取文件内容 + std::ifstream file(entry.path()); + std::string line; + std::vector> matrix; + while (std::getline(file, line)) { + std::vector row; + std::istringstream iss(line); + std::string value; + while (std::getline(iss, value, ',')) { + row.push_back(std::stod(value)); + } + matrix.push_back(row); + } + supply_matrices[layer_name] = matrix; + } + } + + // 计算差值矩阵 + for (const auto& [layer_name, demand_matrix] : demand_matrices) { + // 检查该层是否同时存在supply数据 + if (supply_matrices.find(layer_name) != supply_matrices.end()) { + const auto& supply_matrix = supply_matrices[layer_name]; + + // 确保矩阵尺寸相同 + if (demand_matrix.size() == supply_matrix.size() && + demand_matrix[0].size() == supply_matrix[0].size()) { + + std::vector> diff_matrix; + for (size_t i = 0; i < demand_matrix.size(); ++i) { + std::vector diff_row; + for (size_t j = 0; j < demand_matrix[i].size(); ++j) { + // 计算差值 + diff_row.push_back(demand_matrix[i][j] - supply_matrix[i][j]); + } + diff_matrix.push_back(diff_row); + } + diff_map[layer_name] = diff_matrix; + } else { + printf("Warning: Matrix size mismatch for layer %s\n", layer_name.c_str()); + } + } + } + + return diff_map; +} + } // namespace ieval \ No newline at end of file diff --git a/src/evaluation/src/module/congestion/congestion_eval.h b/src/evaluation/src/module/congestion/congestion_eval.h index 131ce9a6d..d504bb7d4 100644 --- a/src/evaluation/src/module/congestion/congestion_eval.h +++ b/src/evaluation/src/module/congestion/congestion_eval.h @@ -80,6 +80,7 @@ class CongestionEval void setEGRDirPath(std::string egr_dir_path); std::map>> getEGRMap(std::string congestion_dir); + std::map>> getDemandSupplyDiffMap(std::string congestion_dir); private: static CongestionEval* _congestion_eval; diff --git a/src/evaluation/src/util/init_sta.cc b/src/evaluation/src/util/init_sta.cc index 57d5ff457..229a8afe2 100644 --- a/src/evaluation/src/util/init_sta.cc +++ b/src/evaluation/src/util/init_sta.cc @@ -1039,6 +1039,8 @@ TimingWireGraph InitSTA::getTimingWireGraph() { TransType::kFall); } + LOG_FATAL_IF(!rc_net) << the_net->get_name() << " rc net is null."; + auto wire_topo = rc_net->getWireTopo(snk_node_name.c_str()); for (auto* wire_edge : wire_topo | std::ranges::views::reverse) { ieda::Stats stats2; diff --git a/src/large_model/src/graph/data_manager/lm_graph_dm.cpp b/src/large_model/src/graph/data_manager/lm_graph_dm.cpp index b1f5c8082..767be5291 100644 --- a/src/large_model/src/graph/data_manager/lm_graph_dm.cpp +++ b/src/large_model/src/graph/data_manager/lm_graph_dm.cpp @@ -145,9 +145,10 @@ bool LmGraphDataManager::buildGraphData() bg::get<1>(end_point), bg::get<2>(end_point), layout_layers); /// ignore same node - if (node1 != node2) { - lm_wire.add_path(node1, node2); - } + // if (node1 != node2) { + // lm_wire.add_path(node1, node2); + // } + lm_wire.add_path(node1, node2); #if debug_error if (i == 0) { bk_end = node2; diff --git a/src/large_model/src/graph/data_manager/lm_net_graph_gen.cc b/src/large_model/src/graph/data_manager/lm_net_graph_gen.cc index 944525b0c..b56297c77 100644 --- a/src/large_model/src/graph/data_manager/lm_net_graph_gen.cc +++ b/src/large_model/src/graph/data_manager/lm_net_graph_gen.cc @@ -78,12 +78,13 @@ bool LmNetGraphGenerator::isCornerCase(idb::IdbNet* idb_net) const return false; } - auto else_pins = idb_net->get_instance_pin_list()->get_pin_list(); - if (else_pins.size() != 1) { - return false; + auto* io_pin = io_pins.front(); + auto io_shapes = io_pin->get_port_box_list(); + if (io_shapes.empty()) { + return true; } - return true; + return false; } WireGraph LmNetGraphGenerator::buildCornerCaseGraph(idb::IdbNet* idb_net) const { @@ -347,12 +348,146 @@ WireGraph LmNetGraphGenerator::buildWireGraph(const TopoGraph& graph) const } } // post process + innerConnectivityCompletion(graph, wire_graph, point_to_vertex); buildVirtualWire(graph, wire_graph, point_to_vertex); - markPinVertex(graph, wire_graph, point_to_vertex); + markPinVertex(graph, wire_graph); reduceWireGraph(wire_graph); checkConnectivity(wire_graph); return wire_graph; } +void LmNetGraphGenerator::innerConnectivityCompletion(const TopoGraph& graph, WireGraph& wire_graph, + WireGraphVertexMap& point_to_vertex) const +{ + // Temporary structure to group the vertices by flatten shape + struct FlattenShape + { + int low_x; + int low_y; + int high_x; + int high_y; + + bool operator==(const FlattenShape& other) const + { + return low_x == other.low_x && low_y == other.low_y && high_x == other.high_x && high_y == other.high_y; + } + }; + + struct FlattenShapeHash + { + size_t operator()(const FlattenShape& shape) const + { + return std::hash()(shape.low_x) ^ std::hash()(shape.low_y) ^ std::hash()(shape.high_x) + ^ std::hash()(shape.high_y); + } + }; + + auto build_and_connect = [&](const LayoutDefPoint& start, const LayoutDefPoint& end) -> void { + if (!point_to_vertex.contains(start)) { + auto vertex = boost::add_vertex(wire_graph); + wire_graph[vertex].x = getX(start); + wire_graph[vertex].y = getY(start); + wire_graph[vertex].layer_id = getZ(start); + point_to_vertex[start] = vertex; + } + if (!point_to_vertex.contains(end)) { + auto vertex = boost::add_vertex(wire_graph); + wire_graph[vertex].x = getX(end); + wire_graph[vertex].y = getY(end); + wire_graph[vertex].layer_id = getZ(end); + point_to_vertex[end] = vertex; + } + // check edge exists + auto start_vertex = point_to_vertex[start]; + auto end_vertex = point_to_vertex[end]; + if (boost::edge(start_vertex, end_vertex, wire_graph).second) { + return; + } + auto [edge, inserted] = boost::add_edge(start_vertex, end_vertex, wire_graph); + if (inserted) { + wire_graph[edge].path.push_back({start, end}); + } + }; + // Build an R-tree to locate points within a shape + LayoutShapeManager shape_manager; + std::vector points; + for (auto& [point, vertex] : point_to_vertex) { + points.push_back(point); + } + for (size_t i = 0; i < points.size(); ++i) { + shape_manager.addShape(points[i], i); + } + + auto connectivity_complete = [&](const TopoGraphVertex& v) -> void { + auto* content = graph[v].content; + if (!content->is_pin) { + return; + } + auto* pin = dynamic_cast(content); + auto pin_shapes = pin->pin_shapes; + auto via_cuts = pin->via_cuts; + auto via_cuts_set = std::unordered_set(via_cuts.begin(), via_cuts.end()); + // Group pin shapes by (low_x, low_y, high_x, high_y), if the group has more than one shape, connect them + std::unordered_map, FlattenShapeHash> shape_map; + for (size_t i = 0; i < pin_shapes.size(); ++i) { + auto& shape = pin_shapes[i]; + auto low_x = getLowX(shape); + auto low_y = getLowY(shape); + auto high_x = getHighX(shape); + auto high_y = getHighY(shape); + shape_map[{low_x, low_y, high_x, high_y}].push_back(i); + } + // Check if the group has more than one shape, if so, further check the connectivity between the neighboring shapes + for (auto& [shape, indices] : shape_map) { + if (indices.size() < 2) { + continue; + } + std::vector flatten_shapes; + std::ranges::transform(indices, std::back_inserter(flatten_shapes), [&](size_t i) -> LayoutDefRect { return pin_shapes[i]; }); + // sort the shapes by layer, ascending + std::ranges::sort(flatten_shapes, + [&](const LayoutDefRect& lhs, const LayoutDefRect& rhs) -> bool { return getLowZ(lhs) < getLowZ(rhs); }); + // connect the neighboring shapes + for (size_t i = 0; i < flatten_shapes.size() - 1; ++i) { + auto low_shape = flatten_shapes[i]; + auto high_shape = flatten_shapes[i + 1]; + + auto low_point_ids = shape_manager.findIntersections(low_shape); + + if (!low_point_ids.empty()) { + std::ranges::for_each(low_point_ids, [&](size_t low_id) -> void { + auto low_point = points[low_id]; + auto high_point = LayoutDefPoint(getX(low_point), getY(low_point), getHighZ(high_shape)); + auto via_cut = LayoutDefRect(low_point, high_point); + if (via_cuts_set.find(via_cut) != via_cuts_set.end()) { + return; + } + via_cuts_set.insert(via_cut); + build_and_connect(low_point, high_point); + }); + continue; + } + + auto high_points = shape_manager.findIntersections(high_shape); + std::ranges::for_each(high_points, [&](size_t high_id) -> void { + auto high_point = points[high_id]; + auto low_point = LayoutDefPoint(getX(high_point), getY(high_point), getLowZ(low_shape)); + auto via_cut = LayoutDefRect(low_point, high_point); + if (via_cuts_set.find(via_cut) != via_cuts_set.end()) { + return; + } + via_cuts_set.insert(via_cut); + build_and_connect(low_point, high_point); + }); + } + } + // Update the pin's via cuts + pin->via_cuts = std::vector(via_cuts_set.begin(), via_cuts_set.end()); + }; + // Traverse all vertices + for (auto v : boost::make_iterator_range(boost::vertices(graph))) { + connectivity_complete(v); + } +} void LmNetGraphGenerator::buildVirtualWire(const TopoGraph& graph, WireGraph& wire_graph, WireGraphVertexMap& point_to_vertex) const { // for each pin and patch in TopoGraph @@ -475,7 +610,7 @@ void LmNetGraphGenerator::buildVirtualWire(const TopoGraph& graph, WireGraph& wi } }); } -void LmNetGraphGenerator::markPinVertex(const TopoGraph& graph, WireGraph& wire_graph, WireGraphVertexMap& point_to_vertex) const +void LmNetGraphGenerator::markPinVertex(const TopoGraph& graph, WireGraph& wire_graph) const { auto shape_manager = buildShapeManager(graph); // for each node in wire graph, if it's located in the pin shape, mark it as pin @@ -867,10 +1002,8 @@ std::vector> LmNetGraphGenerator::findByDijkstra(con // 2. build points graph by shortest distance (for find the minimum spanning tree/path) using PointGraph = boost::adjacency_list>; - using PointGraphVertex = boost::graph_traits::vertex_descriptor; using PointGraphEdge = boost::graph_traits::edge_descriptor; PointGraph point_graph; - std::unordered_map point_to_vertex_in_point_graph; for (size_t i = 0; i < points.size(); ++i) { for (size_t j = i + 1; j < points.size(); ++j) { auto p1 = points[i]; diff --git a/src/large_model/src/graph/data_manager/lm_net_graph_gen.hh b/src/large_model/src/graph/data_manager/lm_net_graph_gen.hh index 0d4100a14..93f13bfa7 100644 --- a/src/large_model/src/graph/data_manager/lm_net_graph_gen.hh +++ b/src/large_model/src/graph/data_manager/lm_net_graph_gen.hh @@ -196,11 +196,8 @@ class LayoutShapeManager LayoutShapeManager() {} ~LayoutShapeManager() {} - void addShape(const LayoutDefSeg& seg, const size_t& vertex_id) - { - LayoutDefRect box(seg.first, seg.second); - addShape(box, vertex_id); - } + void addShape(const LayoutDefPoint& point, const size_t& vertex_id) { addShape(LayoutDefRect(point, point), vertex_id); } + void addShape(const LayoutDefSeg& seg, const size_t& vertex_id) { addShape(LayoutDefRect(seg.first, seg.second), vertex_id); } void addShape(const LayoutDefRect& box, const size_t& vertex_id) { _rtree.insert(std::make_pair(box, vertex_id)); } std::vector findIntersections(const LayoutDefRect& box) const @@ -274,7 +271,6 @@ class LmNetGraphGenerator void initLayerMap(); WireGraph buildGraph(idb::IdbNet* idb_net) const; std::vector buildGraphs() const; - bool isCornerCase(idb::IdbNet* idb_net) const; WireGraph buildCornerCaseGraph(idb::IdbNet* idb_net) const; @@ -286,8 +282,9 @@ class LmNetGraphGenerator // Wire Graph WireGraph buildWireGraph(const TopoGraph& graph) const; + void innerConnectivityCompletion(const TopoGraph& graph, WireGraph& wire_graph, WireGraphVertexMap& point_to_vertex) const; void buildVirtualWire(const TopoGraph& graph, WireGraph& wire_graph, WireGraphVertexMap& point_to_vertex) const; - void markPinVertex(const TopoGraph& graph, WireGraph& wire_graph, WireGraphVertexMap& point_to_vertex) const; + void markPinVertex(const TopoGraph& graph, WireGraph& wire_graph) const; void reduceWireGraph(WireGraph& graph, const bool& retain_pin = true) const; bool hasCycleUtil(const WireGraph& graph, WireGraphVertex v, std::vector& visited, WireGraphVertex parent) const; bool hasCycle(const WireGraph& graph) const; diff --git a/src/large_model/src/layout/data_manager/lm_layout_init.cpp b/src/large_model/src/layout/data_manager/lm_layout_init.cpp index 5d32ca9a9..b47027925 100644 --- a/src/large_model/src/layout/data_manager/lm_layout_init.cpp +++ b/src/large_model/src/layout/data_manager/lm_layout_init.cpp @@ -39,9 +39,9 @@ void LmLayoutInit::init() initLayers(); initDie(); initTracks(); - initPDN(); - initInstances(); - initIOPins(); + // initPDN(); + // initInstances(); + // initIOPins(); initNets(); }