This commit is contained in:
Yell-walkalone 2025-02-08 18:20:23 +08:00
commit 42cbcc42e1
22 changed files with 259 additions and 22 deletions

0
.clang-format Normal file → Executable file
View File

0
.clang-tidy Normal file → Executable file
View File

0
.dockerignore Normal file → Executable file
View File

0
.gitee/ISSUE_TEMPLATE.en.md Normal file → Executable file
View File

0
.gitee/ISSUE_TEMPLATE.zh-CN.md Normal file → Executable file
View File

0
.gitee/PULL_REQUEST_TEMPLATE.en.md Normal file → Executable file
View File

0
.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md Normal file → Executable file
View File

0
.gitignore vendored Normal file → Executable file
View File

0
.gitmodules vendored Normal file → Executable file
View File

0
CMakeLists.txt Normal file → Executable file
View File

0
Dockerfile Normal file → Executable file
View File

0
LICENSE Normal file → Executable file
View File

0
README-CN.md Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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;

View File

@ -39,9 +39,9 @@ void LmLayoutInit::init()
initLayers();
initDie();
initTracks();
initPDN();
initInstances();
initIOPins();
// initPDN();
// initInstances();
// initIOPins();
initNets();
}