// -*- C++ -*- namespace Kite { /*! \class Manipulator * \brief Handle TrackElement ripup & topological modifications. * * \section secManipStruct Manipulator Structure * * A Manipulator basically binds together a TrackElement, it's * DataNegociate and RoutingEvent (cached for fast access), and * \b a SegmentFsm. * * The TrackElement may differs from the one of the SegmentFsm. * This can occurs when manipulating perpandiculars or segments from * other nets in conflict. For example: Manipulator::isCaged(). * * In the following documentation, the segment which is associated * to the SegmentFsm will be called the reference segment. * * \section secManipDelayed Delayed Modifications * * It is important to note that when a Manipulator is called to * modificate a TrackElement, nothing is actually done by the * Manipulator itself. Instead, the Manipulator create the * relevant SegmentAction (s) that are stored in the SegmentFsm. * The action themselves are done at the end of the SegmentFsm * lifecycle (wrapped inside a Session). * * \red{This is not true!} When dogleg are created, the topology is * immediatly modificated. That way of doing must be clarified. */ //! \enum Manipulator::FunctionFlag //! The various flags that can be passed to the Manipulator methods. //! \var Manipulator::ToRipupLimit //! The ripup limit must be immediatly to it's limit for the current //! state. //! \var Manipulator::AllowExpand //! Allow break points for dogleg not to be exactly on the requested //! position. Meaning that they are moved to the least congested //! GCell. //! \var Manipulator::NoExpand //! Breakpoints for dogleg are kept right where they are requested. //! \var Manipulator::PerpandicularsFirst //! Reorder the events so that perpandiculars segments are re-processed //! before their reference segment. By default this is the other way //! around. //! \var Manipulator::ToMoveUp //! Try to move up ripped up segments. //! \var Manipulator::AllowLocalMoveUp //! Allow local segments to be moved up (forbidden by default). //! \var Manipulator::AllowTerminalMoveUp //! Allow terminal segments to be moved up (forbidden by default). //! \var Manipulator::AllowShortPivotUp //! Allow short segment yo be pivoted up. //! \var Manipulator::NoDoglegReuse //! When creating a dogleg, the default behavior is \e not to create a //! new one if there's already one in the same GCell. If this flag is //! set, a second dogleg will be created. //! \var Manipulator::RightAxisHint //! An explicit right axis hint has been supplied as argument. //! \var Manipulator::LeftAxisHint //! An explicit left axis hint has been supplied as argument. //! \var Manipulator::NotOnLastRipup //! The reference segment has still more than one ripup to go for //! the given state. //! \function Manipulator::Manipulator ( TrackElement* segment, SegmentFsm& fsm ); //! \param segment The TrackElement to manipulate. //! \param fsm The associated SegmentFsm. //! //! Construct a new Manipulator on \c segment. //! \function TrackElement* Manipulator::getSegment () const; //! \sreturn The working TrackElement. //! \function DataNegociate* Manipulator::getData () const; //! \sreturn The DataNegociate of the TrackElement (act as a cache). //! \function RoutingEvent* Manipulator::getEvent () const; //! \sreturn The RoutingEvent associated to the TrackElement (act as a cache). //! \function bool Manipulator::canRipup ( unsigned int flags ) const; //! \sreturn \true if the maximum ripup, for the given SegmentFsm::State has not //! been reached. If \c flags contains Manipulator::HasNextRipup, return //! \true \b only if it still have at least one ripup to go. //! \function bool Manipulator::isCaged ( DbU::Unit axis ) const; //! \sreturn \true if the segment is enclosed (in it's Track) by two fixed or //! blockage segments which at least one is closer than 10 lambdas from //! \c axis. Mostly used to know if a perpandicular is actually restricting //! the axis span of a reference segment. //! \function bool Manipulator::ripup ( unsigned int type, DbU::Unit axisHint=0 ); //! \param type The type of ripup action. //! \param axisHint An indication as where to move the riped up segment. //! \return \true if the operation has succedeed. //! //! If the TrackElement can be ripped up, schedule a ripup action, possibly //! with a hint for the preferred axis position. //! \function bool Manipulator::ripupPerpandiculars ( unsigned int flags ); //! Schedule a ripup of all the perpandiculars of the reference segment. //! \c flags that modificate the behavior: //! - Manipulator::PerpandicularsFirst : the queue will be reordered so //! that all the perpandiculars are re-processed (placed) before the //! reference segment. //! - Manipulator::ToRipupLimit : the ripup count of the reference segment //! is set to the limit (i.e. only one more attempt before a slackening //! occurs). //! //! The method will fails (return \false) if at least one perpandicular can't //! be changed of track (i.e. ripped up) \b and none of it's neighbors could //! be ripped up either. Meaning that the free span on that track cannot be //! changed. //! \function void Manipulator::repackPerpandiculars (); //! Ripup all the perpandiculars of the reference segment, except fixed or //! globals. The reference segment is rescheduled first (before it's //! perpandicular). //! //! This function may be used to find a better placement, maximizing the //! overlap of the various perpandiculars. //! \function bool Manipulator::ripple (); //! \sreturn true if the reference segment is local. //! //! Applies only on reference segments that are of local type. //! Tries to make room for the reference segment by ripping up it's neigbors //! on the parallels tracks. On a vertical plane, left neigbors are shifted //! one track left (trough axis hint) and right ones, one track right. //! Note that they are ripped up and the shift is just a hint, there's no //! guarantee that the router can honor it. //! \function bool Manipulator::minimize (); //! \sreturn true if the reference segment can be mimized in a suitable track hole. //! //! Compute the miminal span of the reference segment, summing up contraints //! from source anchor and target anchors (if any) and perpandiculars. //! Then find holes in the avalaible tracks, and check if one is suitable //! for the miminized segment (try first the biggest hole). //! //! This operation can only be called once on a segment (a flag is set in the //! event). //! \function bool Manipulator::slacken ( unsigned int flags=KbNoFlags ); //! Simple proxy towards TrackElement::slacken(). //! //! \red{To be reviewed.} //! \function bool Manipulator::pivotUp (); //! Tries to move up the reference segment. The segment will be moved //! up only if a half track is free (for a local) or a full track is //! free (for a global). //! //! This function do not modifies/create perpandiculars. //! \function bool Manipulator::pivotDown (); //! Tries to move down the reference segment. The segment will be moved //! up only if \e two track are free (whether global or local). Is is more //! restrictive than Manipulator::pivotUp(). //! //! This function do not modifies/create perpandiculars. //! \function bool Manipulator::moveUp ( unsigned int flags ); //! Tries to move up a segment, if there is enough space in the RoutingPlane //! above and in the same direction. //! //! This function may modificate perpandiculars in order to maintain //! connexity. //! //! \red{To be reviewed.} //! \function bool Manipulator::makeDogleg (); //! \sreturn \false if the segment is \e not local or the dogleg cannot be done. //! //! For \e local reference segment only, look in the first track candidate //! for other segment overlapping and break the reference accordingly. //! \function bool Manipulator::makeDogleg ( Interval overlap ); //! Create a dogleg to avoid the obstructed interval \c overlap. //! \function bool Manipulator::makeDogleg ( DbU::Unit position ); //! Create a dogleg in the GCell under \c position. //! \function bool Manipulator::relax ( Interval overlap, unsigned int flags=AllowExpand ); //! Break the reference segment so it can detour around the interval //! \c overlap. If \c overlap is completly enclosed inside the span of //! the reference segment two dogleg will be created. If the overlap occurs //! only on one side of the reference segment, only one dogleg will be //! created. //! //! If \c flags contains Manipulator::AllowExpand, the dogleg are not created //! exactly at the edges of the overlap but on the lowest density GCell //! (outside the overlap interval). //! //! The axis of the created dogleg are sets so that the broken part of the //! segment completly enclose \c overlap. That is, the orignal segment no //! longer intersect with \c overlap. So the min dogleg is pushed to the //! left and the max to the right if they are in the same GCell as the //! min/max of \c overlap. Otherwise (they have been expanded), they are //! put in the center of the GCell. //! //! We do not allow to dogleg twice in the same GCell, so if min or max //! is in respectively the first or last GCell, it is not done. Moreover //! if there is only one dogleg \e and it is in the first or last GCell, //! the relax method is cancelled (and returns \false). It means that //! this is the segment which is likely to be enclosed inside \c overlap. //! //! \redB{Important:} The doglegs are created immediatly and not in a delayed //! fashion like the SegmentAction. //! //! \image html ManipulatorRelax-1.png "Two Doglegs (min & max), no expansion" //! \image html ManipulatorRelax-2.png "Two Doglegs (min & max), with expansion" //! \image html ManipulatorRelax-3.png "One Dogleg (min)" //! \image html ManipulatorRelax-4.png "One Dogleg (max)" //! \function bool Manipulator::insertInTrack ( size_t i ); //! Try to insert the reference segment in the track at index \c i (in the cost //! table from SegmentFsm). The insertion is done by ripping up overlapping //! segment or shrinking them to left/right if possible. //! //! \red{This operation ripup the processed segment neighbors (and their perpandiculars).} //! \function bool Manipulator::forceToTrack ( size_t i ); //! Try to insert the reference segment in the track at index \c i (in the cost //! table from SegmentFsm). The insertion is done by \e forcibly ripping up the //! overlapping segments \b and their perpandiculars. //! //! \red{This operation ripup the processed segment neighbors (and their perpandiculars).} //! \function bool Manipulator::shrinkToTrack ( size_t i, unsigned int flags, DbU::Unit leftAxisHint, DbU::Unit rightAxisHint ); //! Attempt to minimize the reference segment to fit into the track. //! For this operation to succeed, the minimal span of the segment must //! not overlap any other segment already in the track. To reach the //! minimal span the perpandiculars are ripped up with an axis hint //! which is the center of the minimal span or the explicit value given //! as arguments \c leftAxisHint and \c rightAxisHint if \c flags contains //! respectively Manipulator::LeftAxisHint or Manipulator::RightAxisHint. //! //! \red{This operation ripup the processed segment itself and its perpandiculars.} //! \function bool Manipulator::forceOverLocals (); //! Loop over all the candidate tracks and, insert in the first which //! all conflicting segments are locals (rip them up). //! \function bool Manipulator::repackPerpandiculars (); //! Ripup all perpandiculars and the reference segment itself for a complete //! re-placement. The reference segment will be reprocessed \e before it's //! perpandiculars. }