mirror of https://gitee.com/oscc-project/iEDA.git
merge
This commit is contained in:
commit
42cbcc42e1
|
|
@ -232,7 +232,8 @@ std::string CongestionAPI::egrUnionMap(std::string stage, std::string rt_dir_pat
|
|||
|
||||
std::map<std::string, std::vector<std::vector<int>>> 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
|
||||
|
|
|
|||
|
|
@ -1093,4 +1093,106 @@ std::map<std::string, std::vector<std::vector<int>>> CongestionEval::getEGRMap(s
|
|||
return egr_map;
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<std::vector<int>>> 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<std::string, std::vector<std::vector<int>>> diff_map;
|
||||
// 临时存储demand和supply矩阵
|
||||
std::map<std::string, std::vector<std::vector<int>>> demand_matrices;
|
||||
std::map<std::string, std::vector<std::vector<int>>> 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<std::vector<int>> matrix;
|
||||
while (std::getline(file, line)) {
|
||||
std::vector<int> 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<std::vector<int>> matrix;
|
||||
while (std::getline(file, line)) {
|
||||
std::vector<int> 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<std::vector<int>> diff_matrix;
|
||||
for (size_t i = 0; i < demand_matrix.size(); ++i) {
|
||||
std::vector<int> 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
|
||||
|
|
@ -80,6 +80,7 @@ class CongestionEval
|
|||
void setEGRDirPath(std::string egr_dir_path);
|
||||
|
||||
std::map<std::string, std::vector<std::vector<int>>> getEGRMap(std::string congestion_dir);
|
||||
std::map<std::string, std::vector<std::vector<int>>> getDemandSupplyDiffMap(std::string congestion_dir);
|
||||
|
||||
private:
|
||||
static CongestionEval* _congestion_eval;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<int>()(shape.low_x) ^ std::hash<int>()(shape.low_y) ^ std::hash<int>()(shape.high_x)
|
||||
^ std::hash<int>()(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<LayoutDefPoint> 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<LayoutPin*>(content);
|
||||
auto pin_shapes = pin->pin_shapes;
|
||||
auto via_cuts = pin->via_cuts;
|
||||
auto via_cuts_set = std::unordered_set<LayoutDefRect, LayoutDefRectHash, LayoutDefRectEqual>(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<FlattenShape, std::vector<size_t>, 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<LayoutDefRect> 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<LayoutDefRect>(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<std::vector<LayoutDefPoint>> LmNetGraphGenerator::findByDijkstra(con
|
|||
// 2. build points graph by shortest distance (for find the minimum spanning tree/path)
|
||||
using PointGraph
|
||||
= boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, boost::property<boost::edge_weight_t, int>>;
|
||||
using PointGraphVertex = boost::graph_traits<PointGraph>::vertex_descriptor;
|
||||
using PointGraphEdge = boost::graph_traits<PointGraph>::edge_descriptor;
|
||||
PointGraph point_graph;
|
||||
std::unordered_map<LayoutDefPoint, PointGraphVertex, LayoutDefPointHash, LayoutDefPointEqual> 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];
|
||||
|
|
|
|||
|
|
@ -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<size_t> findIntersections(const LayoutDefRect& box) const
|
||||
|
|
@ -274,7 +271,6 @@ class LmNetGraphGenerator
|
|||
void initLayerMap();
|
||||
WireGraph buildGraph(idb::IdbNet* idb_net) const;
|
||||
std::vector<WireGraph> 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<bool>& visited, WireGraphVertex parent) const;
|
||||
bool hasCycle(const WireGraph& graph) const;
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ void LmLayoutInit::init()
|
|||
initLayers();
|
||||
initDie();
|
||||
initTracks();
|
||||
initPDN();
|
||||
initInstances();
|
||||
initIOPins();
|
||||
// initPDN();
|
||||
// initInstances();
|
||||
// initIOPins();
|
||||
|
||||
initNets();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue