void HyperedgeRerouter::performRerouting(void) { COLA_ASSERT(m_router != NULL); m_new_junctions_vector.clear(); m_new_junctions_vector.resize(count()); m_new_connectors_vector.clear(); m_new_connectors_vector.resize(count()); #ifdef HYPEREDGE_DEBUG double minX = LIMIT; double minY = LIMIT; double maxX = -LIMIT; double maxY = -LIMIT; VertInf *curr = m_router->vertices.connsBegin(); while (curr) { Point p = curr->point; reduceRange(p.x); reduceRange(p.y); if (p.x > -LIMIT) { minX = std::min(minX, p.x); } if (p.x < LIMIT) { maxX = std::max(maxX, p.x); } if (p.y > -LIMIT) { minY = std::min(minY, p.y); } if (p.y < LIMIT) { maxY = std::max(maxY, p.y); } curr = curr->lstNext; } minX -= 8; minY -= 8; maxX += 8; maxY += 8; FILE *fp = fopen("hyperedge-debug.svg", "w"); fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); // width=\"100%%\" height=\"100%%\" fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY); fprintf(fp, "<defs>\n"); fprintf(fp, "<style type=\"text/css\" ><![CDATA[\n"); fprintf(fp, ".shape { stroke-width: 1px; stroke: black; fill: blue; stroke-opacity: 0.50; fill-opacity: 0.50; }\n"); fprintf(fp, ".graph { opacity: 0; fill: none; stroke: red; stroke-width: 1px; }\n"); fprintf(fp, ".forest { fill: none; stroke: purple; stroke-width: 1px; }\n"); fprintf(fp, ".hyperedge { fill: none; stroke-width: 1px; }\n"); fprintf(fp, "]]></style>\n"); fprintf(fp, "</defs>\n"); fprintf(fp, "<g inkscape:groupmode=\"layer\" " "inkscape:label=\"ShapesRect\">\n"); ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin(); while (obstacleIt != m_router->m_obstacles.end()) { Obstacle *obstacle = *obstacleIt; bool isShape = (NULL != dynamic_cast<ShapeRef *> (obstacle)); if ( ! isShape ) { // Don't output obstacles here, for now. ++obstacleIt; continue; } Box bb = obstacle->routingBox(); fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" " "height=\"%g\" class=\"shape\" />\n", obstacle->id(), bb.min.x, bb.min.y, bb.max.x - bb.min.x, bb.max.y - bb.min.y); // shapeContainsEndpointVertex(obstacle) ? "style=\"fill: green;\"" : ""); ++obstacleIt; } fprintf(fp, "</g>\n"); fprintf(fp, "<g inkscape:groupmode=\"layer\" " "id=\"graph\" style=\"display: none;\" " "inkscape:label=\"OrthogVisGraph\">\n"); EdgeInf *finish = m_router->visOrthogGraph.end(); for (EdgeInf *t = m_router->visOrthogGraph.begin(); t != finish; t = t->lstNext) { std::pair<Point, Point> ptpair = t->points(); Point p1 = ptpair.first; Point p2 = ptpair.second; reduceRange(p1.x); reduceRange(p1.y); reduceRange(p2.x); reduceRange(p2.y); // std::pair<VertID, VertID> ids = t->ids(); // (ids.first.isConnPt() || ids.second.isConnPt()) ? "style=\"stroke: green\" " : "" fprintf(fp, "<path class=\"graph\" d=\"M %g %g L %g %g\" " "%s />\n", p1.x, p1.y, p2.x, p2.y, "" ); } fprintf(fp, "</g>\n"); #endif // For each hyperedge... const size_t num_hyperedges = count(); for (size_t i = 0; i < num_hyperedges; ++i) { // Execute the MTST method to find good junction positions and an // initial path. A hyperedge tree will be build for the new route. JunctionHyperEdgeTreeNodeMap hyperEdgeTreeJunctions; MinimumTerminalSpanningTree mtst(m_router, m_terminal_vertices_vector[i], &hyperEdgeTreeJunctions); #ifdef HYPEREDGE_DEBUG mtst.setDebuggingOutput(fp, i); #endif // The older MTST construction method (faster, worse results). //mtst.constructSequential(); // The preferred MTST construction method. // Slightly slower, better quality results. mtst.constructInterleaved(); HyperEdgeTreeNode *treeRoot = mtst.rootJunction(); COLA_ASSERT(treeRoot); // Fill in connector information and join them to junctions of endpoints // of original connectors. treeRoot->addConns(NULL, m_router, m_deleted_connectors_vector[i], NULL); // Output the list of new junctions and connectors from hyperedge tree. treeRoot->listJunctionsAndConnectors(NULL, m_new_junctions_vector[i], m_new_connectors_vector[i]); // Write paths from the hyperedge tree back into individual // connector routes. for (size_t pass = 0; pass < 2; ++pass) { treeRoot->writeEdgesToConns(NULL, pass); } // Tell the router that we are deleting the objects used for the // previous path for the hyperedge. for (ConnRefList::iterator curr = m_deleted_connectors_vector[i].begin(); curr != m_deleted_connectors_vector[i].end(); ++curr) { // Clear visibility assigned for connection pins. (*curr)->assignConnectionPinVisibility(false); m_router->deleteConnector(*curr); } for (JunctionRefList::iterator curr = m_deleted_junctions_vector[i].begin(); curr != m_deleted_junctions_vector[i].end(); ++curr) { m_router->deleteJunction(*curr); } } // Clear the input to this class, so that new objects can be registered // for rerouting for the next time that transaction that is processed. m_terminals_vector.clear(); m_root_junction_vector.clear(); // Free temporarily added vertices. for (VertexList::iterator curr = m_added_vertices.begin(); curr != m_added_vertices.end(); ++curr) { (*curr)->removeFromGraph(); m_router->vertices.removeVertex(*curr); delete *curr; } m_added_vertices.clear(); #ifdef HYPEREDGE_DEBUG fprintf(fp, "</svg>\n"); fclose(fp); #endif }
void buildOrthogonalChannelInfo(Router *router, const size_t dim, ShiftSegmentList& segmentList) { if (segmentList.empty()) { // There are no segments, so we can just return now. return; } // Do a sweep to determine space for shifting segments. size_t altDim = (dim + 1) % 2; const size_t n = router->m_obstacles.size(); const size_t cpn = segmentList.size(); // Set up the events for the sweep. size_t totalEvents = 2 * (n + cpn); Event **events = new Event*[totalEvents]; unsigned ctr = 0; ObstacleList::iterator obstacleIt = router->m_obstacles.begin(); for (unsigned i = 0; i < n; i++) { Obstacle *obstacle = *obstacleIt; JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle); if (junction && ! junction->positionFixed()) { // Junctions that are free to move are not treated as obstacles. ++obstacleIt; totalEvents -= 2; continue; } Box bBox = obstacle->routingBox(); Point min = bBox.min; Point max = bBox.max; double mid = min[dim] + ((max[dim] - min[dim]) / 2); Node *v = new Node(obstacle, mid); events[ctr++] = new Event(Open, v, min[altDim]); events[ctr++] = new Event(Close, v, max[altDim]); ++obstacleIt; } for (ShiftSegmentList::iterator curr = segmentList.begin(); curr != segmentList.end(); ++curr) { const Point& lowPt = (*curr)->lowPoint(); const Point& highPt = (*curr)->highPoint(); COLA_ASSERT(lowPt[dim] == highPt[dim]); COLA_ASSERT(lowPt[altDim] < highPt[altDim]); Node *v = new Node(*curr, lowPt[dim]); events[ctr++] = new Event(SegOpen, v, lowPt[altDim]); events[ctr++] = new Event(SegClose, v, highPt[altDim]); } qsort((Event*)events, (size_t) totalEvents, sizeof(Event*), compare_events); // Process the sweep. // We do multiple passes over sections of the list so we can add relevant // entries to the scanline that might follow, before process them. NodeSet scanline; double thisPos = (totalEvents > 0) ? events[0]->pos : 0; unsigned int posStartIndex = 0; unsigned int posFinishIndex = 0; for (unsigned i = 0; i <= totalEvents; ++i) { // If we have finished the current scanline or all events, then we // process the events on the current scanline in a couple of passes. if ((i == totalEvents) || (events[i]->pos != thisPos)) { posFinishIndex = i; for (int pass = 2; pass <= 4; ++pass) { for (unsigned j = posStartIndex; j < posFinishIndex; ++j) { processShiftEvent(scanline, events[j], dim, pass); } } if (i == totalEvents) { // We have cleaned up, so we can now break out of loop. break; } thisPos = events[i]->pos; posStartIndex = i; } // Do the first sweep event handling -- building the correct // structure of the scanline. const int pass = 1; processShiftEvent(scanline, events[i], dim, pass); } COLA_ASSERT(scanline.size() == 0); for (unsigned i = 0; i < totalEvents; ++i) { delete events[i]; } delete [] events; }
void HyperedgeRerouter::performRerouting(void) { COLA_ASSERT(m_router != NULL); m_new_junctions_vector.clear(); m_new_junctions_vector.resize(count()); m_new_connectors_vector.clear(); m_new_connectors_vector.resize(count()); #ifdef DEBUGHANDLER if (m_router->debugHandler()) { std::vector<Box> obstacleBoxes; ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin(); while (obstacleIt != m_router->m_obstacles.end()) { Obstacle *obstacle = *obstacleIt; JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle); if (junction && ! junction->positionFixed()) { // Junctions that are free to move are not treated as obstacles. ++obstacleIt; continue; } Box bbox = obstacle->routingBox(); obstacleBoxes.push_back(bbox); ++obstacleIt; } m_router->debugHandler()->updateObstacleBoxes(obstacleBoxes); } #endif // For each hyperedge... const size_t num_hyperedges = count(); for (size_t i = 0; i < num_hyperedges; ++i) { if (m_terminal_vertices_vector[i].empty()) { // Invalid hyperedge, ignore. continue; } // Execute the MTST method to find good junction positions and an // initial path. A hyperedge tree will be built for the new route. JunctionHyperedgeTreeNodeMap hyperedgeTreeJunctions; MinimumTerminalSpanningTree mtst(m_router, m_terminal_vertices_vector[i], &hyperedgeTreeJunctions); // The older MTST construction method (faster, worse results). //mtst.constructSequential(); // The preferred MTST construction method. // Slightly slower, better quality results. mtst.constructInterleaved(); HyperedgeTreeNode *treeRoot = mtst.rootJunction(); COLA_ASSERT(treeRoot); // Fill in connector information and join them to junctions of endpoints // of original connectors. treeRoot->addConns(NULL, m_router, m_deleted_connectors_vector[i], NULL); // Output the list of new junctions and connectors from hyperedge tree. treeRoot->listJunctionsAndConnectors(NULL, m_new_junctions_vector[i], m_new_connectors_vector[i]); // Write paths from the hyperedge tree back into individual // connector routes. for (size_t pass = 0; pass < 2; ++pass) { treeRoot->writeEdgesToConns(NULL, pass); } // Tell the router that we are deleting the objects used for the // previous path for the hyperedge. for (ConnRefList::iterator curr = m_deleted_connectors_vector[i].begin(); curr != m_deleted_connectors_vector[i].end(); ++curr) { // Clear visibility assigned for connection pins. (*curr)->assignConnectionPinVisibility(false); m_router->deleteConnector(*curr); } for (JunctionRefList::iterator curr = m_deleted_junctions_vector[i].begin(); curr != m_deleted_junctions_vector[i].end(); ++curr) { m_router->deleteJunction(*curr); } } // Clear the input to this class, so that new objects can be registered // for rerouting for the next time that transaction that is processed. m_terminals_vector.clear(); m_root_junction_vector.clear(); // Free temporarily added vertices. for (VertexList::iterator curr = m_added_vertices.begin(); curr != m_added_vertices.end(); ++curr) { (*curr)->removeFromGraph(); m_router->vertices.removeVertex(*curr); delete *curr; } m_added_vertices.clear(); }