// -*- C++ -*- namespace Kite { /*! \class RoutingEvent * \brief Manage TrackSegment routing requests. * * The \RoutingEvent is the workhorse of Kite. A \RoutingEvent is * associated to one \TrackSegment. One \TrackSegment could be * associated to many \RoutingEvent in the queue, but only one * of those is active (marked as unprocessed). * * \see ClassManipulator. * * \section secProcessAlgorithm Description of the process() method * \code void RoutingEvent::process () { if ( isProcessed() ) return; setProcessed (); incRipupCount (); if ( getRipupCount() > MAX_RIPUP_COUNT ) { // We are *not* in ripup mode. // The event's segment has to be topologically modified. modifyTopology ( _segment ); } else { // We are in ripup mode. // Other overlaping segments are to be removeds/pusheds. It can result in // segment breaking *if* other segment came from an already routed GCell. // optimal, constraint, perpandicular. computeAllIntervals (); // Find & order all candidates Tracks. candidates = computeCostOnCandidateTracks (); sort ( candidates ); if ( candidates[0].isFree() ) { // Case -A.1- "Free Track". candidate[0].insert ( _segment ); } else if ( candidates[0].isSoftOverlap() || candidates[0].isHardOverlap() ) { // Case -A.2- "Soft Overlap". // Case -A.3- "Hard Overlap". for ( size_t i=0 ; i<candidates.size() ; i++ ) { if ( candidates[0].insertInTrack ( _segment ) ) { break; } } } else { // Case -B- "Infinite Cost". // Attention: meaning's changed, *infinite* only in case of // conflict with a *fixed* other segment. modifyTopology ( _segment ); } } // Restore Track coherency before processing any other event. Session::revalidate (); } \endcode * \section secRoutingIntervalToDo ToDo * * <ul> * <li>New \c isLocal() method on \TrackSegment. Tells if the \TrackSegment * is associated only to local AutoSegment. * <li>Increase the overlap cost of a \TrackSegment from an already routed * GCell routing set. * </ul> * * * \section secRoutingEventInterval The various intervals of a RoutingEvent * * The three Intervals controlling a RoutingEvent : all those intervals * defines the track range in which the \TrackSegment could be inserted. * <ul> * <li>The <i>optimal</i> interval : where the \Net wirelength will be * minimal (comes from \c Katabatic::AutoSegment). * <li>The <i>constraint</i> interval : the interval outside of which * the \Net connexity would be broken. This is the bigger interval * but it must be strictly respected (also comes from * \c Katabatic::AutoSegment). * <li>The <i>perpandicular</i> interval : for each perpandicular * \TrackSegment connected, the intersection of the free interval * around them in their track. * * It is important to note that the \TrackSegment overlaping in the * target track is not removed from the track. It is it's perpandiculars * which are, along with a modification of theirs left axis weight and/or * right axis weight. * * Second remark: no overlap will be created (due to the non-removal of * overlaping \TrackSegments) because the insertion is delayed in case * of overlap. * </ul> * The perpandicular interval comes from perpandicular constraints on \TrackSegment * of the <i>same</i> \c Net. The left/right axis weights comes from requests of * <i>other</i> \c Nets. * * \image html RoutingEvent-1.png "RoutingEvent Intervals" * \image latex RoutingEvent-1.pdf "RoutingEvent Intervals" width=0.6\textwidth * * Example of perpandicular interval computation : * * \image html RoutingEvent-2.png "Perpandicular Interval" * \image latex RoutingEvent-2.pdf "Perpandicular Interval" * * * \section secRoutingEventRules Rules governing RoutingEvents * * \RoutingEvent respect the following rules: * <ul> * <li>A \TrackSegment can only be displaced by it's associated \RoutingEvent. * <li>Corollary: the only \TrackSegment displaced while processing a * \RoutingEvent is the one associated to the event. * <li>Conflicts occurs between the \RoutingEvent \TrackSegment and already * placed others \TrackSegment. * * The conflict can be solved by displacing/modifying <i>others</i> * \TrackSegment or by modifying the to be inserted one. In the later * case, the newly created or modified \TrackSegment are (re)scheduleds * <i>before</i> the would be inserted. * <li>Conflicting \TrackSegments are only removed from their \Track * but their axis remains unchanged. Movement requests are passed * through increase of the left/right axis weights, if needed. * <li>\TrackSegment are inserted only, and only if there is enough free space. * That is, if any kind of overlap occurs, it is <i>not</i> inserted * but <i>rescheduled</i>. The blocking \TrackSegments are then * rescheduled <i>after</i> the current one. * <li>Each \RoutingEvent processing takes place inside a one atomic * Session. That is, the coherency of the data-base is restored * immediatly afterward (both Kite & Katabatic). * </ul> * * \remark Be very careful to distinguish between Session commands, which affects * \Track and \TrackSegment insertion/update/removal and schedule/re-schedule * events, which relates to the negociation algorithm. * * Re-ordering rules: * <ol> * <li>In normal mode, that is, no maximum ripup has been reached, the * blocking <i>other</i> \TrackSegment are removed and the current * is rescheduled <i>before</i> them. * <li>In maximum ripup mode, some \TrackSegment has to give way. * <ul> * <li>If the current one is modified, it must be rescheduled <i>after</i> * it's modified bits are rescheduleds. * <li>If <i>others</i> are modifieds they must be rescheduled <i>after</i> * the current one (so it will grabs the place). * </ul> * </ol> * * * \section secRoutingEventCycle RoutingEvent life cycle * * As an active \RoutingEvent is associated with one and only one \TrackSegment * we can talk indeferently of \RoutingEvent lifecycle or \TrackSegment * lifecycle. * * Below is the ordered list of states that a \RoutingEvent could be in. * The order correspond to increasing level of slackening/freedom. * Transition between states occurs each time a maximum ripup is reached. * * <table> * <tr> * <td align="center"> \b Id </td> * <td align="center">\b Type</td> * <td align="center"> \b Local </td> * <td align="center"> \b Global </td> * <td align="center">\b Action</td> * </tr> * <tr> * <td align="center">\e 1</td> * <td align="center">\c Minimize</td> * <td align="center">\e yes</td> * <td align="center">\e no</td> * <td>try to fit into a hole</td> * </tr> * <tr> * <td align="center">\e 2</td> * <td align="center">\c DogLeg</td> * <td align="center">\e yes</td> * <td align="center">\e no</td> * <td>Dogleg : analyse overlap and try to solve it by breaking (self)</td> * </tr> * <tr> * <td align="center">\e 3</td> * <td align="center">\c Desalignate</td> * <td align="center">\e yes</td> * <td align="center">\e yes</td> * <td>on a set of alignated \TrackSegment, suppress the * alignment constraints, thus making then independants * </td> * </tr> * <tr> * <td align="center">\e 4</td> * <td align="center">\c Slacken</td> * <td align="center">\e yes</td> * <td align="center">\e yes</td> * <td>if the target/source constraint is less than the * GCell, adds perpandicular straps to free the \TrackSegment. * This occurs to free from terminal constraints * </td> * </tr> * <tr> * <td align="center">\e 5</td> * <td align="center">\c ConflictSolve1</td> * <td align="center">\e yes</td> * <td align="center">\e yes</td> * <td>try to find in the history a reccurent dislodger, * and break (self) to accomodate it * </td> * </tr> * <tr> * <td align="center">\e 6</td> * <td align="center">\c ConflictSolve2</td> * <td align="center">\e no</td> * <td align="center">\e yes</td> * <td>try to find a Track on which we can dislodge * an other \TrackSegment * </td> * </tr> * <tr> * <td align="center">\e 7</td> * <td align="center">\c MoveUp</td> * <td align="center">\e no</td> * <td align="center">\e yes</td> * <td>try to go on upper layer. * </td> * </tr> * <tr> * <td align="center">\e 8</td> * <td align="center">\c Unimplemented</td> * <td align="center">\e no</td> * <td align="center">\e yes</td> * <td>we failed to place this \TrackSegment * </td> * </tr> * </table> * * * \section secManageMaximumRipup Managing the maximum ripup case * \code bool State::manageMaximumRipup () { bool success = false; if ( !_segment->isGlobal() ) { // Candidates Tracks (ignore optimal & perpandiculars). candidates = computeAllIntervals (); overlap = _segment->getInterval(); for ( size_t i=0 ; i<candidates.size() ; i++ ) { others = otherSegmentsConflicts(candidates[i]); // Select Track with only one conflicting other. if ( others.size() == 1 ) { // Local vs. Local => reject. // Local vs. Terminal => reject. if ( others[0]->isLocal() || others[0]->isTerminal() ) continue; // Local vs. Global (not routed yet). if ( others[i]->getOrder() >= _segment->getOrder() ) { success = modifyTopology(others[0]); break; } // Local vs. Global (already routed). success = relax(_others[0],overlap); if ( success ) break; } } } if ( !success ) { // Global vs. Local. // Failed Local vs. Any. success = modifyTopology(_segment); } return success; } \endcode * * * \section secModifyTopology Description of the modifyTopology() method * \code bool Manipulator::modifyTopology ( TrackSegment* segment ) { bool success = false; if ( segment->isLocal() ) { if ( segment->canMinimize() { segment->minimize(); success = true; } if ( segment->canDogLeg() ) { // Case -C.4- "Self Relax". segment->makeDogLeg(); success = true; } } else if ( segment->canDesalignate() ) { // Case -C.5- "Desalignate". segment->desalignate(); success = true; } else if ( segment->canSlacken() ) { // Case -C.6- "Slacken". segment->slacken(); success = true; } else { RipupHistory* history = RipupHistory(segment); GCell* dogLegGCell = history.getDogLegGCell(); if ( dogLegGCell ) { if ( segment->canDogLegAt(dogLegGCell) ) { segment->makeDogLeg(dogLegGCell) success = true; } } else { // Dislodgers seems to far in ripup history. // Recheck the Track, maybe they have vanish. Track* track = getTrack(segment); if ( track->getFreeInterval(segment) ) { track.insert ( segment ); success = true; } } } if ( segment->canMoveUp() ) { segment->moveUp (); success = true; } if ( success ) { resetRipupCount(segment); } else { cerr << "[UNIMPLEMENTED] " << segment << endl; } return success; } \endcode * * * \section secHardSoftOverlap Hard and soft overlap * * Schematic execution of a \RoutingEvent leading to a set aside. * <ol> * <li>The scheduler try to place the \TrackSegment on top of the * event queue, calling process(). * <li>There is a soft overlap on the best candidate track, a set * aside is issued. * <li>Each \TrackSegment in conflict in the candidate track has the * \RoutingEvent bounds of it's perpandicular \TrackSegment modificated * according to the free space requested through setLeftBound() or setRightBound(). * <li>If a perpandicular is already in a \Track is removed from it and scheduled for * immediate re-routing (it's event level is increased so it pops * out immediately from the queue). * <li>If the perpandicular is not routed yet, we are done. * * Note that this technique of modificating a \RoutingEvent yet to come is * kind a like seeing the future... * </ol> * * \image html RoutingEvent-3.png "Set aside schematic" * \image latex RoutingEvent-3.pdf "Set aside schematic" * * * \section setDetructionStrategy Destruction Strategy * * \RoutingEvent are not destroyed as soon as they have been processed by * the scheduler. Instead, they are stored in the historical queue. * They are two reasons for that behavior : * <ul> * <li>\RoutingEvent are used to store algorithmic informations that * must persist until the negociation algorithm have fully * completed (<i>bound</i> interval in particular). * <li>When ripup phases takes place and maximum ripup count is * reached, the history can be used to find the whole set of * \TrackSegment in conflict an made an educated guess about * which one must be relaxed. * </ul> * * \important This is the history queue which is responsible for freeing all the * \RoutingEvent in his destructor. * * * \section secRoutingEventCase Routing Event actions * * <ul> * <li><b>Free Track Case</b> * * There is a sufficent free space in the candidate \Track to insert the * \TrackSegment. The \TrackSegment is inserted. * * \important This is the only way for a \TrackSegment to be inserted into a \Track. * * \image html RoutingEvent-10.png * \image latex RoutingEvent-10.pdf * * * <li><b>Soft Overlap Case</b> * * Already inserted \TrackSegment <b>a</b> & <b>b</b> could be shrunk * to make place for \TrackSegment <b>c</b>. Parallel overlaping \TrackSegment * are not removed, their perpandiculars are with updated left/right axis weight. * * The <b>a</b> perpandicular belongs the same GCell routing set so it * is removed from is \Track to be displaced. * * The <b>b</b> perdandicular belongs to a more prioritary GCell routing * set, which has therefore be placed earlier so it can't be removed. * Instead it is broken. * * \image html RoutingEvent-11.png * \image latex RoutingEvent-11.pdf * * * <li><b>Hard Overlap Case</b> * * No way to shrunk overlaping \TrackSegment to make place for <b>c</b>. * All parallel overlaping \TrackSegments must be removeds to be displaced * on other \Tracks. * * The <b>a</b> parallel belongs to a more prioritary GCell routing set * so it can be removed, it is therefore broken. * * The <b>b</b> parallel belongs the same GCell routing set so it can be * removed to be displaced. * * \image html RoutingEvent-12.png * \image latex RoutingEvent-12.pdf * * * <li><b>Self Relax</b> * * Instead of trying to displace overlaping \TrackSegments we break the * current one. * * \image html RoutingEvent-13.png * \image latex RoutingEvent-13.pdf * * * <li><b>Self Desalignate</b> * * Instead of trying to displace overlaping \TrackSegments we desalignate * it's components (by supressing alignement constraints on it's * AutoContacts). We do not create new Katabatic components but new * \TrackSegments will appears. * * \image html RoutingEvent-14.png * \image latex RoutingEvent-14.pdf * * * <li><b>Self Slacken</b> * * Instead of trying to displace overlaping \TrackSegments we slacken * the current one. This is different than desalignate because we create * new Katabatic component to relax any AutoContact transmitted constraints. * This operation is most likely to be applied on \TrackSegments that are * directly connecteds to terminals. * * \image html RoutingEvent-15.png * \image latex RoutingEvent-15.pdf * * </ul> */ /*! \function bool RoutingEvent::isProcessed () const; * \return \true if this event has already been processed. * * \remark Note that inside a _setAside() a \RoutingEvent can be re-posted for * a given \TrackSegment which has been processed yet. This can lead * to two or more \RoutingEvent in the queue (as we cannot easily remove * a \RoutingEvent already in the queue). We need this new \RoutingEvent * because we want to reschedule with a new priority/slack. * As we cannot remove the previous \RoutingEvent, we mark it as * processed for it to be ignored by the scheduler. */ /*! \function TrackSegment* RoutingEvent::getSegment () const; * \Return The associated and unique \TrackSegment. */ /*! \function unsigned long RoutingEvent::getPriority () const; * \Return The second criterion used to sort \RoutingEvents in the negociation queue. * Currently, it is the <i>area</i> of the associated \TrackSegment, which in * turn return the <i>slack</i> (not a very fortunate choice of name...). */ /*! \function unsigned int RoutingEvent::getEventLevel () const; * \Return The first criterion used to sort \RoutingEvents in the negociation queue. * It is used to re-schedule a \RoutingEvent and make the new event be * processed <i>before</i> the original one, which is marked as * <i>processed</i> to be ignored. * * \see setEventLevel(). */ /*! \function RoutingEvent* RoutingEvent::getClone () const; * \Return An exact copy of the current \RoutingEvent. */ /*! \function RoutingEvent* RoutingEvent::reschedule ( RoutingEventQueue& queue ); * \param queue The \RoutingEvent queue. * \return The rescheduled \RoutingEvent. May be \NULL if it cannot be rescheduled. */ /*! \function void RoutingEvent::setProcessed ( bool state=true ); * \param state The state into which the event is to be put. * * Mark the event as processed. This arises in two cases : * <ul> * <li>The event has really been processed by the process() member * function. * <li>There has been a fork from this event and it has been * superseded by a newly rescheduled one, so we have to * invalidate this one. * </ul> */ /*! \function void RoutingEvent::setEventLevel ( unsigned int level ); * \param level The new event level. * * \see getEventLevel(). */ /*! \function void RoutingEvent::process ( RoutingEventQueue& queue, RoutingEventHistory& history ); * \param queue The event queue from the negociate algorithm. * \param history The event history. * * Perform all the operations shared by all \RoutingEvent classes then * calls the virtual _subProcess() functions. * * Shared operations are : * <ol> * <li>Invalidating all perpandicular \TrackSegments. * <li>Computing the free interval allowed by the free intervals * in perpandicular \Tracks holding the perpandicular \TrackSegments. * <li>Merging in the various constraints intervals : from the * \TrackSegment itself, from the free intervals in the * perpandicular \Tracks and from the \RoutingEvent bound * constraints. * <li>Finding the candidate \Tracks for the \RoutingEvent, * using \c Track_Spiral \Collection. * </ol> * The results of the shared operation are passed to derived classes * trough the \c State internal structure. */ /* \function bool RoutingEvent::_setAside ( Track* track, size_t begin, size_t end, Net* net, Interval interval, RoutingEventQueue& queue ); * \param track The track in wich to make free space. * \param begin The index of the first overlaping TrackSegment. * \param end The index of the last overlaping TrackSegment. * \param net The net for which we want to insert a TrackSegment. * \param interval The interval which must be made empty. * \param queue The queue of RoutingEvent. * * Manage the case of <i>soft overlap</i>. Create or enlarge a free space * in \c track so it can contain the requested \interval. <code>[begin:end]</code> defines * the range of indexes of overlaping \TrackSegment in \c track. * Displace TrackSegment that are <b>perpandicular</b> to those overlaping, * remove them from their \c Track if needed and issue an associated \RoutingEvent * with an updated bound constraint. Note that the overlaping \TrackSegment * themselves are <em>not</em> removed from the \c track. * * A note on implementation : * <ul> * <li>\c data1 : the DataNegociate of the to be inserted \TrackSegment. * <li>\c segment2 : the current overlaping \TrackSegment (from \c begin * to \c end). * <li>\c data2 : the DataNegociate of the overlaping \TrackSegment. * <li>\c segment3 : a \TrackSegment perpandicular to \c segment2. * </ul> */ /* \function void RoutingEvent::_ripup ( Track* track, Net* net, Interval interval, size_t begin, size_t end, RoutingEventQueue& queue ); * \param track The track in wich to make free space. * \param net The net for which we want to insert a TrackSegment. * \param interval The interval which must be made empty. * \param begin The index of the first overlaping TrackSegment. * \param end The index of the last overlaping TrackSegment. * \param queue The queue of RoutingEvent. * * Manage the case of <i>hard overlap</i>, that is bluntly remove * any \TrackSegment overlaping \interval. Issue both a remove event * (to \c Session) and a \RoutingEvent to re-process the dislodged * \TrackSegment. */ } // End of Kite namespace.