From 5dd8cb502ac3c993551cb729a34be87e80295618 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 9 Mar 2010 15:24:55 +0000 Subject: [PATCH] * ./hurricane/src/hviewer, ./coriolis/src/crlcore, ./coriolis/src/knik, ./coriolis/src/katabatic, ./coriolis/src/kite, ./coriolis/src/equinox, ./coriolis/src/solstice, ./coriolis/src/ispd: - SVN MOVE: Source tree simplification & uniformisation. Now all tools are at the same level, directly under the root of the repository. No more "coriolis/src". --- kite/CMakeLists.txt | 50 + kite/cmake_modules/CMakeLists.txt | 1 + kite/cmake_modules/FindKITE.cmake | 47 + kite/doc/ASIM-bigfonts.css | 353 +++ kite/doc/ASIM.css | 485 ++++ kite/doc/CMakeLists.txt | 12 + kite/doc/Kite.dox | 97 + kite/doc/RoutingEvent.dox | 597 ++++ kite/doc/Session.dox | 133 + kite/doc/Track.dox | 397 +++ kite/doc/TrackCost.dox | 130 + kite/doc/TrackSegment.dox | 170 ++ kite/doc/TrackSegmentCost.dox | 118 + kite/doc/asimbook.cls | 798 ++++++ kite/doc/doxyfile | 286 ++ kite/doc/footer.html | 16 + kite/doc/header.html | 23 + kite/doc/header.tex | 47 + kite/doc/html.entry | 1 + kite/doc/images/RoutingEvent-1.fig | 66 + kite/doc/images/RoutingEvent-1.pdf | Bin 0 -> 4367 bytes kite/doc/images/RoutingEvent-1.png | Bin 0 -> 5564 bytes kite/doc/images/RoutingEvent-10.fig | 46 + kite/doc/images/RoutingEvent-10.pdf | Bin 0 -> 3053 bytes kite/doc/images/RoutingEvent-10.png | Bin 0 -> 2951 bytes kite/doc/images/RoutingEvent-11.fig | 124 + kite/doc/images/RoutingEvent-11.pdf | Bin 0 -> 3641 bytes kite/doc/images/RoutingEvent-11.png | Bin 0 -> 5965 bytes kite/doc/images/RoutingEvent-12.fig | 127 + kite/doc/images/RoutingEvent-12.pdf | Bin 0 -> 3580 bytes kite/doc/images/RoutingEvent-12.png | Bin 0 -> 5771 bytes kite/doc/images/RoutingEvent-13.fig | 108 + kite/doc/images/RoutingEvent-13.pdf | 108 + kite/doc/images/RoutingEvent-13.png | Bin 0 -> 5220 bytes kite/doc/images/RoutingEvent-14.fig | 110 + kite/doc/images/RoutingEvent-14.pdf | Bin 0 -> 3259 bytes kite/doc/images/RoutingEvent-14.png | Bin 0 -> 5046 bytes kite/doc/images/RoutingEvent-15.fig | 96 + kite/doc/images/RoutingEvent-15.pdf | 93 + kite/doc/images/RoutingEvent-15.png | Bin 0 -> 5077 bytes kite/doc/images/RoutingEvent-2.fig | 82 + kite/doc/images/RoutingEvent-2.pdf | Bin 0 -> 4559 bytes kite/doc/images/RoutingEvent-2.png | Bin 0 -> 7740 bytes kite/doc/images/RoutingEvent-3.fig | 98 + kite/doc/images/RoutingEvent-3.pdf | Bin 0 -> 5286 bytes kite/doc/images/RoutingEvent-3.png | Bin 0 -> 7436 bytes kite/doc/images/Track-1.fig | 87 + kite/doc/images/Track-1.pdf | Bin 0 -> 2720 bytes kite/doc/images/Track-1.png | Bin 0 -> 6262 bytes kite/doc/images/Track-2.fig | 150 + kite/doc/images/Track-2.pdf | Bin 0 -> 4361 bytes kite/doc/images/Track-2.png | Bin 0 -> 8319 bytes kite/doc/images/Track-3.fig | 165 ++ kite/doc/images/Track-3.pdf | Bin 0 -> 3438 bytes kite/doc/images/Track-3.png | Bin 0 -> 7643 bytes kite/doc/images/Track-4.fig | 83 + kite/doc/images/Track-4.pdf | Bin 0 -> 2979 bytes kite/doc/images/Track-4.png | Bin 0 -> 4174 bytes kite/doc/images/Track-5.fig | 74 + kite/doc/images/Track-5.pdf | Bin 0 -> 2851 bytes kite/doc/images/Track-5.png | Bin 0 -> 4102 bytes kite/doc/images/TrackSegmentCost-1.fig | 57 + kite/doc/images/TrackSegmentCost-1.pdf | Bin 0 -> 3955 bytes kite/doc/images/TrackSegmentCost-1.png | Bin 0 -> 3712 bytes kite/doc/images/TrackSegmentCost-2.fig | 51 + kite/doc/images/TrackSegmentCost-2.pdf | Bin 0 -> 3155 bytes kite/doc/images/TrackSegmentCost-2.png | Bin 0 -> 3260 bytes kite/doc/images/TrackSegmentCost-3.fig | 105 + kite/doc/images/TrackSegmentCost-3.pdf | Bin 0 -> 3504 bytes kite/doc/images/TrackSegmentCost-3.png | Bin 0 -> 5425 bytes kite/src/BuildBlockages.cpp | 439 +++ kite/src/BuildPowerRails.cpp | 595 ++++ kite/src/CMakeLists.txt | 95 + kite/src/Configuration.cpp | 178 ++ kite/src/DataNegociate.cpp | 111 + kite/src/GCell.cpp | 569 ++++ kite/src/GCellGrid.cpp | 154 + kite/src/GCellRoutingSet.cpp | 402 +++ kite/src/GraphicKiteEngine.cpp | 395 +++ kite/src/HorizontalTrack.cpp | 84 + kite/src/KiteEngine.cpp | 652 +++++ kite/src/KiteMain.cpp | 218 ++ kite/src/NegociateWindow.cpp | 560 ++++ kite/src/PreProcess.cpp | 319 +++ kite/src/RoutingEvent.cpp | 3648 ++++++++++++++++++++++++ kite/src/RoutingEventHistory.cpp | 130 + kite/src/RoutingEventQueue.cpp | 321 +++ kite/src/RoutingPlane.cpp | 196 ++ kite/src/Session.cpp | 364 +++ kite/src/Track.cpp | 774 +++++ kite/src/TrackBlockage.cpp | 204 ++ kite/src/TrackCost.cpp | 191 ++ kite/src/TrackElement.cpp | 305 ++ kite/src/TrackElements.cpp | 148 + kite/src/TrackFixedSegment.cpp | 220 ++ kite/src/TrackMarker.cpp | 145 + kite/src/TrackSegment.cpp | 1192 ++++++++ kite/src/TrackSegmentCost.cpp | 219 ++ kite/src/Tracks.cpp | 329 +++ kite/src/VerticalTrack.cpp | 83 + kite/src/kite/Configuration.h | 128 + kite/src/kite/DataNegociate.h | 177 ++ kite/src/kite/GCell.h | 217 ++ kite/src/kite/GCellGrid.h | 92 + kite/src/kite/GCellRoutingSet.h | 158 + kite/src/kite/GraphicKiteEngine.h | 111 + kite/src/kite/HorizontalTrack.h | 67 + kite/src/kite/KiteEngine.h | 193 ++ kite/src/kite/NegociateWindow.h | 158 + kite/src/kite/RoutingEvent.h | 272 ++ kite/src/kite/RoutingEventHistory.h | 86 + kite/src/kite/RoutingEventQueue.h | 92 + kite/src/kite/RoutingPlane.h | 137 + kite/src/kite/Session.h | 212 ++ kite/src/kite/Track.h | 232 ++ kite/src/kite/TrackBlockage.h | 98 + kite/src/kite/TrackCost.h | 168 ++ kite/src/kite/TrackElement.h | 229 ++ kite/src/kite/TrackElements.h | 158 + kite/src/kite/TrackFixedSegment.h | 98 + kite/src/kite/TrackMarker.h | 119 + kite/src/kite/TrackSegment.h | 181 ++ kite/src/kite/TrackSegmentCost.h | 108 + kite/src/kite/Tracks.h | 153 + kite/src/kite/VerticalTrack.h | 65 + kite/src/kiteRefactor.conf | 141 + 126 files changed, 22681 insertions(+) create mode 100644 kite/CMakeLists.txt create mode 100644 kite/cmake_modules/CMakeLists.txt create mode 100644 kite/cmake_modules/FindKITE.cmake create mode 100644 kite/doc/ASIM-bigfonts.css create mode 100644 kite/doc/ASIM.css create mode 100644 kite/doc/CMakeLists.txt create mode 100644 kite/doc/Kite.dox create mode 100644 kite/doc/RoutingEvent.dox create mode 100644 kite/doc/Session.dox create mode 100644 kite/doc/Track.dox create mode 100644 kite/doc/TrackCost.dox create mode 100644 kite/doc/TrackSegment.dox create mode 100644 kite/doc/TrackSegmentCost.dox create mode 100644 kite/doc/asimbook.cls create mode 100644 kite/doc/doxyfile create mode 100644 kite/doc/footer.html create mode 100644 kite/doc/header.html create mode 100644 kite/doc/header.tex create mode 100644 kite/doc/html.entry create mode 100644 kite/doc/images/RoutingEvent-1.fig create mode 100644 kite/doc/images/RoutingEvent-1.pdf create mode 100644 kite/doc/images/RoutingEvent-1.png create mode 100644 kite/doc/images/RoutingEvent-10.fig create mode 100644 kite/doc/images/RoutingEvent-10.pdf create mode 100644 kite/doc/images/RoutingEvent-10.png create mode 100644 kite/doc/images/RoutingEvent-11.fig create mode 100644 kite/doc/images/RoutingEvent-11.pdf create mode 100644 kite/doc/images/RoutingEvent-11.png create mode 100644 kite/doc/images/RoutingEvent-12.fig create mode 100644 kite/doc/images/RoutingEvent-12.pdf create mode 100644 kite/doc/images/RoutingEvent-12.png create mode 100644 kite/doc/images/RoutingEvent-13.fig create mode 100644 kite/doc/images/RoutingEvent-13.pdf create mode 100644 kite/doc/images/RoutingEvent-13.png create mode 100644 kite/doc/images/RoutingEvent-14.fig create mode 100644 kite/doc/images/RoutingEvent-14.pdf create mode 100644 kite/doc/images/RoutingEvent-14.png create mode 100644 kite/doc/images/RoutingEvent-15.fig create mode 100644 kite/doc/images/RoutingEvent-15.pdf create mode 100644 kite/doc/images/RoutingEvent-15.png create mode 100644 kite/doc/images/RoutingEvent-2.fig create mode 100644 kite/doc/images/RoutingEvent-2.pdf create mode 100644 kite/doc/images/RoutingEvent-2.png create mode 100644 kite/doc/images/RoutingEvent-3.fig create mode 100644 kite/doc/images/RoutingEvent-3.pdf create mode 100644 kite/doc/images/RoutingEvent-3.png create mode 100644 kite/doc/images/Track-1.fig create mode 100644 kite/doc/images/Track-1.pdf create mode 100644 kite/doc/images/Track-1.png create mode 100644 kite/doc/images/Track-2.fig create mode 100644 kite/doc/images/Track-2.pdf create mode 100644 kite/doc/images/Track-2.png create mode 100644 kite/doc/images/Track-3.fig create mode 100644 kite/doc/images/Track-3.pdf create mode 100644 kite/doc/images/Track-3.png create mode 100644 kite/doc/images/Track-4.fig create mode 100644 kite/doc/images/Track-4.pdf create mode 100644 kite/doc/images/Track-4.png create mode 100644 kite/doc/images/Track-5.fig create mode 100644 kite/doc/images/Track-5.pdf create mode 100644 kite/doc/images/Track-5.png create mode 100644 kite/doc/images/TrackSegmentCost-1.fig create mode 100644 kite/doc/images/TrackSegmentCost-1.pdf create mode 100644 kite/doc/images/TrackSegmentCost-1.png create mode 100644 kite/doc/images/TrackSegmentCost-2.fig create mode 100644 kite/doc/images/TrackSegmentCost-2.pdf create mode 100644 kite/doc/images/TrackSegmentCost-2.png create mode 100644 kite/doc/images/TrackSegmentCost-3.fig create mode 100644 kite/doc/images/TrackSegmentCost-3.pdf create mode 100644 kite/doc/images/TrackSegmentCost-3.png create mode 100644 kite/src/BuildBlockages.cpp create mode 100644 kite/src/BuildPowerRails.cpp create mode 100644 kite/src/CMakeLists.txt create mode 100644 kite/src/Configuration.cpp create mode 100644 kite/src/DataNegociate.cpp create mode 100644 kite/src/GCell.cpp create mode 100644 kite/src/GCellGrid.cpp create mode 100644 kite/src/GCellRoutingSet.cpp create mode 100644 kite/src/GraphicKiteEngine.cpp create mode 100644 kite/src/HorizontalTrack.cpp create mode 100644 kite/src/KiteEngine.cpp create mode 100644 kite/src/KiteMain.cpp create mode 100644 kite/src/NegociateWindow.cpp create mode 100644 kite/src/PreProcess.cpp create mode 100644 kite/src/RoutingEvent.cpp create mode 100644 kite/src/RoutingEventHistory.cpp create mode 100644 kite/src/RoutingEventQueue.cpp create mode 100644 kite/src/RoutingPlane.cpp create mode 100644 kite/src/Session.cpp create mode 100644 kite/src/Track.cpp create mode 100644 kite/src/TrackBlockage.cpp create mode 100644 kite/src/TrackCost.cpp create mode 100644 kite/src/TrackElement.cpp create mode 100644 kite/src/TrackElements.cpp create mode 100644 kite/src/TrackFixedSegment.cpp create mode 100644 kite/src/TrackMarker.cpp create mode 100644 kite/src/TrackSegment.cpp create mode 100644 kite/src/TrackSegmentCost.cpp create mode 100644 kite/src/Tracks.cpp create mode 100644 kite/src/VerticalTrack.cpp create mode 100644 kite/src/kite/Configuration.h create mode 100644 kite/src/kite/DataNegociate.h create mode 100644 kite/src/kite/GCell.h create mode 100644 kite/src/kite/GCellGrid.h create mode 100644 kite/src/kite/GCellRoutingSet.h create mode 100644 kite/src/kite/GraphicKiteEngine.h create mode 100644 kite/src/kite/HorizontalTrack.h create mode 100644 kite/src/kite/KiteEngine.h create mode 100644 kite/src/kite/NegociateWindow.h create mode 100644 kite/src/kite/RoutingEvent.h create mode 100644 kite/src/kite/RoutingEventHistory.h create mode 100644 kite/src/kite/RoutingEventQueue.h create mode 100644 kite/src/kite/RoutingPlane.h create mode 100644 kite/src/kite/Session.h create mode 100644 kite/src/kite/Track.h create mode 100644 kite/src/kite/TrackBlockage.h create mode 100644 kite/src/kite/TrackCost.h create mode 100644 kite/src/kite/TrackElement.h create mode 100644 kite/src/kite/TrackElements.h create mode 100644 kite/src/kite/TrackFixedSegment.h create mode 100644 kite/src/kite/TrackMarker.h create mode 100644 kite/src/kite/TrackSegment.h create mode 100644 kite/src/kite/TrackSegmentCost.h create mode 100644 kite/src/kite/Tracks.h create mode 100644 kite/src/kite/VerticalTrack.h create mode 100644 kite/src/kiteRefactor.conf diff --git a/kite/CMakeLists.txt b/kite/CMakeLists.txt new file mode 100644 index 00000000..fcd5deba --- /dev/null +++ b/kite/CMakeLists.txt @@ -0,0 +1,50 @@ +PROJECT(KITE) + +OPTION(BUILD_DOC "Build the documentation (doxygen)" OFF) +OPTION(CHECK_DATABASE "Run database in full check mode (very slow)" OFF) + +CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0) + +SET(CMAKE_C_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE) +SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg" CACHE STRING "Debug options." FORCE) +SET(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG -Wall" CACHE STRING "Release options." FORCE) +SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -Wall" CACHE STRING "Release options." FORCE) + +IF(COMMAND CMAKE_POLICY) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND CMAKE_POLICY) + +SET(CMAKE_MODULE_PATH "$ENV{HURRICANE_TOP}/share/cmake_modules/") + +SET(QT_USE_QTXML "true") + +IF(BUILD_DOC) + FIND_PACKAGE(Doxygen) +ENDIF(BUILD_DOC) +FIND_PACKAGE(Boost 1.33.1 COMPONENTS program_options REQUIRED) +FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project +FIND_PACKAGE(Boost 1.33.1 REQUIRED) +FIND_PACKAGE(LEFDEF REQUIRED) +FIND_PACKAGE(HURRICANE REQUIRED) +FIND_PACKAGE(CORIOLIS REQUIRED) +FIND_PACKAGE(KNIK REQUIRED) +FIND_PACKAGE(KATABATIC REQUIRED) + +SET_LIB_LINK_MODE() + +IF(CHECK_DATABASE) + ADD_DEFINITIONS(-DCHECK_DATABASE) +ENDIF(CHECK_DATABASE) +IF(CHECK_DETERMINISM) + ADD_DEFINITIONS(-DCHECK_DETERMINISM) +ENDIF(CHECK_DETERMINISM) + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(cmake_modules) +IF(BUILD_DOC AND DOXYGEN_FOUND) + ADD_SUBDIRECTORY(doc) +ENDIF(BUILD_DOC AND DOXYGEN_FOUND) diff --git a/kite/cmake_modules/CMakeLists.txt b/kite/cmake_modules/CMakeLists.txt new file mode 100644 index 00000000..0cb75c1c --- /dev/null +++ b/kite/cmake_modules/CMakeLists.txt @@ -0,0 +1 @@ +install ( FILES FindKITE.cmake DESTINATION /share/cmake_modules ) diff --git a/kite/cmake_modules/FindKITE.cmake b/kite/cmake_modules/FindKITE.cmake new file mode 100644 index 00000000..7ec9d910 --- /dev/null +++ b/kite/cmake_modules/FindKITE.cmake @@ -0,0 +1,47 @@ +# - Find the Kite includes and libraries. +# The following variables are set if Coriolis is found. If KITE is not +# found, KITE_FOUND is set to false. +# KITE_FOUND - True when the Coriolis include directory is found. +# KITE_INCLUDE_DIR - the path to where the Coriolis include files are. +# KITE_LIBRARIES - The path to where the Coriolis library files are. + + +SET(KITE_INCLUDE_PATH_DESCRIPTION "directory containing the Kite include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis") + +SET(KITE_DIR_MESSAGE "Set the KITE_INCLUDE_DIR cmake cache entry to the ${KITE_INCLUDE_PATH_DESCRIPTION}") + +# don't even bother under WIN32 +IF(UNIX) + + SET(KITE_DIR_SEARCH $ENV{CORIOLIS_TOP} $ENV{HURRICANE_TOP}) + # + # Look for an installation. + # + FIND_PATH(KITE_INCLUDE_PATH NAMES kite/KiteEngine.h PATHS + # Look in other places. + ${KITE_DIR_SEARCH} + PATH_SUFFIXES include/coriolis + # Help the user find it if we cannot. + DOC "The ${KITE_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(KITE_LIBRARY_PATH + NAMES kite + PATHS ${KITE_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${KITE_INCLUDE_PATH_DESCRIPTION}" + ) + + FIND_LIBRARY(KITE_STATIC_LIBRARY_PATH + NAMES kite-static + PATHS ${KITE_DIR_SEARCH} + PATH_SUFFIXES lib + # Help the user find it if we cannot. + DOC "The ${KITE_INCLUDE_PATH_DESCRIPTION}" + ) + + SET_LIBRARIES_PATH(KITE KITE) + HURRICANE_CHECK_LIBRARIES(KITE) + +ENDIF(UNIX) diff --git a/kite/doc/ASIM-bigfonts.css b/kite/doc/ASIM-bigfonts.css new file mode 100644 index 00000000..f8ec6823 --- /dev/null +++ b/kite/doc/ASIM-bigfonts.css @@ -0,0 +1,353 @@ + + +/* + * x-----------------------------------------------------------------x + * | HTML Standart Tags | + * x-----------------------------------------------------------------x + */ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 10%; + margin-left: 10%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + .hide { + display: none; + color: white; + } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + caption { font-weight: bold } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: solid; + border-width: thin; + border-color: #003300; + background-color: #EEEEEE; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + + + + +/* + * x-----------------------------------------------------------------x + * | Doxygen Specific Classes | + * x-----------------------------------------------------------------x + */ + + +/* ------------------------------------------------------------------- + * Header & Footer Classes (customized top page navigation bar). + */ + + table.header { + width: 100%; + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + } + + h1.header { + font-family: times, verdana, sans-serif; + } + + td.header { + /*width: 14%;*/ + text-align: center; + font-weight: bold; + font-family: verdana, sans-serif; + } + + table.footer { + width: 100%; + } + + td.leftFoot1, td.leftFoot2 { + text-align: left; + } + + td.rightFoot1, td.rightFoot2 { + text-align: right; + } + + td.leftFoot2 { + font-family: time; + font-weight: bold; + } + + td.rightFoot2 { + font-weight: bold; + } + + div.ah { + font-family: time; + font-size: 250%; + } + + +/* ------------------------------------------------------------------- + * Quick Index Class (top page navigation bar). + */ + + div.qindex, div.nav { + width: 100%; + /*background-color: #DADAEF;*/ + /*background-color: #eeeeff;*/ + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + border: 1px solid #003300; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; + } + + a.qindex, a.qindex:visited, a.qindex:hover, a.qindexHL, a.el, a.elRef { + text-decoration: none; + font-weight: bold; + } + + a.qindex, a.qindex:visited { + color: #09550B; + } + + a.qindex:hover { + background-color: #ddddff; + } + + a.qindexHL, a.qindexHL:hover, a.qindexHL:visited { + background-color: #0c780c; + color: #ffffff; + border: 1px double #9295C2; + } + + a.code:link, a.code:visited, a.codeRef:link, a.codeRef:visited { + text-decoration: none; + font-weight: normal; + color: #0000ff; + } + + .indexkey { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + padding: 2px 15px; + } + + .indexkey, .indexvalue { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + padding: 2px 15px; + } + + .indexkey { + width: 40%; + } + + .indexvalue { + width: 80%; + } + + +/* ------------------------------------------------------------------- + * Verbatim Source Code / Examples. + */ + + pre.fragment { background-color: #EEEEEE; } + + span.keyword { color: #008000 } + span.keywordtype { color: #604020 } + span.keywordflow { color: #e08000 } + span.comment { color: #800000 } + span.preprocessor { color: #806020 } + span.stringliteral { color: #002080 } + span.charliteral { color: #008080 } + + +/* ------------------------------------------------------------------- + * Attributes Listing. + */ + + .mdTable { + /*border: 1px solid #868686;*/ + /*background-color: #DADAEF;*/ + /*background-color: #F4F4FB;*/ + border: 1px none #868686; + /*background-color: #B8E6B8;*/ + background-color: #CCE6CA; + margin-top: 25px; + } + + .mdRow { + padding: 5px 10px; + } + + /* This Mozilla/Firefox bug has been corrected from v1.5. + * .mdname1 { + * padding: 3px 0px 0px 0px; + * } + */ + + .mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + font-size: 12px; + font-style: italic; + /*background-color: #FAFAFA;*/ + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; + } + + .memItemLeft, .memItemRight, .memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #0c0c0c; + border-right-color: #0c0c0c; + border-bottom-color: #0c0c0c; + border-left-color: #0c0c0c; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + /*background-color: #DADAEF;*/ + /*background-color: #eeeeff;*/ + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + } + + .memItemLeft { font-size: 12px; } + .memItemRight { font-size: 13px; } + .memTemplItemLeft { font-size: 12px; } + .memTemplItemRight { font-size: 13px; } + + .memTemplParams { + color: #606060; + background-color: #DADAEF; + font-size: 12px; + } + diff --git a/kite/doc/ASIM.css b/kite/doc/ASIM.css new file mode 100644 index 00000000..6d92a0c5 --- /dev/null +++ b/kite/doc/ASIM.css @@ -0,0 +1,485 @@ + + +/* + * x-----------------------------------------------------------------x + * | HTML Standart Tags | + * x-----------------------------------------------------------------x + */ + + html, body, th, td, tr, p, li, h1, h2, h3, h4, h5, h6 { + font-size: 96%; + font-family: verdana, sans-serif; + } + + body { + color: black; + background: white; + background-color: white; + background-position: top left; + background-attachment: fixed; + background-repeat: no-repeat; + margin-top: 2em; + margin-right: 8%; + margin-left: 8%; + } + + hr { + height: 1px; + border: 0; + color: #004400; + background-color: #004400; + } + + + h1, h2, h3, h4, h5, h6 { + font-family: verdana, sans-serif; + } + + h1 { text-align: center; } + h2, h3, h4, h5, h6 { text-align: left; + padding-top: 2em; + } + h1, h2, h3 { font-family: "Trebuchet MS", sans-serif; + color: #09550B; + } + h1 { font-weight: bold; font-size: 170%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 118%; } + h4 { font-weight: bold; font-size: 100%; } + h5 { font-style: italic; font-size: 100%; } + h6 { font-variant: small-caps; font-size: 100%; } + + h2.classHierarchy { + /*border: 1px none #008500;*/ + border: 1px none #000000; + border-top-width: 2px; + border-top-style: solid; + padding-top: 1em; + } + + + .hide { + display: none; + color: white; + } + + + p { + margin-top: 0.6em; + margin-bottom: 0.6em; + margin-left: 0.0em; + margin-right: 0.0em; + } + + + address { + text-align: right; + font-weight: bold; + font-style: italic; + font-size: 80%; + } + + + caption { font-weight: bold } + + + blockquote { + margin-left: 4em; + margin-right: 4em; + margin-top: 0.8em; + margin-bottom: 0.8em; + font-style: italic; + color: #003300; + } + + blockquote p { + margin-bottom: 0; + } + + blockquote address { + margin: 0; + } + + + table { + border-collapse: collapse; + } + + dt, dd { margin-top: 0; margin-bottom: 0; } + dt { font-weight: bold; } + + + pre, tt, code { + font-family: "andale mono", monospace; + font-size: 100%; + white-space: pre; + } + + pre { + font-size: 80%; + border: dashed; + border-width: thin; + border-color: #003300; + /* + background-color: #EEEEEE; + */ + background-color: #FCFCE1; + padding: 0.5em; + margin-left: 2em; + margin-right: 2em + } + + tt { color: green; } + em { font-style: italic; + font-weight: bold; } + strong { font-weight: bold; } + + span.textit { font-style: italic; } + span.textbf { font-weight: bold; } + + .small { font-size: 90%; } + .white { color: #FFFFFF; } + + + ul.toc { + list-style: disc; + list-style: none; + } + + + a:link img, a:visited img { border-style: none; } + a img { color: white; } + + a:link, a:active, a:visited { + color: #09550B; + text-decoration: none; + } + + a:hover, a:focus { + color: #FF9900; + text-decoration: underline; + } + + + + +/* + * x-----------------------------------------------------------------x + * | Doxygen Specific Classes | + * x-----------------------------------------------------------------x + */ + + +/* ------------------------------------------------------------------- + * Header & Footer Classes (customized top page navigation bar). + */ + + h1.header { + font-size: 200%; + font-family: times, verdana, sans-serif; + } + + center.header { + background-color: #CCE6CA; + } + + table.header { + /*width: 100%;*/ + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + } + + table.header td { + padding: 2px 14px; + text-align: center; + font-weight: bold; + font-family: verdana, sans-serif; + font-size: 110%; + } + + table.footer1, table.footer2 { width: 100%; } + td.LFooter { text-align: left; } + td.RFooter { text-align: right; } + td.CFooter { text-align: center;} + table.footer2 td.RFooter { font-weight: bold; width: 35% } + table.footer2 td.CFooter { width: 30% } + table.footer2 td.LFooter { font-weight: bold; width: 35%; font-family: time; } + + table.classHierarchy { + border-collapse: separate; + border-spacing: 5px; + font-size: 110%; + } + + table.classHierarchy tr { + border: 1px solid blue; + } + + table.classHierarchy td.normal { + border: 1px solid #CCE6CA; + width: 140pt; + text-align: center; + font-weight: bold; + background-color: #CCE6CA; + } + + table.classHierarchy td.virtual { + border: 1px solid black; + width: 140pt; + text-align: center; + font-weight: bold; + } + + table.classHierarchy td.wnormal { + border: 1px solid #CCE6CA; + width: 240pt; + text-align: center; + font-weight: bold; + background-color: #CCE6CA; + } + + table.classHierarchy td.wvirtual { + border: 1px solid black; + width: 240pt; + text-align: center; + font-weight: bold; + } + + div.ah { + font-family: time; + font-size: 250%; + } + + +/* ------------------------------------------------------------------- + * Quick Index Class (top page navigation bar). + */ + + div.qindex, div.nav { + width: 100%-4px; + /*background-color: #DADAEF;*/ + /*background-color: #eeeeff;*/ + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + border: 0px solid #003300; + text-align: center; + margin: 0px; + padding: 2px; + line-height: 140%; + } + + a.qindex, a.qindex:visited, a.qindex:hover, a.qindexHL, a.el, a.elRef { + text-decoration: none; + font-weight: bold; + } + + a.qindex, a.qindex:visited { + color: #09550B; + } + + a.qindex:hover { + background-color: #ddddff; + } + + a.qindexHL, a.qindexHL:hover, a.qindexHL:visited { + background-color: #0c780c; + color: #ffffff; + border: 1px double #9295C2; + } + + a.code:link, a.code:visited, a.codeRef:link, a.codeRef:visited { + text-decoration: none; + font-weight: normal; + color: #0000ff; + } + + .indexkey { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + padding: 2px 15px; + } + + .indexkey, .indexvalue { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + padding: 2px 15px; + } + + .indexkey { + width: 40%; + } + + .indexvalue { + width: 80%; + } + + h3 a[name="index__"], + h3 a[name="index_a"], + h3 a[name="index_b"], + h3 a[name="index_c"], + h3 a[name="index_d"], + h3 a[name="index_e"], + h3 a[name="index_f"], + h3 a[name="index_g"], + h3 a[name="index_h"], + h3 a[name="index_i"], + h3 a[name="index_j"], + h3 a[name="index_k"], + h3 a[name="index_l"], + h3 a[name="index_m"], + h3 a[name="index_n"], + h3 a[name="index_o"], + h3 a[name="index_p"], + h3 a[name="index_q"], + h3 a[name="index_r"], + h3 a[name="index_s"], + h3 a[name="index_t"], + h3 a[name="index_u"], + h3 a[name="index_v"], + h3 a[name="index_w"], + h3 a[name="index_x"], + h3 a[name="index_y"], + h3 a[name="index_z"], + h3 a[name="index_0"], + h3 a[name="index_1"], + h3 a[name="index_2"], + h3 a[name="index_3"], + h3 a[name="index_4"], + h3 a[name="index_5"], + h3 a[name="index_6"], + h3 a[name="index_7"], + h3 a[name="index_8"], + h3 a[name="index_9"] + { + font-family: time; + font-size: 250%; + } + + +/* ------------------------------------------------------------------- + * Verbatim Source Code / Examples. + */ + + /* pre.fragment { background-color: #EEEEEE; } */ + + span.keyword { color: #008000 } + span.keywordtype { color: #604020 } + span.keywordflow { color: #e08000 } + span.comment { color: #800000 } + span.preprocessor { color: #806020 } + span.stringliteral { color: #002080 } + span.charliteral { color: #008080 } + + +/* ------------------------------------------------------------------- + * Attributes Listing. + */ + + .mdTable { + /*border: 1px solid #868686;*/ + /*background-color: #DADAEF;*/ + /*background-color: #F4F4FB;*/ + border: 1px none #008500; + border-left-width: 1px; + border-left-style: solid; + /*background-color: #B8E6B8;*/ + /*background-color: #CCE6CA;*/ + margin-top: 25px; + font-size: 105%; + } + + .mdRow { + padding: 5px 10px; + } + + /* This Mozilla/Firefox bug has been corrected from v1.5. + * .mdname1 { + * padding: 3px 0px 0px 0px; + * } + */ + + .mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + font-size: 11px; + font-style: italic; + /*background-color: #FAFAFA;*/ + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; + } + + .memitem { + margin-bottom: 30px; + border: 1px none #008500; + } + + .memproto { + background-color: #CCE6CA; + border-left-width: 4px; + border-left-style: solid; + border-color: #008500; + } + + .memname { + white-space: nowrap; + padding-left: 5px; + font-size: 105%; + } + + + .memdoc{ + padding-left: 5px; + /*margin-top: -8px;*/ + border-left-width: 1px; + border-left-style: solid; + border-color: #008500; + } + + .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #0c0c0c; + border-right-color: #0c0c0c; + border-bottom-color: #0c0c0c; + border-left-color: #0c0c0c; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + /*background-color: #DADAEF;*/ + /*background-color: #eeeeff;*/ + /*background-color: #EEEEEE;*/ + background-color: #CCE6CA; + } + + .memTemplItemLeft, .memTemplItemRight { + border-bottom-width: 2px; + border-bottom-style: solid; + font-weight: bold; + } + + .memItemLeft { font-size: 11px; } + .memItemRight { font-size: 12px; } + .memTemplItemLeft { font-size: 11px; } + .memTemplItemRight { font-size: 12px; } + + .memTemplParams { + color: #FFFFFF; + background-color: #000000; + font-size: 11px; + font-weight: bold; + } + + .groupText, .groupHeader { + color: #09550B; + margin-top: 15px; + font-size: 130%; + font-weight: bold; + } + diff --git a/kite/doc/CMakeLists.txt b/kite/doc/CMakeLists.txt new file mode 100644 index 00000000..7d6870ef --- /dev/null +++ b/kite/doc/CMakeLists.txt @@ -0,0 +1,12 @@ + + set ( htmlInstallDir /share/doc/en/html/kite ) + set ( latexInstallDir /share/doc/en/latex/kite ) + + add_custom_target ( doc ALL cd ${KITE_SOURCE_DIR}/doc && ${DOXYGEN_EXECUTABLE} doxyfile ) + + install ( DIRECTORY html/ DESTINATION ${htmlInstallDir} ) +# install ( FILES customHierarchy.html DESTINATION ${htmlInstallDir} ) +# install ( FILES customSummary.html DESTINATION ${htmlInstallDir} ) + + install ( DIRECTORY latex/ DESTINATION ${latexInstallDir} ) + install ( FILES asimbook.cls DESTINATION ${latexInstallDir} ) diff --git a/kite/doc/Kite.dox b/kite/doc/Kite.dox new file mode 100644 index 00000000..9e144a1e --- /dev/null +++ b/kite/doc/Kite.dox @@ -0,0 +1,97 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \mainpage Detailed Router Documentation + * + * This documentation adresses two level of explanations : + * + * + * + * + * \defgroup AlgorithmOverview Algorithm Overview (internal) + * + * The algorithm top-level is implemented in the \c NegociateWindow. + * + * First step : NegociateWindow::_loadRouting() + *
    + *
  1. Load routing wires (\c AutoSegment) from \c KatabaticEngine + * inside the Kite \c GCell's. Then update the \c GCell's density. + *
  2. Sort the \c GCell's according to decreasing density (denser + * \c GCell's are to be routed first). + *
  3. Agglomerate clusters of contiguous GCell's whose density + * is superior to 0.7 to the seed GCell. See \c GCellRoutingSet + * for the mechanism. + * + * GCellRoutingSet receive an increasing order number. The higher + * the order the lower the density. This order is transmitted + * to the \c TrackSegment of the \c GCellRoutingSet to be taken into + * account by the track cost function. + *
+ * + * Second step : \c NegociateWindow::_runOnGCellRoutingSet() + * + * For each \c GCellRoutingSet in decreasing density, negociate the + * set of associated \c TrackSegment. + *
    + *
  1. Build a \c RoutingEventQueue from the list of \c TrackSegment. + * The queue is responsible for allocating the \c RoutingEvent + * associated to each \c TrackSegment. + *
  2. The queue is sorted according to the "event level" then + * to the priority, which is for now the slack of the \c TrackSegment. + * That is, constrained \c TrackSegment are routed first. + *
  3. The queue is processed till it's empty (no unprocessed \c RoutingEvent + * remains). + * + * Processing a \c RoutingEvent is trying to insert a \c TrackSegment in + * a suitable Track. We proceed as follow : + *
      + *
    • The maximum ripup count for the to be inserted segment has + * been reached. Issue a severe warning and left unrouted + * this \c TrackSegment (for now). + *
    • Compute the Tracks in which the \c TrackSegment can be inserted, + * then compute the insertion cost in each one. The candidates + * are ordered by the insertion cost. + *
    • Now consider the lower cost \c Track. If there is a free interval + * for the \c TrackSegment. Issue a \c Session::addInsertEvent() then + * finish. + * + * If there is a "soft overlap", that is the overlaping + * \c TrackSegment already in the \c Track could be shrunk either to + * the left or the right so the new \c TrackSegment can be inserted. + * This is managed by \c RoutingEvent::_setAside(), for each soft + * overlaping \c TrackSegment, gets its perpandiculars and issue + * a displacement request for all of them. That is, re-post a + * \c RoutingEvent with updated constraints and remove the + * perpandicular from it's Track if it has already been routed. + * Note that no request is issued for the overlaping \c TrackSegment + * itself has it do not change of Track. + * + * If there is a "hard overlap", that is the two \c TrackSegment + * cannot share the same \c Track, remove the previous one from + * the \c Track and re-post a \c RoutingEvent. Note that, the + * cost object should have selected a \c TrackSegment which could + * be ripped-up. Otherwise the \c Track would'nt even be a candidate. + *
    + * + * When a TrackSegment is riped up, it is re-routed immediately + * afterward. This is done by increasing his event level. + *
+ */ + + + /*! \namespace Kite + * \brief The namespace dedicated to Kite. + */ + + } diff --git a/kite/doc/RoutingEvent.dox b/kite/doc/RoutingEvent.dox new file mode 100644 index 00000000..031e85e6 --- /dev/null +++ b/kite/doc/RoutingEvent.dox @@ -0,0 +1,597 @@ + + // -*- 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 + *
  • New \c isLocal() method on \TrackSegment. Tells if the \TrackSegment + * is associated only to local AutoSegment. + *
  • Increase the overlap cost of a \TrackSegment from an already routed + * GCell routing set. + * + * + * + * \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. + *
      + *
    • The optimal interval : where the \Net wirelength will be + * minimal (comes from \c Katabatic::AutoSegment). + *
    • The constraint 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). + *
    • The perpandicular 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. + *
    + * The perpandicular interval comes from perpandicular constraints on \TrackSegment + * of the same \c Net. The left/right axis weights comes from requests of + * other \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: + *
      + *
    • A \TrackSegment can only be displaced by it's associated \RoutingEvent. + *
    • Corollary: the only \TrackSegment displaced while processing a + * \RoutingEvent is the one associated to the event. + *
    • Conflicts occurs between the \RoutingEvent \TrackSegment and already + * placed others \TrackSegment. + * + * The conflict can be solved by displacing/modifying others + * \TrackSegment or by modifying the to be inserted one. In the later + * case, the newly created or modified \TrackSegment are (re)scheduleds + * before the would be inserted. + *
    • 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. + *
    • \TrackSegment are inserted only, and only if there is enough free space. + * That is, if any kind of overlap occurs, it is not inserted + * but rescheduled. The blocking \TrackSegments are then + * rescheduled after the current one. + *
    • 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). + *
    + * + * \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: + *
      + *
    1. In normal mode, that is, no maximum ripup has been reached, the + * blocking other \TrackSegment are removed and the current + * is rescheduled before them. + *
    2. In maximum ripup mode, some \TrackSegment has to give way. + *
        + *
      • If the current one is modified, it must be rescheduled after + * it's modified bits are rescheduleds. + *
      • If others are modifieds they must be rescheduled after + * the current one (so it will grabs the place). + *
      + *
    + * + * + * \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. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
     \b Id \b Type \b Local  \b Global \b Action
    \e 1\c Minimize\e yes\e notry to fit into a hole
    \e 2\c DogLeg\e yes\e noDogleg : analyse overlap and try to solve it by breaking (self)
    \e 3\c Desalignate\e yes\e yeson a set of alignated \TrackSegment, suppress the + * alignment constraints, thus making then independants + *
    \e 4\c Slacken\e yes\e yesif the target/source constraint is less than the + * GCell, adds perpandicular straps to free the \TrackSegment. + * This occurs to free from terminal constraints + *
    \e 5\c ConflictSolve1\e yes\e yestry to find in the history a reccurent dislodger, + * and break (self) to accomodate it + *
    \e 6\c ConflictSolve2\e no\e yestry to find a Track on which we can dislodge + * an other \TrackSegment + *
    \e 7\c MoveUp\e no\e yestry to go on upper layer. + *
    \e 8\c Unimplemented\e no\e yeswe failed to place this \TrackSegment + *
    + * + * + * \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 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. + *
      + *
    1. The scheduler try to place the \TrackSegment on top of the + * event queue, calling process(). + *
    2. There is a soft overlap on the best candidate track, a set + * aside is issued. + *
    3. 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(). + *
    4. 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). + *
    5. 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... + *
    + * + * \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 : + *
      + *
    • \RoutingEvent are used to store algorithmic informations that + * must persist until the negociation algorithm have fully + * completed (bound interval in particular). + *
    • 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. + *
    + * + * \important This is the history queue which is responsible for freeing all the + * \RoutingEvent in his destructor. + * + * + * \section secRoutingEventCase Routing Event actions + * + *
      + *
    • Free Track Case + * + * 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 + * + * + *
    • Soft Overlap Case + * + * Already inserted \TrackSegment a & b could be shrunk + * to make place for \TrackSegment c. Parallel overlaping \TrackSegment + * are not removed, their perpandiculars are with updated left/right axis weight. + * + * The a perpandicular belongs the same GCell routing set so it + * is removed from is \Track to be displaced. + * + * The 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 + * + * + *
    • Hard Overlap Case + * + * No way to shrunk overlaping \TrackSegment to make place for c. + * All parallel overlaping \TrackSegments must be removeds to be displaced + * on other \Tracks. + * + * The a parallel belongs to a more prioritary GCell routing set + * so it can be removed, it is therefore broken. + * + * The 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 + * + * + *
    • Self Relax + * + * Instead of trying to displace overlaping \TrackSegments we break the + * current one. + * + * \image html RoutingEvent-13.png + * \image latex RoutingEvent-13.pdf + * + * + *
    • Self Desalignate + * + * 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 + * + * + *
    • Self Slacken + * + * 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 + * + *
    + */ + + /*! \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 area of the associated \TrackSegment, which in + * turn return the slack (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 before the original one, which is marked as + * processed 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 : + *
      + *
    • The event has really been processed by the process() member + * function. + *
    • 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. + *
    + */ + + /*! \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 : + *
      + *
    1. Invalidating all perpandicular \TrackSegments. + *
    2. Computing the free interval allowed by the free intervals + * in perpandicular \Tracks holding the perpandicular \TrackSegments. + *
    3. Merging in the various constraints intervals : from the + * \TrackSegment itself, from the free intervals in the + * perpandicular \Tracks and from the \RoutingEvent bound + * constraints. + *
    4. Finding the candidate \Tracks for the \RoutingEvent, + * using \c Track_Spiral \Collection. + *
    + * 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 soft overlap. Create or enlarge a free space + * in \c track so it can contain the requested \interval. [begin:end] defines + * the range of indexes of overlaping \TrackSegment in \c track. + * Displace TrackSegment that are perpandicular 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 not removed from the \c track. + * + * A note on implementation : + *
      + *
    • \c data1 : the DataNegociate of the to be inserted \TrackSegment. + *
    • \c segment2 : the current overlaping \TrackSegment (from \c begin + * to \c end). + *
    • \c data2 : the DataNegociate of the overlaping \TrackSegment. + *
    • \c segment3 : a \TrackSegment perpandicular to \c segment2. + *
    + */ + + /* \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 hard overlap, 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. diff --git a/kite/doc/Session.dox b/kite/doc/Session.dox new file mode 100644 index 00000000..45ca9041 --- /dev/null +++ b/kite/doc/Session.dox @@ -0,0 +1,133 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \class Session + * \brief Kite update Session (\b API). + * + * Session extend the Katabatic update session to the Kite + * router level. Mainly by managing Track update. + * + * For details on how Katabatic Sessions works, have a look to + * \ref katabaticSession. + * + * + * \section secSessionMechanism The Session Mechanism. + * + * Delayed modification procedure : + *
      + *
    1. Modifications events are recorded into the Session. + * At this step, no modification are actually done, the + * data-base retains it's previous state and coherency. + *
    2. The Revalidate() procedure is called (or the Session + * is closed), then all the modification events are applied. + * the data-base is in it's new state. + *
    + * + * + * \section secKiteSessionRevalidate The Revalidate Algorithm. + * + * Revalidation steps : + *
      + *
    1. process all remove events. detach TrackSegment from + * their Track, but do not remove the pointer from the + * internal \vector. + *
    2. Pack all Track in which removal have took place. + *
    3. process all insert events. This is the time TrackSegment + * are moved into their new Track (physical displacement). + *
    4. Call the Katabatic::Session::revalidate() method. + *
    5. Recompute the canonical position of source and target + * of all invalidateds TrackSegment (take account of + * extention modifications). + *
    6. Perform a sort() on all Track that have been modifieds. + *
    + */ + + + /*! \name Accessors + */ + // \{ + + /*! \function static Session* Session::get (); + * \Return The currently opened session, \c NULL if no session has + * been opened. + */ + + /*! \function static KiteEngine* Session::getKiteEngine (); + * \Return The Kite ToolEngine associated to the current update + * session. + */ + + // \} + + + /*! \name Miscellaneous + */ + // \{ + + /*! \function bool Session::isEmpty (); + * Ensure that the Session is empty and can be closed (deleted) + * safely. + */ + + /*! \function static Session* Session::open ( KiteEngine* kite ); + * \param kite A Kite ToolEngine on which to work. + * \return A new Kite update Session. + * + * Open a new Kite update Session on the \c kite \c ToolEngine. + * At this point only one session can be opened at a time. Attempt + * to open a second one will result in an exception. + */ + + // \} + + + /*! \name Event Scheduling + */ + // \{ + + /* \function void Session::addInvalidated ( TrackSegment* segment ); + * \param segment An AutoSegment that has been moved. + * + * add \e segment to the \vector of TrackSegment for which we + * have to recompute the canonical size (i.e. extentions may + * have moved). + */ + + /*! \function void Session::addInsertEvent ( TrackSegment* segment, Track* track ); + * \param segment An AutoSegment to insert in a Track. + * \param track The Track into which the \e segment will be inserted. + * + * Schedule the insertion of \e segment into Track \e track. + * The \e segment must not already be part of a Track. + */ + + /*! \function void Session::addRemoveEvent ( TrackSegment* segment ); + * \param segment An AutoSegment to remove from a Track. + * + * Schedule the removal of \e segment from Track \e track. + */ + + /*! \function void Session::addMoveEvent ( TrackSegment* segment, Track* track ); + * \param segment An AutoSegment to move into a new Track. + * \param track The Track into which the \e segment will be moved. + * + * Schedule the displacement of \e segment into Track \e track. + */ + + /*! \function void Session::addSortEvent ( Track* track, bool forced=false ); + * \param track The Track to update. + * \param forced Force the invalidation of the \Track. + * + * Schedule the update of Track \e track. If the \Track has not been + * invalidated, no actual sort will takes place. To force a sort + * (manually invalidating the \Track), sets \b forced to \true. + * + * \see Track::pack() & Track::sort(). + */ + + // \} + + } diff --git a/kite/doc/Track.dox b/kite/doc/Track.dox new file mode 100644 index 00000000..3422d6ee --- /dev/null +++ b/kite/doc/Track.dox @@ -0,0 +1,397 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \class Track + * \brief Structure managing one routing track. + * + * \section secTrackImplementation Track Implementation + * + * Basically a Track is a sorted vector of TrackSegment, TrackSegment + * beeing a decoration of the Katabatic::AutoSegment. Managment rules : + *
      + *
    • Rule 1 : the vector of TrackSegment is sorted by + * increasing source positions. + *
    • Rule 2 : two consecutives segments TrackSegment do + * not overlap, except in case of rule 3. + *
    • Rule 3 : if they belongs to the same \Net, two + * consecutive segments can overlap, see Track::getNetUsedInterval(). + *
    + * + * \image html Track-1.png "Track Structure" + * \image latex Track-1.pdf "Track Structure" width=0.7\textwidth + * + * + * updates procedures + * + * Kite extend the Katabatic::Session mechanism to manage Track + * modifications. + * + * Indexes vs. Iterators + * + * Numerical indexes have been prefered over iterators because they can + * be used more easily by objects other the Track itself for referencing. + * So internal managment follow the same rule, handling indexes or + * reference to indexes. + * + * Looking up free/used zones + * + * The most important operation performed on a Track is to locate + * free or used zones at a given point. We uses the \STL \lower_bound + * function to find the index in the vector from a position. + * It relies heavily on the hypothesis that consecutives TrackSegment + * do not overlap, however, as segments from a same net can overlap + * the \c max() function is more complex than the \c min(). In fact + * it has to aggregate all the overlaping TrackSegment from the + * same \Net (getUsedNetInterval()). + * + * \image html Track-2.png "Track Zones - First Approach" + * \image latex Track-2.pdf "Track Zones - First Approach" width=0.7\textwidth + * + * As can be seen on the previous figure it is slightly more + * efficient to work on \c lower_bound-1 instead of \c lower_bound. + * + * \image html Track-3.png "Track Zones - Optimized" + * \image latex Track-3.pdf "Track Zones - Optimized" width=0.7\textwidth + */ + + /*! \enum Track::IndexState + * Indicates how to compute the bounds of the interval enclosing + * a given position. + * + * \note According to \e position, the interval can be a free interval + * or a used interval. + */ + + /*! \var Track::MinTrackMin + * Minimum/Source : uses the Track minimum. + */ + + /*! \var Track::MinSegmentMin + * Minimum/Source : uses the begin segment minimum (source). + */ + + /*! \var Track::MinSegmentMax + * Minimum/Source : uses the begin segment maximum (target). + */ + + /*! \var Track::MaxTrackMax + * Maximum/Target : uses the Track maximum. + */ + + /*! \var Track::MaxSegmentMin + * Maximum/Target : uses the end segment minimum (source). + */ + + /*! \var Track::MaxNextSegmentMin + * Maximum/Target : uses the next to end segment minimum (source). + */ + + /*! \var Track::MaxSegmentMax + * Maximum/Target : uses the end segment maximum (target). + */ + + /*! \var Track::BeforeFirst + * Interval type : free, before the first interval [case (1)]. + */ + + /*! \var Track::Inside + * Interval type : used, in the Track [case (2)]. + */ + + /*! \var Track::Outside + * Interval type : free, between two used TrackSegment [case (3)]. + */ + + /*! \var Track::AfterLast + * Interval type : free, after the last used TrackSegment [case (4)]. + */ + + /*! \var Track::EmptyTrack + * Interval type : free, and the Track is empty [case (5)]. + */ + + /*! \var Track::MinMask + * Mask value : used to reset all the minimal values. + */ + + /*! \var Track::MaxMask + * Mask value : used to reset all the maximal values. + */ + + /*! \var Track::NPOS; + * A special index value (greatest integer) meaning that + * an index is invalid. + */ + + + /*! \name Accessors + */ + // \{ + + /*! \function RoutingPlane* Track::getRoutingPlane () const; + * \Return The RoutingPlane owning this Track. + */ + + /*! \function KiteEngine* Track::getKiteEngine () const; + * \Return The KiteEngine owning this Track. + */ + + /*! \function RoutingPlane* Track::getIndex () const; + * \Return The index of this Track in the RoutingPlane Track vector. + */ + + /*! \function Layer* Track::getLayer () const; + * \Return The \Layer of the Track. + */ + + /*! \function DbU::Unit Track::getAxis () const; + * \Return The Axis of the Track. + */ + + /*! \function DbU::Unit Track::getMin () const; + * \Return The minimal allowed coordinate of the Track. + */ + + /*! \function DbU::Unit Track::getMax () const; + * \Return The maximal allowed coordinate of the Track. + */ + + /*! \function Track* Track::getNext () const; + * \Return The next Ttrack in the \RoutingPlane vector. That is the + * one with the axis immediatly superior. + */ + + /*! \function Track* Track::getPrevious () const; + * \Return The previous Track in the \RoutingPlane vector. That is the + * one with the axis immediatly inferior. + */ + + /*! \function size_t Track::getSize () const; + * \Return The total number of TrackSegment in the Track. + */ + + /*! \function Point Track::getPosition ( DbU::Unit position ) const; + * \Return the point at \c (position,getAxis()) for horizontal Track + * at or \c (getAxis(),position) for vertical Track. + */ + + // \} + + + /*! \name TrackSegment Accessors + */ + // \{ + + /*! \function TrackSegment* Track::getNext ( size_t& index, Net* net ) const; + * \param index Index of the starting TrackSegment. + * \param net A \Net to ignore. + * \return The next TrackSegment (\NULL if not found). + * + * find, starting from TrackSegment at \e index the next TrackSegment + * ignoring TrackSegment from \e net. \e index is modified to point + * on the returned TrackSegment. If there's no next TrackSegment (\NULL) + * then index is set to Track::NPOS. + */ + + /*! \function TrackSegment* Track::getPrevious ( size_t& index, Net* net ) const; + * \param index Index of the starting TrackSegment. + * \param net A \Net to ignore. + * \return The previous TrackSegment (\NULL if not found). + * + * find, starting from TrackSegment at \e index the previous TrackSegment + * ignoring TrackSegment from \e net. \e index is modified to point + * on the returned TrackSegment. If there's no previous TrackSegment (\NULL) + * then index is set to Track::NPOS. + */ + + /*! \function TrackSegment* Track::getNextFixed ( size_t& index ) const; + * \param index Index of the starting TrackSegment. + * \return The first previous \e Fixed TrackSegment. + * + * find, starting from TrackSegment at \e index the first previous + * with a \e Fixed attribute set. \e index is modified to point on the + * returned TrackSegment. If there's no previous TrackSegment (\NULL) + * then index is set to Track::NPOS. + */ + + /*! \function TrackSegment* Track::getSegment ( size_t index ) const; + * \param index The index of the TrackSegment. + * \return The TrackSegment at \e index. The result will be \NULL in the + * follwing cases : + *
      + *
    • \e index is outside the sorted zone. + *
    • \e index points to a hole in the Track. + *
    • \e index is equal to Track::NPOS. + *
    + */ + + /*! \function TrackSegment* Track::getSegment ( DbU::Unit position ) const; + * \param position The position where to search. + * \return The TrackSegment whose starting point is immediatly inferior to \e position. + */ + + /*! \function size_t Track::find ( const TrackSegment* segment ) const; + * \Return the \e index of \e segment inside the Track. If the \e segment do + * not belongs to the Track, return Track::NPOS. + */ + + /*! \function void Track::getIBounds ( DbU::Unit position, size_t& begin, size_t& end, unsigned int& state ) const; + * \param position The position where to search. + * \param begin Index of the starting bound. + * \param end Index of the ending bound. + * \param state how to use the returned \e indexes. + * \return The TrackSegment index around \e position. + * + * The relation between the returned \e index and the position is + * given through the \e state parameter. + * + * \note It uses the \lower_bound \STL function. + */ + + /*! \function DbU::Unit Track::getSourcePosition ( size_t index ) const; + * \Return The canonical source position of TrackSegment at index \e index. + * If \e index is equal to Track::NPOS, returns zero. + */ + + /*! \function DbU::Unit Track::getSourcePosition ( vector::iterator it ) const; + * \Return The canonical source position of TrackSegment pointed by iterator \e it. + * If \e it is equal to \c end() , returns zero. + */ + + /*! \function DbU::Unit Track::getMinimalPosition ( size_t index, unsigned int state ) const; + * \Return The minmal position (lower bound) of an interval, starting near index \e index + * with state \e state. + * + * \see Track::IndexState. + */ + + /*! \function DbU::Unit Track::getMaximalPosition ( size_t index, unsigned int state ) const; + * \Return The maximal position (upper bound) of an interval, ending near index \e index + * with state \e state. + * + * \see Track::IndexState. + */ + + /*! \function Interval Track::getFreeInterval ( DbU::Unit position, Net* net ) const; + * \param position where fo find a free interval. + * \param net for which net to find the free interval. + * \return The longuest free interval enclosing \e position (may be empty). + */ + + /*! \function Interval Track::expandUsedInterval ( size_t& begin, size_t& end ) const; + * \param begin index on any of the overlaping TrackSegment. This value + * is then modified to point on the lower TrackSegment of the set. + * \param end initial value is ignored. sets to the index of the rightmost + * extended TrackSegment of the set (i.e. the one setting the + * upper bound). + * \return the whole interval used by a set of overlaping TrackSegment. + * + * \image html Track-4.png "Overlap - Example 1" + * \image html Track-5.png "Overlap - Example 2" + * \image latex Track-4.pdf "Overlap - Example 1" width=0.7\textwidth + * \image latex Track-5.pdf "Overlap - Example 2" width=0.7\textwidth + */ + + /*! \function Interval Track::expandFreeInterval ( size_t& begin, size_t& end, unsigned int state, Net* net ) const; + * \param begin the lowest used TrackSegment. + * \param end the highest used TrackSegment. + * \param state the enclosing characterics. + * \param net the for wich we seek place. + * \Return The longuest free interval between \c ]begin,end[ . + * + * \note \c ]begin,end[ must define a free interval between two TrackSegment. + */ + + /*! \function void Track::_check ( const char* message=NULL ) const; + * \param message An iformative message, only printed if an error occurs. + * \return \true if the Track contains no incoherencies. + * + * Perform a complete Track check. Looks for the following incoherencies : + *
      + *
    • TrackSegment do not refers this Track. + *
    • TrackSegment is detached (TrackSegment::getTrack() is \NULL). + *
    • TrackSegment is hollow, this one is very unlikely as hollow + * TrackSegment are only created for the \lower_bound. + *
    • \NULL pointers (should never occurs, nevertheless...) + *
    • And finally, call checkOverlap(). + *
    + */ + + /*! \function void Track::checkOverlap () const; + * \return the number of overlaping TrackSegment. + * + * Perform the following checks : + *
      + *
    • Two consecutive TrackSegment from different \Net must not + * overlap. + *
    • For TrackSegment starting from the same position, the + * longuest must be first. + *
    + */ + + /*! \function void Track::getOverlapBounds ( Interval interval, size_t& begin, size_t& end ) const; + * \param interval the overlaping interval. + * \param begin where to store the starting bound. + * \param end where to store the ending bound. + * + * find the range of TrackSegment intersecting \e interval. + * Note that when the \e interval lower bound crosses a set of + * overlaping intervals from the same \Net, the interval at + * \e begin will crosses the lower bound but some following + * of the same \Net may not. + */ + + /*! \function DbU::Unit Track::getOverlapCost ( Interval interval, Net* net, size_t begin, size_t end ) const; + * \param interval the overlaping interval. + * \param net a Net to ignore (null cost). + * \param begin the starting bound. + * \param end the ending bound. + * \return The cost of the overlap. + * + * compute the cost of the overlap of \e interval with the range + * \c [begin,end] of TrackSegment. Any TrackSegment belonging to + * \e net will be ignored. + */ + + /*! \function DbU::Unit Track::getOverlapCost ( Interval interval, Net* net ) const; + * \param interval the overlaping interval. + * \param net a Net to ignore (null cost). + * + * compute the overlap of \e interval with TrackSegment from + * the current Track, ignoring thoses belonging to \e net. + */ + + // \} + + + /*! \name Updators + */ + // \{ + + /*! \function void Track::insert ( TrackSegment* segment ); + * adds \e segment to the Track. Must only be used inside a + * TrackSession. + * + * \see TrackSession. + */ + + /*! \function size_t Track::pack (); + * \Return The number of removeds TrackSegment. + * + * Suppress all the TrackSegment that have been withdraw from the + * Track. TrackSegment must be withdraw trough the TrackSegment::detach() + * method which sets their owning Track to \NULL (the removal criterion). + */ + + /*! \function void Track::sort (); + * + * sort the the vector. Must be called \e after the Pack() method, + * so no detached TrackSegment are presents. + */ + + // \} + + } diff --git a/kite/doc/TrackCost.dox b/kite/doc/TrackCost.dox new file mode 100644 index 00000000..4d56a32f --- /dev/null +++ b/kite/doc/TrackCost.dox @@ -0,0 +1,130 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \class TrackCost + * \brief Insertion cost of a \TrackSegment in a \Track. + * + * + * The \TrackCost is not computed by itself. It has to be build by + * whoever has created it. For example Track::getOverlapCost(). + * + * + * \section secTrackCostOrdering Sorting Track costs + * + * The \TrackCost is composed of the following criterions : + *
      + *
    1. boolean \c _infinite : infinite. + *
    2. count \c _terminals : number of terminals. + *
    3. length \c _delta : overlap between requested interval and + * \TrackSegment of the \Track. + *
    4. length \c _deltaPerpand : length of perpandicular wiring needed to + * connect to this \Track. + *
    + * Criterions are listed above in decreasing lexicographical weigh order. + * + * There is also special partial ordering functor : TrackCost::CompareByDelta. + */ + + /*! \function TrackCost::TrackCost ( Track* track, const Interval& interval, size_t begin, size_t end ); + * \param track The track on which the cost is performed. + * \param interval The interval for which we want a cost. + * \param begin The index of the first overlaping \TrackSegment in the \Track. + * \param end The index of the last overlaping \TrackSegment in the \Track. + * + * Create a \TrackCost object. Constructor parameters cannot be changed + * after creation. + * + * \remark The cost is not computed by the constructor. It is computed afterward + * by any flavor of Track::getOverlapCost(). + */ + + /*! \function bool TrackCost::isInfinite () const; + * \Return The overlap include a \TrackSegment from a \GCellRoutingSet of + * higher priority, must'nt be overlaped. + */ + + /*! \function bool TrackCost::isHardOverlap () const; + * \Return The overlaped \TrackSegment cannot be shrunk to create a sufficent + * free space. See the bound interval of \TrackSegmentCost. + */ + + /*! \function bool TrackCost::isOverlap () const; + * \Return The overlaped \TrackSegment could be shrunk to create a suitable + * free space. + */ + + /*! \function bool TrackCost::isFree () const; + * \Return There is enough free space to insert the \TrackSegment. + */ + + /*! \function Track* TrackCost::getTrack () const; + * \Return The associated \Track. + */ + + /*! \function const Interval& TrackCost::getInterval () const; + * \Return The interval for which we want to compute a cost. + */ + + /*! \function size_t TrackCost::getBegin () const; + * \Return The index of the first overlaping \TrackSegment in \Track. + */ + + /*! \function size_t TrackCost::getEnd () const; + * \Return The index of the last overlaping \TrackSegment in \Track. + */ + + /*! \function unsigned int TrackCost::getTerminals () const; + * \Return The number of terminal in the interval, see TrackSegmentCost::getTerminals(). + */ + + /*! \function DbU::Unit TrackCost::getDelta () const; + * \Return The amount of overlaping between the interval and the \TrackSegments + * already in the \Track. + */ + + /*! \function DbU::Unit TrackCost::getDeltaPerpand () const; + * \Return The amount of perpandicular wirelength needed to put the to be + * inserted \TrackSegment in this \Track. + */ + + /*! \function void TrackCost::setInfinite (); + * Raise the infinite flag. + */ + + /*! \function void TrackCost::setHardOverlap (); + * Raise the hard overlap flag. + */ + + /*! \function void TrackCost::setOverlap (); + * Raise the soft overlap flag. + */ + + /*! \function void TrackCost::incTerminals ( unsigned int number ); + * \param number The number of terminal to adds. + */ + + /*! \function void TrackCost::incDelta ( DbU::Unit delta ); + * \param delta The amount of length to add to the overlap. + */ + + /*! \function void TrackCost::incDeltaPerpand ( DbU::Unit delta ); + * \param delta Increments the perpandicular delta. + */ + + /*! \function bool operator< ( const TrackCost& lhs, const TrackCost& rhs ); + * \param lhs the left hand side operand. + * \param rhs the right hand side operand. + * \return \true if lhs < rhs, see \ref secTrackCostOrdering. + */ + + + /*! \class TrackCost::CompareByDelta + * \brief Partial compare function for \TrackCost. + * + * Allow \TrackCost sorting on the \c _delta criterion alone. + */ + + } // End of Kite namespace. diff --git a/kite/doc/TrackSegment.dox b/kite/doc/TrackSegment.dox new file mode 100644 index 00000000..cb68db85 --- /dev/null +++ b/kite/doc/TrackSegment.dox @@ -0,0 +1,170 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \typedef SegmentOverlapCostCB + * Prototype of overlap cost callback functions. + * + * \see TrackSegment::setOverlapCostCB(), TrackSegment::getOverlapCost(). + */ + + /*! \class TrackSegment + * \brief Derived Katabatic::AutoSegment for the router. + * + * We create one TrackSegment per aligned Katabatic::AutoSegment set, + * the TrackSegment is associated to the canonical one of the set. + * + * To provide some speedup, the full extention of the aligned segment + * set is computed once and stored in the TrackSegment itself. + * The drawback beeing that whenever one segment from the aligned + * set has it's extention modified, the full extention must be + * recomputed. + */ + + + /*! \name Constructors & Destructors + */ + // \{ + + /*! \function static TrackSegment* TrackSegment::create ( AutoSegment* segment, Track* track, bool& created ); + * \param segment The Katabatic AutoSegment to decorate. + * \param track A Track into which insert the TrackSegment (may be \NULL). + * \param created This flag is sets is a new TrackSegment has be created. + * \return A TrackSegment wrapped around an AutoSegment. + * + * Constructor mainly used at loading time to decorate the Katabatic + * data-base with the router attributes. + */ + + // \} + + + /*! \name Predicates + */ + // \{ + + /*! \function bool TrackSegment::isLocked () const; + * \Return \True if the TrackSegment is locked (cannot be deleted from the + * Track). + */ + + // \} + + + /*! \name Callback modifier + */ + // \{ + + /*! \function SegmentOverlapCostCB* TrackSegment::setOverlapCostCB ( SegmentOverlapCostCB* cb ); + * \param cb the new overlap cost callback. + * \return the previous overlap cost callback. + * + * sets the overlap callback. + */ + + // \} + + + /*! \name Accessors + */ + // \{ + + /*! \function Track* TrackSegment::getTrack () const; + * \Return The Track in which this TrackSegment is inserted (can be \NULL). + */ + + /*! \function size_t TrackSegment::getIndex () const; + * \Return Index of the TrackSegment inside the Track's vector. set to + * Track::NPOS if not inserted in any Track. + */ + + /*! \function unsigned long TrackSegment::getArea () const; + * \Return The priority value used for TrackSegment sorting. Currently, + * the slack of the AutoSegment. + */ + + /*! \function TrackSegment* TrackSegment::getNext () const; + * \Return The next TrackSegment in the Track (can be \NULL). + * + * \see Track::getNext(). + */ + + /*! \function TrackSegment* TrackSegment::getPrevious () const; + * \Return The previous TrackSegment in the Track (can be \NULL). + * + * \see Track::getPrevious(). + */ + + /*! \function Interval TrackSegment::getFreeInterval () const; + * \Return The free interval around this TrackSegment in the Track. + */ + + /*! \function DbU::Unit TrackSegment::getSourceCanonical () const; + * \Return The leftmost position of the associated aligned segment set. + */ + + /*! \function DbU::Unit TrackSegment::getTargetCanonical () const; + * \Return The rightmost position of the associated aligned segment set. + */ + + /*! \function DbU::Unit TrackSegment::getCanonicalInterval () const; + * \Return The canonical interval of the associated aligned segment set. + */ + + /* \function DbU::Unit TrackSegment::getOverlapCost ( Interval interval, Net* net ) const; + * \param interval the overlaping interval. + * \param net the \Net owning the overlaping interval. + * \return The cost of overlaping the TrackSegment with \e interval from \Net \e net. + */ + + // \} + + + /*! \name Modifiers + */ + // \{ + + /*! \function void TrackSegment::setLock ( bool state ); + * \param state set the Track locking state. + */ + + /*! \function void TrackSegment::setTrack ( Track* track ); + * \param track The Track the TrackSegment is assigned to. + */ + + /*! \function void TrackSegment::setIndex ( size_t index ); + * \param index The index of TrackSegment in the Track's vector. + */ + + /*! \function void TrackSegment::setArea (); + * compute the the sorting criterion used as priority, for + * now it's simply the AutoSegment's slack. + */ + + /*! \function void TrackSegment::detach (); + * remove the TrackSegment from the Track. + * + * \important This function do not update the Track itself. The + * program must take care of it under penalty of introducing + * incoherencies. + * + * \see Track::detach(). + */ + + /* \function void TrackSegment::autoInvalidate (); + * add \e this TrackSegment to the Kite level update Session. + * Something maybe buggy here, or at least not very clean. + */ + + /* \function void TrackSegment::refreshCanonical (); + * Recompute the letfmost & rightmost position of the collapsed set. + * Must be done after each modification of the TrackSegment. + * Dealt by the TrackSession mechanism. + * + */ + + // \} + + } diff --git a/kite/doc/TrackSegmentCost.dox b/kite/doc/TrackSegmentCost.dox new file mode 100644 index 00000000..9d1435bd --- /dev/null +++ b/kite/doc/TrackSegmentCost.dox @@ -0,0 +1,118 @@ + + // -*- C++ -*- + + + namespace Kite { + + /*! \class TrackSegmentCost + * \brief The cost calculator of a TrackSegment. + * + * \section secMiscAttributes Miscellaneous attributes + * + * Net instead of \TrackSegment : what we will access the most is the + * \TrackSegment owner, so it's it we keep as an attribute. The consequence + * beeing that the update member function should be given the \TrackSegment + * as argument. + * + * + * \section secBoundInterval Bound interval cost component + * + * This is the minimal interval to which the \TrackSegment can be + * shrunk without breaking the net's connexity. The interval is + * computed by AutoSegment::getTopologicalInfos(). And the computation + * is as follow : + *
      + *
    1. Each AutoContact has a constraint box which defines + * the legal area where the AutoContact could be positionned. + *
    2. The left bound is the minimum of all constraints + * boxes max. + *
    3. Conversely, the right bound is the maximum of all + * constraints boxes min. + *
    + * \image html TrackSegmentCost-1.png "Left bound & right bound" + * \image latex TrackSegmentCost-1.pdf "Left bound & right bound" width=0.6\textwidth + * + * \image html TrackSegmentCost-2.png "Maximal shrink example" + * \image latex TrackSegmentCost-2.pdf "Maximal shrink example" width=0.6\textwidth + * + * + * \section secCostAttractors Attractors and differential wirelength cost component + * + * The goal of attractors is to compute the wirelength variation whenever + * the \TrackSegment changes of supporting \Track. + * + * The \TrackSegment is connected to perpandicular \TrackSegment, attractors + * are the extremity position of those perpandicular which are not + * connected to the reference \TrackSegment. The true rule is more complex + * an is computed by AutoSegment::isTopologicalBound(). + * + * \image html TrackSegmentCost-3.png "Attractors example" + * \image latex TrackSegmentCost-3.pdf "Attractors example" width=0.6\textwidth + * + * In the attractor example, the reference horizontal \TrackSegment (in + * black) which is made of (at least) three \c AutoSegments, is connected + * to five vertical canonical \TrackSegment (labelled \e A through \e E). + * + * \e Left attractors are below the horizontal \TrackSegment axis, + * \e right ones are above. Punctual attractors are exactly on the axis. + * + * As both \TrackSegment and \c AutoSegment are orienteds, source is always + * the minimum and target always the maximum. + * + * The attractors are deduced as follow : + *
      + *
    • \e A : source is on the axis and move with it, so it is not took + * into account. Target \@2:19 is a right attractor. + *
    • \e B : not aligned due to constraints on \e A, fully included in + * \e A, do not generate attractor. + *
    • \e C : canonical is accross the reference horizontal, both source + * and target generate attractors : left \@7:6 and + * right \@7:16. + *
    • \e D : punctual, that is null-length canonical exactly on the + * axis. Generate only one attractor : punctual \@14:10 + * (i.e. not one for each extremity). + *
    • \e E : target is on the axis and move with it, so it is not took + * into account. Target \@23:4 is a left attractor. + *
    + * The concept of left/right and punctual flavor for attractors are only + * used dured construction. Once built only the coordinate remains. + * + * The extremity of perpandicular canonical \TrackSegment connected to + * the reference segment do not generate attractors because they move + * with it. But there are exception to this behavior : one is that + * the extremity is in fact anchored to a terminal and will not move. + * This is the work of the AutoSegment::isTopologicalBound() function + * to check for thoses exceptions, in which case an attractor will be + * created. + * + * + * \section secTerminalCount The terminal count cost component + * + * The number of terminals directly connected to this \TrackSegment. + * Computation relies on AutoSegment::getTerminalCount(). + */ + + /*! \function Net* TrackSegmentCost::getNet () const; + * \Return The Net owning this TrackSegment. + */ + + /*! \function unsigned int TrackSegmentCost::getTerminals () const; + * \Return The number of terminal directly connected to this \TrackSegment. + */ + + /*! \function DbU::Unit TrackSegmentCost::getWiringDelta ( DbU::Unit axis ) const; + * \param axis The axis where to put the TrackSegment. + * + * \return The total wirelengh needed for perpandicular TrackSegment to connect + * with this one sets on axis. The sum of distance to all the + * attractors. + */ + + /*! \function void TrackSegmentCost::update ( TrackSegment* trackSegment ); + * \param trackSegment the associated \TrackSegment, must be the same as used + * in the construction. + * + * Update the cost calculator after a relative position change. + */ + + } // End of Kite namespace. diff --git a/kite/doc/asimbook.cls b/kite/doc/asimbook.cls new file mode 100644 index 00000000..54270780 --- /dev/null +++ b/kite/doc/asimbook.cls @@ -0,0 +1,798 @@ +%% +%% This is file `book.cls', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% classes.dtx (with options: `book') +%% +%% This is a generated file. +%% +%% Copyright 1993 1994 1995 1996 1997 1998 1999 2000 2001 +%% The LaTeX3 Project and any individual authors listed elsewhere +%% in this file. +%% +%% This file was generated from file(s) of the LaTeX base system. +%% -------------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.2 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.2 or later is part of all distributions of LaTeX +%% version 1999/12/01 or later. +%% +%% This file may only be distributed together with a copy of the LaTeX +%% base system. You may however distribute the LaTeX base system without +%% such generated files. +%% +%% The list of all files belonging to the LaTeX base distribution is +%% given in the file `manifest.txt'. See also `legal.txt' for additional +%% information. +%% +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{asimbook} + [2005/11/21 v1.0 + ASIM LaTeX document class] +\newcommand\@ptsize{} +\newif\if@restonecol +\newif\if@titlepage +\@titlepagetrue +\newif\if@openright +\newif\if@mainmatter \@mainmattertrue +\if@compatibility\else +\DeclareOption{a4paper} + {\setlength\paperheight {297mm}% + \setlength\paperwidth {210mm}} +\DeclareOption{a5paper} + {\setlength\paperheight {210mm}% + \setlength\paperwidth {148mm}} +\DeclareOption{b5paper} + {\setlength\paperheight {250mm}% + \setlength\paperwidth {176mm}} +\DeclareOption{letterpaper} + {\setlength\paperheight {11in}% + \setlength\paperwidth {8.5in}} +\DeclareOption{legalpaper} + {\setlength\paperheight {14in}% + \setlength\paperwidth {8.5in}} +\DeclareOption{executivepaper} + {\setlength\paperheight {10.5in}% + \setlength\paperwidth {7.25in}} +\DeclareOption{landscape} + {\setlength\@tempdima {\paperheight}% + \setlength\paperheight {\paperwidth}% + \setlength\paperwidth {\@tempdima}} +\fi +\if@compatibility + \renewcommand\@ptsize{0} +\else +\DeclareOption{10pt}{\renewcommand\@ptsize{0}} +\fi +\DeclareOption{11pt}{\renewcommand\@ptsize{1}} +\DeclareOption{12pt}{\renewcommand\@ptsize{2}} +\if@compatibility\else +\DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse} +\fi +\DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue} +\DeclareOption{draft}{\setlength\overfullrule{5pt}} +\if@compatibility\else +\DeclareOption{final}{\setlength\overfullrule{0pt}} +\fi +\DeclareOption{titlepage}{\@titlepagetrue} +\if@compatibility\else +\DeclareOption{notitlepage}{\@titlepagefalse} +\fi +\if@compatibility +\@openrighttrue +\else +\DeclareOption{openright}{\@openrighttrue} +\DeclareOption{openany}{\@openrightfalse} +\fi +\if@compatibility\else +\DeclareOption{onecolumn}{\@twocolumnfalse} +\fi +\DeclareOption{twocolumn}{\@twocolumntrue} +\DeclareOption{leqno}{\input{leqno.clo}} +\DeclareOption{fleqn}{\input{fleqn.clo}} +\DeclareOption{openbib}{% + \AtEndOfPackage{% + \renewcommand\@openbib@code{% + \advance\leftmargin\bibindent + \itemindent -\bibindent + \listparindent \itemindent + \parsep \z@ + }% + \renewcommand\newblock{\par}}% +} +\ExecuteOptions{letterpaper,10pt,twoside,onecolumn,final,openright} +\ProcessOptions +\input{bk1\@ptsize.clo} +\setlength\lineskip{1\p@} +\setlength\normallineskip{1\p@} +\renewcommand\baselinestretch{} +\setlength\parskip{0\p@ \@plus \p@} +\@lowpenalty 51 +\@medpenalty 151 +\@highpenalty 301 +\setcounter{topnumber}{2} +\renewcommand\topfraction{.7} +\setcounter{bottomnumber}{1} +\renewcommand\bottomfraction{.3} +\setcounter{totalnumber}{3} +\renewcommand\textfraction{.2} +\renewcommand\floatpagefraction{.5} +\setcounter{dbltopnumber}{2} +\renewcommand\dbltopfraction{.7} +\renewcommand\dblfloatpagefraction{.5} +%%%% Select Chapter font. +\newcommand \textchapter [1] {\textsf{\textbf{#1}}} +\newcommand \fontchapter {\sffamily \bfseries} +\if@twoside + \def\ps@headings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{\thepage\hfil\slshape\leftmark}% + \def\@oddhead{{\slshape\rightmark}\hfil\thepage}% + \let\@mkboth\markboth + \def\chaptermark##1{% + \markboth {\MakeUppercase{% + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \@chapapp\ \thechapter. \ % + \fi + \fi + ##1}}{}}% + \def\sectionmark##1{% + \markright {\MakeUppercase{% + \ifnum \c@secnumdepth >\z@ + \thesection. \ % + \fi + ##1}}}} +\else + \def\ps@headings{% + \let\@oddfoot\@empty + \def\@oddhead{{\slshape\rightmark}\hfil\thepage}% + \let\@mkboth\markboth + \def\chaptermark##1{% + \markright {\MakeUppercase{% + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \@chapapp\ \thechapter. \ % + \fi + \fi + ##1}}}} +\fi +\def\ps@myheadings{% + \let\@oddfoot\@empty\let\@evenfoot\@empty + \def\@evenhead{\thepage\hfil\slshape\leftmark}% + \def\@oddhead{{\slshape\rightmark}\hfil\thepage}% + \let\@mkboth\@gobbletwo + \let\chaptermark\@gobble + \let\sectionmark\@gobble + } + \if@titlepage + \newcommand\maketitle{\begin{titlepage}% + \let\footnotesize\small + \let\footnoterule\relax + \let \footnote \thanks + \null\vfil + \vskip 60\p@ + \begin{center}% + {\LARGE \@title \par}% + \vskip 3em% + {\large + \lineskip .75em% + \begin{tabular}[t]{c}% + \@author + \end{tabular}\par}% + \vskip 1.5em% + {\large \@date \par}% % Set date in \large size. + \end{center}\par + \@thanks + \vfil\null + \end{titlepage}% + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +\else +\newcommand\maketitle{\par + \begingroup + \renewcommand\thefootnote{\@fnsymbol\c@footnote}% + \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}% + \long\def\@makefntext##1{\parindent 1em\noindent + \hb@xt@1.8em{% + \hss\@textsuperscript{\normalfont\@thefnmark}}##1}% + \if@twocolumn + \ifnum \col@number=\@ne + \@maketitle + \else + \twocolumn[\@maketitle]% + \fi + \else + \newpage + \global\@topnum\z@ % Prevents figures from going at top of page. + \@maketitle + \fi + \thispagestyle{plain}\@thanks + \endgroup + \setcounter{footnote}{0}% + \global\let\thanks\relax + \global\let\maketitle\relax + \global\let\@maketitle\relax + \global\let\@thanks\@empty + \global\let\@author\@empty + \global\let\@date\@empty + \global\let\@title\@empty + \global\let\title\relax + \global\let\author\relax + \global\let\date\relax + \global\let\and\relax +} +\def\@maketitle{% + \newpage + \null + \vskip 2em% + \begin{center}% + \let \footnote \thanks + {\LARGE \@title \par}% + \vskip 1.5em% + {\large + \lineskip .5em% + \begin{tabular}[t]{c}% + \@author + \end{tabular}\par}% + \vskip 1em% + {\large \@date}% + \end{center}% + \par + \vskip 1.5em} +\fi +\newcommand*\chaptermark[1]{} +\setcounter{secnumdepth}{2} +\newcounter {part} +\newcounter {chapter} +\newcounter {section}[chapter] +\newcounter {subsection}[section] +\newcounter {subsubsection}[subsection] +\newcounter {paragraph}[subsubsection] +\newcounter {subparagraph}[paragraph] +\renewcommand \thepart {\@Roman\c@part} +\renewcommand \thechapter {\@arabic\c@chapter} +\renewcommand \thesection {\thechapter.\@arabic\c@section} +\renewcommand\thesubsection {\thesection.\@arabic\c@subsection} +\renewcommand\thesubsubsection{\thesubsection .\@arabic\c@subsubsection} +\renewcommand\theparagraph {\thesubsubsection.\@arabic\c@paragraph} +\renewcommand\thesubparagraph {\theparagraph.\@arabic\c@subparagraph} +\newcommand\@chapapp{\chaptername} +\newcommand\frontmatter{% + \cleardoublepage + \@mainmatterfalse + \pagenumbering{roman}} +\newcommand\mainmatter{% + \cleardoublepage + \@mainmattertrue + \pagenumbering{arabic}} +\newcommand\backmatter{% + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \@mainmatterfalse} +\newcommand\part{% + \if@openright + \cleardoublepage + \else + \clearpage + \fi + \thispagestyle{plain}% + \if@twocolumn + \onecolumn + \@tempswatrue + \else + \@tempswafalse + \fi + \null\vfil + \secdef\@part\@spart} + +\def\@part[#1]#2{% + \ifnum \c@secnumdepth >-2\relax + \refstepcounter{part}% + \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}% + \else + \addcontentsline{toc}{part}{#1}% + \fi + \markboth{}{}% + {\centering + \interlinepenalty \@M + \normalfont + \ifnum \c@secnumdepth >-2\relax + \huge\bfseries \partname\nobreakspace\thepart + \par + \vskip 20\p@ + \fi + \Huge \bfseries #2\par}% + \@endpart} +\def\@spart#1{% + {\centering + \interlinepenalty \@M + \normalfont + \Huge \bfseries #1\par}% + \@endpart} +\def\@endpart{\vfil\newpage + \if@twoside + \if@openright + \null + \thispagestyle{empty}% + \newpage + \fi + \fi + \if@tempswa + \twocolumn + \fi} +\newcommand\chapter{\if@openright\cleardoublepage\else\clearpage\fi + \thispagestyle{plain}% + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter} +\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \refstepcounter{chapter}% + \typeout{\@chapapp\space\thechapter.}% + \addcontentsline{toc}{chapter}% + {\protect\numberline{\thechapter}#1}% + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \chaptermark{#1}% + \addtocontents{lof}{\protect\addvspace{10\p@}}% + \addtocontents{lot}{\protect\addvspace{10\p@}}% + \if@twocolumn + \@topnewpage[\@makechapterhead{#2}]% + \else + \@makechapterhead{#2}% + \@afterheading + \fi} +%%%%\def\@makechapterhead#1{% +%%%% \vspace*{50\p@}% +%%%% {\parindent \z@ \raggedright \normalfont +%%%% \ifnum \c@secnumdepth >\m@ne +%%%% \if@mainmatter +%%%% \huge\bfseries \@chapapp\space \thechapter +%%%% \par\nobreak +%%%% \vskip 20\p@ +%%%% \fi +%%%% \fi +%%%% \interlinepenalty\@M +%%%% \Huge \bfseries #1\par\nobreak +%%%% \vskip 40\p@ +%%%% }} + \newlength \titlewidth + \setlength \titlewidth {\textwidth} + \addtolength \titlewidth {\marginparwidth} + \addtolength \titlewidth {\marginparsep} + \def\@makechapterhead#1{% + \vspace*{50\p@}% + {\parindent \z@ \raggedleft \fontchapter + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \huge \@chapapp\space \thechapter + \par\nobreak + \vskip 20\p@ + \fi + \fi + \interlinepenalty\@M + \hsize=\titlewidth + \Huge #1 \par\nobreak + \hsize=\textwidth + \vskip 40\p@ + }} +\def\@schapter#1{\if@twocolumn + \@topnewpage[\@makeschapterhead{#1}]% + \else + \@makeschapterhead{#1}% + \@afterheading + \fi} +%%%%\def\@makeschapterhead#1{% +%%%% \vspace*{50\p@}% +%%%% {\parindent \z@ \raggedright +%%%% \normalfont +%%%% \interlinepenalty\@M +%%%% \Huge \bfseries #1\par\nobreak +%%%% \vskip 40\p@ +%%%% }} + \def\@makeschapterhead#1{% + \vspace*{50\p@}% + {\parindent \z@ \raggedright + \normalfont + \interlinepenalty\@M + \hsize=\titlewidth + \flushright + \Huge \bfseries #1\par\nobreak + \hsize=\textwidth + \vskip 40\p@ + }} +\newcommand\section{\@startsection {section}{1}{\z@}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {2.3ex \@plus.2ex}% + {\normalfont\Large\bfseries}} +\newcommand\subsection{\@startsection{subsection}{2}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\large\bfseries}} +\newcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}% + {-3.25ex\@plus -1ex \@minus -.2ex}% + {1.5ex \@plus .2ex}% + {\normalfont\normalsize\bfseries}} +\newcommand\paragraph{\@startsection{paragraph}{4}{\z@}% + {3.25ex \@plus1ex \@minus.2ex}% + {-1em}% + {\normalfont\normalsize\bfseries}} +\newcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}% + {3.25ex \@plus1ex \@minus .2ex}% + {-1em}% + {\normalfont\normalsize\bfseries}} +\if@twocolumn + \setlength\leftmargini {2em} +\else + \setlength\leftmargini {2.5em} +\fi +\leftmargin \leftmargini +\setlength\leftmarginii {2.2em} +\setlength\leftmarginiii {1.87em} +\setlength\leftmarginiv {1.7em} +\if@twocolumn + \setlength\leftmarginv {.5em} + \setlength\leftmarginvi {.5em} +\else + \setlength\leftmarginv {1em} + \setlength\leftmarginvi {1em} +\fi +\setlength \labelsep {.5em} +\setlength \labelwidth{\leftmargini} +\addtolength\labelwidth{-\labelsep} +\@beginparpenalty -\@lowpenalty +\@endparpenalty -\@lowpenalty +\@itempenalty -\@lowpenalty +\renewcommand\theenumi{\@arabic\c@enumi} +\renewcommand\theenumii{\@alph\c@enumii} +\renewcommand\theenumiii{\@roman\c@enumiii} +\renewcommand\theenumiv{\@Alph\c@enumiv} +\newcommand\labelenumi{\theenumi.} +\newcommand\labelenumii{(\theenumii)} +\newcommand\labelenumiii{\theenumiii.} +\newcommand\labelenumiv{\theenumiv.} +\renewcommand\p@enumii{\theenumi} +\renewcommand\p@enumiii{\theenumi(\theenumii)} +\renewcommand\p@enumiv{\p@enumiii\theenumiii} +\newcommand\labelitemi{\textbullet} +\newcommand\labelitemii{\normalfont\bfseries \textendash} +\newcommand\labelitemiii{\textasteriskcentered} +\newcommand\labelitemiv{\textperiodcentered} +\newenvironment{description} + {\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + {\endlist} +\newcommand*\descriptionlabel[1]{\hspace\labelsep + \normalfont\bfseries #1} +\newenvironment{verse} + {\let\\\@centercr + \list{}{\itemsep \z@ + \itemindent -1.5em% + \listparindent\itemindent + \rightmargin \leftmargin + \advance\leftmargin 1.5em}% + \item\relax} + {\endlist} +\newenvironment{quotation} + {\list{}{\listparindent 1.5em% + \itemindent \listparindent + \rightmargin \leftmargin + \parsep \z@ \@plus\p@}% + \item\relax} + {\endlist} +\newenvironment{quote} + {\list{}{\rightmargin\leftmargin}% + \item\relax} + {\endlist} +\if@compatibility +\newenvironment{titlepage} + {% + \cleardoublepage + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse\newpage + \fi + \thispagestyle{empty}% + \setcounter{page}\z@ + }% + {\if@restonecol\twocolumn \else \newpage \fi + } +\else +\newenvironment{titlepage} + {% + \cleardoublepage + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse\newpage + \fi + \thispagestyle{empty}% + \setcounter{page}\@ne + }% + {\if@restonecol\twocolumn \else \newpage \fi + \if@twoside\else + \setcounter{page}\@ne + \fi + } +\fi +\newcommand\appendix{\par + \setcounter{chapter}{0}% + \setcounter{section}{0}% + \gdef\@chapapp{\appendixname}% + \gdef\thechapter{\@Alph\c@chapter}} +\setlength\arraycolsep{5\p@} +\setlength\tabcolsep{6\p@} +\setlength\arrayrulewidth{.4\p@} +\setlength\doublerulesep{2\p@} +\setlength\tabbingsep{\labelsep} +\skip\@mpfootins = \skip\footins +\setlength\fboxsep{3\p@} +\setlength\fboxrule{.4\p@} +\@addtoreset {equation}{chapter} +\renewcommand\theequation + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@equation} +\newcounter{figure}[chapter] +\renewcommand \thefigure + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@figure} +\def\fps@figure{tbp} +\def\ftype@figure{1} +\def\ext@figure{lof} +\def\fnum@figure{\figurename\nobreakspace\thefigure} +\newenvironment{figure} + {\@float{figure}} + {\end@float} +\newenvironment{figure*} + {\@dblfloat{figure}} + {\end@dblfloat} +\newcounter{table}[chapter] +\renewcommand \thetable + {\ifnum \c@chapter>\z@ \thechapter.\fi \@arabic\c@table} +\def\fps@table{tbp} +\def\ftype@table{2} +\def\ext@table{lot} +\def\fnum@table{\tablename\nobreakspace\thetable} +\newenvironment{table} + {\@float{table}} + {\end@float} +\newenvironment{table*} + {\@dblfloat{table}} + {\end@dblfloat} +\newlength\abovecaptionskip +\newlength\belowcaptionskip +\setlength\abovecaptionskip{10\p@} +\setlength\belowcaptionskip{0\p@} +\long\def\@makecaption#1#2{% + \vskip\abovecaptionskip + \sbox\@tempboxa{#1: #2}% + \ifdim \wd\@tempboxa >\hsize + #1: #2\par + \else + \global \@minipagefalse + \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}% + \fi + \vskip\belowcaptionskip} +\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} +\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} +\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} +\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} +\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} +\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} +\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} +\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal} +\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal} +\newcommand\@pnumwidth{1.55em} +\newcommand\@tocrmarg{2.55em} +\newcommand\@dotsep{4.5} +\setcounter{tocdepth}{2} +\newcommand\tableofcontents{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\contentsname + \@mkboth{% + \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% + \@starttoc{toc}% + \if@restonecol\twocolumn\fi + } +\newcommand*\l@part[2]{% + \ifnum \c@tocdepth >-2\relax + \addpenalty{-\@highpenalty}% + \addvspace{2.25em \@plus\p@}% + \setlength\@tempdima{3em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + {\leavevmode + \large \bfseries #1\hfil \hb@xt@\@pnumwidth{\hss #2}}\par + \nobreak + \global\@nobreaktrue + \everypar{\global\@nobreakfalse\everypar{}}% + \endgroup + \fi} +%%%%\newcommand*\l@chapter[2]{% +%%%% \ifnum \c@tocdepth >\m@ne +%%%% \addpenalty{-\@highpenalty}% +%%%% \vskip 1.0em \@plus\p@ +%%%% \setlength\@tempdima{1.5em}% +%%%% \begingroup +%%%% \parindent \z@ \rightskip \@pnumwidth +%%%% \parfillskip -\@pnumwidth +%%%% \leavevmode \bfseries +%%%% \advance\leftskip\@tempdima +%%%% \hskip -\leftskip +%%%% #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par +%%%% \penalty\@highpenalty +%%%% \endgroup +%%%% \fi} +\newcommand\l@chapter[2]{% + \ifnum \c@tocdepth >\m@ne + \addpenalty{-\@highpenalty}% + \vskip 1.0em \@plus\p@ + \setlength\@tempdima{1.5em}% + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \fontchapter + \advance\leftskip\@tempdima + \hskip -\leftskip + #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par + \penalty\@highpenalty + \endgroup + \fi} +\newcommand*\l@section{\@dottedtocline{1}{1.5em}{2.3em}} +\newcommand*\l@subsection{\@dottedtocline{2}{3.8em}{3.2em}} +\newcommand*\l@subsubsection{\@dottedtocline{3}{7.0em}{4.1em}} +\newcommand*\l@paragraph{\@dottedtocline{4}{10em}{5em}} +\newcommand*\l@subparagraph{\@dottedtocline{5}{12em}{6em}} +\newcommand\listoffigures{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\listfigurename}% + \@mkboth{\MakeUppercase\listfigurename}% + {\MakeUppercase\listfigurename}% + \@starttoc{lof}% + \if@restonecol\twocolumn\fi + } +\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}} +\newcommand\listoftables{% + \if@twocolumn + \@restonecoltrue\onecolumn + \else + \@restonecolfalse + \fi + \chapter*{\listtablename}% + \@mkboth{% + \MakeUppercase\listtablename}% + {\MakeUppercase\listtablename}% + \@starttoc{lot}% + \if@restonecol\twocolumn\fi + } +\let\l@table\l@figure +\newdimen\bibindent +\setlength\bibindent{1.5em} +\newenvironment{thebibliography}[1] + {\chapter*{\bibname}% + \@mkboth{\MakeUppercase\bibname}{\MakeUppercase\bibname}% + \list{\@biblabel{\@arabic\c@enumiv}}% + {\settowidth\labelwidth{\@biblabel{#1}}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \@openbib@code + \usecounter{enumiv}% + \let\p@enumiv\@empty + \renewcommand\theenumiv{\@arabic\c@enumiv}}% + \sloppy + \clubpenalty4000 + \@clubpenalty \clubpenalty + \widowpenalty4000% + \sfcode`\.\@m} + {\def\@noitemerr + {\@latex@warning{Empty `thebibliography' environment}}% + \endlist} +\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em} +\let\@openbib@code\@empty +\newenvironment{theindex} + {\if@twocolumn + \@restonecolfalse + \else + \@restonecoltrue + \fi + \columnseprule \z@ + \columnsep 35\p@ + \twocolumn[\@makeschapterhead{\indexname}]% + \@mkboth{\MakeUppercase\indexname}% + {\MakeUppercase\indexname}% + \thispagestyle{plain}\parindent\z@ + \parskip\z@ \@plus .3\p@\relax + \let\item\@idxitem} + {\if@restonecol\onecolumn\else\clearpage\fi} +\newcommand\@idxitem{\par\hangindent 40\p@} +\newcommand\subitem{\@idxitem \hspace*{20\p@}} +\newcommand\subsubitem{\@idxitem \hspace*{30\p@}} +\newcommand\indexspace{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax} +\renewcommand\footnoterule{% + \kern-3\p@ + \hrule\@width.4\columnwidth + \kern2.6\p@} +\@addtoreset{footnote}{chapter} +\newcommand\@makefntext[1]{% + \parindent 1em% + \noindent + \hb@xt@1.8em{\hss\@makefnmark}#1} +\newcommand\contentsname{Contents} +\newcommand\listfigurename{List of Figures} +\newcommand\listtablename{List of Tables} +\newcommand\bibname{Bibliography} +\newcommand\indexname{Index} +\newcommand\figurename{Figure} +\newcommand\tablename{Table} +\newcommand\partname{Part} +\newcommand\chaptername{Chapter} +\newcommand\appendixname{Appendix} +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} +\setlength\columnsep{10\p@} +\setlength\columnseprule{0\p@} +\pagestyle{headings} +\pagenumbering{arabic} +\if@twoside +\else + \raggedbottom +\fi +\if@twocolumn + \twocolumn + \sloppy + \flushbottom +\else + \onecolumn +\fi +\endinput +%% +%% End of file `book.cls'. diff --git a/kite/doc/doxyfile b/kite/doc/doxyfile new file mode 100644 index 00000000..a51583ff --- /dev/null +++ b/kite/doc/doxyfile @@ -0,0 +1,286 @@ +# Doxyfile 1.3.4 + +# -------------------------------------------------------------------- +# Project related configuration options + +PROJECT_NAME = "Kite - Detailed Router" +PROJECT_NUMBER = 1.0 +OUTPUT_DIRECTORY = . +OUTPUT_LANGUAGE = English +#USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +#DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 2 +ALIASES = "function=\fn"\ + "important=\par Important:\n"\ + "remark=\par Remark:\n"\ + "Return=Returns:"\ + "True=\b True"\ + "true=\b true"\ + "False=\b False"\ + "false=\b false"\ + "VERTICAL=\b VERTICAL"\ + "HORIZONTAL=\b HORIZONTAL"\ + "NULL=\c NULL"\ + "vector=\c vector"\ + "lower_bound=\c lower_bound"\ + "Collection=\c Collection"\ + "Collections=\c Collections"\ + "Interval=\c Interval"\ + "interval=\c interval"\ + "Box=\c Box"\ + "box=\c box"\ + "Layer=\c Layer"\ + "Layers=\c Layers"\ + "Net=\c Net"\ + "Nets=\c Nets"\ + "Pin=\c Pin"\ + "Pins=\c Pins"\ + "Plug=\c Plug"\ + "Plugs=\c Plugs"\ + "RoutingPad=\c RoutingPad"\ + "RoutingPads=\c RoutingPads"\ + "Cell=\c Cell"\ + "Cells=\c Cells"\ + "CEngine=\c CEngine"\ + "CEngines=\c CEngines"\ + "GCell=\c GCell"\ + "GCells=\c GCells"\ + "GCellRoutingSet=\c GCellRoutingSet"\ + "RoutingPlane=\c RoutingPlane"\ + "RoutingPlanes=\c RoutingPlanes"\ + "TrackSegment=\c TrackSegment"\ + "TrackSegments=\c TrackSegments"\ + "TrackSegmentCost=\c TrackSegmentCost"\ + "TrackSegmentCosts=\c TrackSegmentCosts"\ + "RoutingEvent=\c RoutingEvent"\ + "RoutingEvents=\c RoutingEvents"\ + "Track=\c Track"\ + "Tracks=\c Tracks"\ + "TrackCost=\c TrackCost"\ + "TrackCosts=\c TrackCosts"\ + "Session=\c Session"\ + "Sessions=\c Sessions"\ + "Hurricane=Hurricane"\ + "STL=STL" +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES + +# -------------------------------------------------------------------- +# Build related configuration options + +EXTRACT_ALL = NO +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_ANON_NSPACES = YES +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 1 +SHOW_USED_FILES = YES + +# -------------------------------------------------------------------- +# Configuration options related to warning and progress messages + +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +# -------------------------------------------------------------------- +# Configuration options related to the input files + +INPUT = \ + ../src/kite/TrackSegment.h ../src/TrackSegment.cpp TrackSegment.dox \ + ../src/kite/TrackSegmentCost.h ../src/TrackSegmentCost.cpp TrackSegmentCost.dox \ + ../src/kite/Track.h ../src/Track.cpp Track.dox \ + ../src/kite/TrackCost.h ../src/TrackCost.cpp TrackCost.dox \ + ../src/kite/RoutingEvent.h ../src/RoutingEvent.cpp RoutingEvent.dox \ + ../src/kite/Session.h Session.dox \ + Kite.dox + +FILE_PATTERNS = *.h \ + *.cpp \ + *.dox + +RECURSIVE = YES + +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = images +INPUT_FILTER = +FILTER_SOURCE_FILES = YES + +# -------------------------------------------------------------------- +# Configuration options related to source browsing + +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = NO +VERBATIM_HEADERS = YES + +# -------------------------------------------------------------------- +# Configuration options related to the alphabetical class index + +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = + +# -------------------------------------------------------------------- +# Configuration options related to the HTML output + +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = header.html +HTML_FOOTER = footer.html +HTML_STYLESHEET = ASIM.css +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 1 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 + +# -------------------------------------------------------------------- +# Configuration options related to the LaTeX output + +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = header.tex +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO + +# -------------------------------------------------------------------- +# Configuration options related to the RTF output + +GENERATE_RTF = YES +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = + +# -------------------------------------------------------------------- +# Configuration options related to the man page output + +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO + +# -------------------------------------------------------------------- +# Configuration options related to the XML output + +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = + +# -------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output + +GENERATE_AUTOGEN_DEF = NO + +# -------------------------------------------------------------------- +# Configuration options related to the Perl module output + +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = + +# -------------------------------------------------------------------- +# Configuration options related to the preprocessor + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = __DOXYGEN_PROCESSOR__ +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES + +# -------------------------------------------------------------------- +# Configuration options related to external references + +TAGFILES = ../../../../hurricane/doc/hurricane/html/hurricane.tag=../hurricane \ + ../../katabatic/doc/html/katabatic.tag=../katabatic +GENERATE_TAGFILE = html/kite.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl + +# -------------------------------------------------------------------- +# Configuration options related to the dot tool + +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = NO +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +#MAX_DOT_GRAPH_WIDTH = 512 +#MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES + +# -------------------------------------------------------------------- +# Configuration::addtions related to the search engine + +SEARCHENGINE = NO diff --git a/kite/doc/footer.html b/kite/doc/footer.html new file mode 100644 index 00000000..d0245539 --- /dev/null +++ b/kite/doc/footer.html @@ -0,0 +1,16 @@ +
    +
    + + + + + +
    Generated by doxygen $doxygenversion on $dateReturn to top of page
    + + + + + +
    Kite - Detailed RouterCopyright © 2008-2009 LIP6. All rights reserved
    + + diff --git a/kite/doc/header.html b/kite/doc/header.html new file mode 100644 index 00000000..bf039968 --- /dev/null +++ b/kite/doc/header.html @@ -0,0 +1,23 @@ + + + + Kite - Detailed Router: Router Documentation + + +

    Kite - Detailed Router

    +
    + + + + + + + + + + +
    SummaryConceptsNamespacesClass HierarchyClassesMember Index
    +
    +
    +
    + diff --git a/kite/doc/header.tex b/kite/doc/header.tex new file mode 100644 index 00000000..ec779312 --- /dev/null +++ b/kite/doc/header.tex @@ -0,0 +1,47 @@ + + + \documentclass[a4paper]{asimbook} + + \usepackage{a4wide} + \usepackage{makeidx} + \usepackage{fancyhdr} + \usepackage{graphicx} + \usepackage{multicol} + \usepackage{float} + \usepackage{textcomp} + \usepackage{alltt} + \usepackage{times} + \ifx\pdfoutput\undefined + \usepackage[ps2pdf,pagebackref=true,colorlinks=true,linkcolor=blue]{hyperref} + \usepackage{pspicture} + \else + \usepackage[pdftex,pagebackref=true,colorlinks=true,linkcolor=blue]{hyperref} + \fi + \usepackage{doxygen} + + \makeindex + \setcounter{tocdepth}{1} + \renewcommand{\footrulewidth}{0.4pt} + \raggedbottom + + + \begin{document} + + \begin{titlepage} + \vspace*{7cm} + \begin{center} + {\Large $projectname Reference Manual\\[1ex]\large $projectnumber }\\ + \vspace*{1cm} + {\large Generated by Doxygen $doxygenversion}\\ + \vspace*{0.5cm} + {\small $datetime}\\ + \end{center} + \end{titlepage} + + \clearemptydoublepage + \pagenumbering{roman} + + \tableofcontents + \clearemptydoublepage + + \pagenumbering{arabic} diff --git a/kite/doc/html.entry b/kite/doc/html.entry new file mode 100644 index 00000000..cbd72d89 --- /dev/null +++ b/kite/doc/html.entry @@ -0,0 +1 @@ +
  • Kite
    Detailed Router

    diff --git a/kite/doc/images/RoutingEvent-1.fig b/kite/doc/images/RoutingEvent-1.fig new file mode 100644 index 00000000..4ea3e9df --- /dev/null +++ b/kite/doc/images/RoutingEvent-1.fig @@ -0,0 +1,66 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 900 0 2700 4800 +2 2 0 0 4 7 60 -1 45 0.000 0 0 7 0 0 5 + 1650 0 1950 0 1950 1800 1650 1800 1650 0 +2 2 0 0 4 7 60 -1 45 0.000 0 0 7 0 0 5 + 1650 3000 1950 3000 1950 4800 1650 4800 1650 3000 +2 2 0 0 7 4 60 -1 38 2.000 0 0 -1 0 0 5 + 1650 1800 1950 1800 1950 3000 1650 3000 1650 1800 +4 1 4 50 -1 14 12 0.0000 4 180 1785 1800 1725 right axis weight\001 +4 1 4 50 -1 14 12 0.0000 4 180 1680 1800 3225 left axis weight\001 +-6 +6 375 0 675 4800 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 600 4800 600 3000 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 600 0 600 1800 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 600 1800 600 3000 +4 1 4 50 -1 14 12 1.5708 4 180 1470 525 4050 _perpandicular\001 +-6 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 2400 6900 2400 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 900 6900 900 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 3300 6900 3300 +2 2 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 5 + 3000 900 6900 900 6900 3300 3000 3300 3000 900 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7050 3300 8400 3300 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7050 900 8400 900 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7050 1500 7800 1500 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7125 2700 7800 2700 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 + 3 1 1.00 60.00 120.00 + 3 1 1.00 60.00 120.00 + 7725 1500 7725 2700 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 + 3 1 1.00 60.00 120.00 + 3 1 1.00 60.00 120.00 + 8325 900 8325 3300 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6900 3000 300 3000 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6900 1800 300 1800 +2 2 0 0 0 7 55 -1 10 0.000 0 0 -1 0 0 5 + 3000 1500 6900 1500 6900 2700 3000 2700 3000 1500 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 2925 2325 3075 2325 3075 2475 2925 2475 2925 2325 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 6825 2325 6975 2325 6975 2475 6825 2475 6825 2325 +4 1 0 50 -1 14 12 1.5708 4 180 840 7950 2100 _optimal\001 +4 1 0 50 -1 14 12 1.5708 4 165 1155 8550 2100 _constraint\001 diff --git a/kite/doc/images/RoutingEvent-1.pdf b/kite/doc/images/RoutingEvent-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0c663e2673300ab9d7f006273477446c2a733689 GIT binary patch literal 4367 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-1.png b/kite/doc/images/RoutingEvent-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f88287fb401c30298ce640133869e19eb16a5471 GIT binary patch literal 5564 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-10.png b/kite/doc/images/RoutingEvent-10.png new file mode 100644 index 0000000000000000000000000000000000000000..12c456bfb8578ec47600054732cf46979216b754 GIT binary patch literal 2951 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 C&02>5 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-12.fig b/kite/doc/images/RoutingEvent-12.fig new file mode 100644 index 00000000..d228bc30 --- /dev/null +++ b/kite/doc/images/RoutingEvent-12.fig @@ -0,0 +1,127 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 5925 3225 6375 3675 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 6000 3300 6300 3300 6300 3600 6000 3600 6000 3300 +4 1 0 50 -1 14 18 0.0000 4 180 165 6150 3525 b\001 +-6 +6 13125 3600 13575 4050 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 13200 3675 13500 3675 13500 3975 13200 3975 13200 3675 +4 1 0 50 -1 14 18 0.0000 4 180 165 13350 3900 b\001 +-6 +6 1725 825 2175 1275 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1800 900 2100 900 2100 1200 1800 1200 1800 900 +4 1 4 50 -1 14 18 0.0000 4 135 165 1950 1125 c\001 +-6 +6 8925 825 9375 1275 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 9000 900 9300 900 9300 1200 9000 1200 9000 900 +4 1 4 50 -1 14 18 0.0000 4 135 165 9150 1125 c\001 +-6 +6 825 3150 1275 3600 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 900 3225 1200 3225 1200 3525 900 3525 900 3225 +4 1 0 50 -1 14 18 0.0000 4 135 165 1050 3450 a\001 +-6 +6 1425 3225 1875 3975 +1 4 0 2 0 7 45 -1 20 0.000 1 0.0000 1650 3600 75 75 1575 3600 1725 3600 +2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1500 3300 1800 3900 +2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1500 3900 1800 3300 +-6 +6 8025 3150 8475 3600 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8100 3225 8400 3225 8400 3525 8100 3525 8100 3225 +4 1 0 50 -1 14 18 0.0000 4 135 165 8250 3450 a\001 +-6 +1 4 0 2 0 7 45 -1 20 0.000 1 0.0000 5400 3600 75 75 5325 3600 5475 3600 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 7800 3600 13800 3600 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 600 3600 6600 3600 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 6300 3600 4800 3600 4800 900 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 12300 600 12300 6600 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 9300 6600 9300 600 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 5100 600 5100 6600 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 2100 600 2100 6600 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 4800 600 4800 6600 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 2400 600 2400 6600 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 0 0 525 0 525 525 0 525 0 0 +2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 2.00 120.00 240.00 + 5400 3300 5400 4200 +2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 2.00 120.00 240.00 + 5400 3900 5400 3000 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 9600 600 9600 6600 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 9000 600 9000 6600 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 7800 4500 13500 4500 +2 2 0 2 0 7 45 -1 -1 0.000 0 0 -1 0 0 5 + 525 0 3525 0 3525 525 525 525 525 0 +2 2 0 2 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 0 0 14400 0 14400 7500 0 7500 0 0 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 12000 3675 12000 900 +2 1 1 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 12000 3675 13500 3675 +2 1 0 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 8925 3600 8100 3600 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 2100 900 2100 3675 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9300 900 9300 3750 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 5100 3675 5100 6300 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 12300 3750 12300 6300 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 2100 3675 5100 3675 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9300 3750 12300 3750 +2 1 0 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9600 4575 9600 6300 +2 1 0 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 900 3525 2400 3525 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 900 3600 2400 3600 +2 1 0 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 2400 3600 2400 6300 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 12000 600 12000 6600 +2 1 0 4 0 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 8100 3525 8925 3525 +2 1 1 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 3 + 8925 3600 8925 4575 9600 4575 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 1200 2100 3600 2100 3600 4800 1200 4800 1200 2100 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 3600 2100 6000 2100 6000 4800 3600 4800 3600 2100 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 8400 2100 10800 2100 10800 4800 8400 4800 8400 2100 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 10800 2100 13200 2100 13200 4800 10800 4800 10800 2100 +4 1 0 50 -1 14 24 0.0000 4 240 225 300 375 3\001 +4 0 0 45 -1 14 24 0.0000 4 315 2700 675 375 Hard Overlap\001 +4 0 0 50 -1 14 20 0.0000 4 240 4125 8400 6900 (a/horizontal) is broken.\001 +4 0 0 50 -1 14 20 0.0000 4 255 4620 8400 7200 (b/horizontal) is dislodged.\001 diff --git a/kite/doc/images/RoutingEvent-12.pdf b/kite/doc/images/RoutingEvent-12.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cf442228f67792008df0be38c72853a601a3acd1 GIT binary patch literal 3580 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 +stream +xœÍUÉnÛ0½ó+xt +D—ár-PôÒK,sqT;I+ÛˆS Ë×w8Q²#!ÒC!@zÒpö7£'YWJÖéâg»Ë•—÷ÏÂV  +’ÉÕg¡êh$Ô`¤¡Î·ÓV4Bƒ1Ò:”î3q‡RñfZÃø¢`¢g™®Ó½Ð’&Ù´Æ0îÄîƒP}@sgš,1µ/¤='jDŠSé”WŒIgF’UtˆE@˜TJÕfŽpŒÊB „ðㄈ•ÀÑ”&DMö ‘Ì¥p^”rú;ta…ðàpBÔ£“ÄQ(„™¨4'j†Še€xBþæG»—×HÎ •«´\ïð¨’×) «ªoë½X|9¶›NÝï«õ7ñi-nDD&ç +¥Ò"UÏÅ9/ñ¥mz€X9,yÚ™WN½×ºqÌ“õ»‘õˆùÿë`*œÒ¨Šõ!öBƒHäÖáÜ‹z­!îTm1”J±»¶¸+ÎÍEV¯`¶x>ú‰â¥GÌþGéAŒÅÝžöã­Iû  ¬:e«`<Öy”·D/Œ—]J‡}ȸËØÔ„É<ãæ"˜  ô~¼V½† JòØÒ(—‰º†\$í´ÒÐ-¼h`ЩAr^Ïlæ xUQÔem½lÍˉ° uÊÑhô6Æü+ ‹å·ðö¥ÆA9g˜I„6U >Ͼ¬ÿk¥d´sT_Wë*@~ÕNc'õù ½à­C •JV!3冧@t 3#za[³“^…Ü—¸Ú´„©ÃgÍøÏc~7Ù`؉œ8ÃoßÓ-?fÛíäjÛm~¥¾.W¨ß½Å5ò:?Ö_ÅâvÑ.Ž§Ç?ÇÃMw{%ŸåÝéø}{¨ +)nÄ_#1ÛÍendstream +endobj +6 0 obj +676 +endobj +4 0 obj +<> +/Contents 5 0 R +>> +endobj +3 0 obj +<< /Type /Pages /Kids [ +4 0 R +] /Count 1 +>> +endobj +1 0 obj +<> +endobj +7 0 obj +<>endobj +11 0 obj +<> +endobj +12 0 obj +<> +endobj +8 0 obj +<> +endobj +9 0 obj +<> +endobj +10 0 obj +<> +endobj +13 0 obj +<>stream + + + + + +fig2dev Version 3.2 Patchlevel 4 + +RoutingEvent-13.figjpc@lepka \(Jean-Paul Chaput\) + + + + + +endstream +endobj +2 0 obj +<>endobj +xref +0 14 +0000000000 65535 f +0000000990 00000 n +0000002842 00000 n +0000000931 00000 n +0000000780 00000 n +0000000015 00000 n +0000000761 00000 n +0000001055 00000 n +0000001176 00000 n +0000001238 00000 n +0000001305 00000 n +0000001096 00000 n +0000001126 00000 n +0000001372 00000 n +trailer +<< /Size 14 /Root 1 0 R /Info 2 0 R +/ID [<0EA112F20693973E4390FF82218EF626><0EA112F20693973E4390FF82218EF626>] +>> +startxref +3064 +%%EOF diff --git a/kite/doc/images/RoutingEvent-13.png b/kite/doc/images/RoutingEvent-13.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc702a8d5c7583ebeaf7b8c0f868228bea602f9 GIT binary patch literal 5220 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-14.fig b/kite/doc/images/RoutingEvent-14.fig new file mode 100644 index 00000000..c145c189 --- /dev/null +++ b/kite/doc/images/RoutingEvent-14.fig @@ -0,0 +1,110 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 825 3825 1275 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 900 3900 1200 3900 1200 4200 900 4200 900 3900 +4 1 0 50 -1 14 18 0.0000 4 135 165 1050 4125 a\001 +-6 +6 5925 3825 6375 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 6000 3900 6300 3900 6300 4200 6000 4200 6000 3900 +4 1 0 50 -1 14 18 0.0000 4 180 165 6150 4125 b\001 +-6 +6 13125 3825 13575 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 13200 3900 13500 3900 13500 4200 13200 4200 13200 3900 +4 1 0 50 -1 14 18 0.0000 4 180 165 13350 4125 b\001 +-6 +6 8025 3825 8475 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8100 3900 8400 3900 8400 4200 8100 4200 8100 3900 +4 1 0 50 -1 14 18 0.0000 4 135 165 8250 4125 a\001 +-6 +6 1725 1425 2175 1875 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1800 1500 2100 1500 2100 1800 1800 1800 1800 1500 +4 1 4 50 -1 14 18 0.0000 4 135 165 1950 1725 c\001 +-6 +6 8925 1425 9375 1875 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 9000 1500 9300 1500 9300 1800 9000 1800 9000 1500 +4 1 4 50 -1 14 18 0.0000 4 135 165 9150 1725 c\001 +-6 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 7800 4200 13800 4200 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 900 4200 3900 4200 3900 6900 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 6300 4200 5100 4200 5100 1500 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 13575 4200 12300 4200 12300 1500 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 8100 4200 11100 4200 11100 6900 +2 2 0 2 0 7 60 -1 -1 6.000 0 0 -1 0 0 5 + 0 0 14400 0 14400 8100 0 8100 0 0 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 1200 3000 3600 3000 3600 5400 1200 5400 1200 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 3600 3000 6000 3000 6000 5400 3600 5400 3600 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 8400 3000 10800 3000 10800 5400 8400 5400 8400 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 10800 3000 13200 3000 13200 5400 10800 5400 10800 3000 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 5100 1200 5100 7200 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 11100 1200 11100 7200 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 12300 1200 12300 7200 +2 2 0 2 0 7 45 -1 -1 0.000 0 0 -1 0 0 5 + 525 0 4500 0 4500 600 525 600 525 0 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 0 0 525 0 525 600 0 600 0 0 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 3900 1200 3900 7200 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 1800 1200 1800 7200 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 600 4200 6600 4200 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 1800 1500 1800 4275 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 4800 1200 4800 7200 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 4200 1200 4200 7200 +2 1 0 4 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4800 4275 4800 6900 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 1800 4275 4800 4275 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 4200 1500 4200 4275 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 4125 4200 4275 4200 4275 4350 4125 4350 4125 4200 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 9000 7200 9000 1200 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 11400 1200 11400 7200 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 11400 1500 11400 4275 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9000 1500 9000 3975 +2 1 0 1 4 7 60 -1 20 0.000 0 0 -1 0 0 2 + 12000 1200 12000 7200 +2 1 0 4 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 12000 4275 12000 6900 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 11400 4275 12000 4275 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9000 3975 11325 3975 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 11325 3825 11475 3825 11475 4350 11325 4350 11325 3825 +4 1 0 50 -1 14 24 0.0000 4 240 225 300 375 5\001 +4 0 0 45 -1 14 24 0.0000 4 315 3600 675 375 Self Desalignate\001 +4 0 0 50 -1 14 20 0.0000 4 255 4950 8400 7800 (c/horizontal) is desalignate.\001 diff --git a/kite/doc/images/RoutingEvent-14.pdf b/kite/doc/images/RoutingEvent-14.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c80b3d05dc22442d2ba3e5fafe703b74f6b26f5a GIT binary patch literal 3259 zcmb_feQ*@z8Ap&hE+2(jh)99gNZiD-x4UNKLRBY)NqsEFh6hsAuAXG7$WQt6Ou{I!1YZXV4;VYO9*1qq3+u zWkH87D5`$wbP`crgF=`{{I+AITkU72cYU_%{I6y{_tUNIIrVKbmL9y+dG^lU_l%3F zT|d5k-`ax5+dB^JKh;^{toX9>V&&ozNBQa2>Z|XZ{CDA*GyJQLTmM!&SjXIb@#wAL z*&Wi9p5hm~whyf7D|tj|H9oveed20o<>f=$m-!|wnw^!^x@FSWY|q8~Lk}IhXX(tB z?p{5)-Pzp<=2dU^ng8DZ^ZkS7U-Zoj^%MK*cRmWFEpK=xz0%u0dogt?H0@Z^1I7){ zsBi7c8TEO0Y(8?!h3Cv&b*)9ubY6Mlk*BY$Tpym9Jtsc-1^5k5lpynFDjJr7Lz=!=#s zGJRV@nZ36B&8G0<<%|FLJwA8MJ2xy#U)g#7*I#w-I6L)5?%`?5*0YK0 zl})$p-uGVL>V;?46Gxt&wY%b%Q;uaHT%vWXJ$Lv?m$Gfaou53sVCIs>-eW!gdbiav ze_QkOrw`|@h;BVFeLyc;f32%(;afNT^<(X|)9V)OXny;^nt5Md+x$l2_^CY~-aI`R zT2R^clf88IS2y+D%RdVHzmDj-yh+#y=1iXt>uvl_t!ME1N1+YMONGs0-v^za*Z2mQ zx({xwvwiVjyW{ARfgi5Y;_WY7llGqrFUq1nd$z`Y;r5q5p&G9abUyW1cW`&v)Ia?B z`uxF;hBsxeK3QPc?@O%O0gH)oP@nVKt%+pgb<+u$ypZ#Fe*B-i@g=4*_a_=ON1j~WClotWhH7$ILM@k z4V^KWCP9)#Z*-8gZV%8^Rc@4YU^MUsmSRmyKtL11Fs^EifHiO=g4Fy0n-`T-3J|?H z$dIl_Y&0E@#|?3lLDhmZ%kwSNnE>T8G8T$uAx|;rp`Zvk-pX@+Mqo3V zA|osur3zgjT_zL)bh4p#@yA4{ImqRn3a~t+M)j0xU^Q?INvA!Z0E1Ar#`hgvq?`xn zWOJ*2DbVafz3L#141+whP)4qrHQCIZ&BQ&3{6k#DXqTbg_U&9w`w*L|RipGe15(iF zhfSacYEc|llfei)f-Z(+*aT%@w$o!J>@<%32-hbx7;g7>ha()uRVqZ>ZktOLV_`I& z%3S|v4NPF#{Nj+Ak(eeY%iJ&0P=?r|D9Rj*?DUJafU1QBRHQ;AB1@uxYnMh9Mmp{2 zQkQfYI+IOQDC?<%Ea9fG$$}DekO|5U142yJNv9Xpx}*e4nh-w4nhhv%sZ7X{Gj&Kp z(8I9kB;tZlwG?s{d?=&B*$@$z$uQC=fYrJ8K|!HBNDC+q36Yq-I&TbcQV;_V!HrV_ zNfH_bs2b>@LE|LA1U(Z6G(26=o^X(HJUh{8^d>eAFM!M}$Q^GKrV~o;@+b-8- z!`;bPj2vq+bEq*91M1yxy{pC*kULIpGr+2r`+Y5nSPNr%2yuRQR`Z57V?u)gf&r|N zz=JaN04_h@ln(+RL*vaT2>1a?hGyiG}hi@qYp^0D8*V;Kgm z>d|~GI}VL8qb)s#kFks+YZ;+K*91w18v1hp=qjlNq8I?$tE%W51%Ckmx=abE0B0Y4 zK$W>boju=TauuQtW;XF0Z!~iyR;JYIvT!a}p}B}-t-E-{{v!XBVqsm literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-14.png b/kite/doc/images/RoutingEvent-14.png new file mode 100644 index 0000000000000000000000000000000000000000..472416bd9eee325fa7d115c3a5077967000e69b1 GIT binary patch literal 5046 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 S;I%pdt)4xhy4v-hwe{~~gf3J7 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-15.fig b/kite/doc/images/RoutingEvent-15.fig new file mode 100644 index 00000000..750401ee --- /dev/null +++ b/kite/doc/images/RoutingEvent-15.fig @@ -0,0 +1,96 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +60.00 +Single +-2 +1200 2 +6 825 3825 1275 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 900 3900 1200 3900 1200 4200 900 4200 900 3900 +4 1 0 50 -1 14 18 0.0000 4 135 165 1050 4125 a\001 +-6 +6 5925 3825 6375 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 6000 3900 6300 3900 6300 4200 6000 4200 6000 3900 +4 1 0 50 -1 14 18 0.0000 4 180 165 6150 4125 b\001 +-6 +6 13125 3825 13575 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 13200 3900 13500 3900 13500 4200 13200 4200 13200 3900 +4 1 0 50 -1 14 18 0.0000 4 180 165 13350 4125 b\001 +-6 +6 8025 3825 8475 4275 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 8100 3900 8400 3900 8400 4200 8100 4200 8100 3900 +4 1 0 50 -1 14 18 0.0000 4 135 165 8250 4125 a\001 +-6 +6 1575 2325 2025 2775 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1650 2400 1950 2400 1950 2700 1650 2700 1650 2400 +4 1 4 50 -1 14 18 0.0000 4 135 165 1800 2625 c\001 +-6 +6 8925 2325 9375 2775 +2 2 0 2 4 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 9000 2400 9300 2400 9300 2700 9000 2700 9000 2400 +4 1 4 50 -1 14 18 0.0000 4 135 165 9150 2625 c\001 +-6 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 7800 4200 13800 4200 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 900 4200 3900 4200 3900 6900 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 6300 4200 5100 4200 5100 1500 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 13575 4200 12300 4200 12300 1500 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 + 8100 4200 11100 4200 11100 6900 +2 2 0 2 0 7 60 -1 -1 6.000 0 0 -1 0 0 5 + 0 0 14400 0 14400 8100 0 8100 0 0 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 1200 3000 3600 3000 3600 5400 1200 5400 1200 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 3600 3000 6000 3000 6000 5400 3600 5400 3600 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 8400 3000 10800 3000 10800 5400 8400 5400 8400 3000 +2 2 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 5 + 10800 3000 13200 3000 13200 5400 10800 5400 10800 3000 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 5100 1200 5100 7200 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 11100 1200 11100 7200 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 12300 1200 12300 7200 +2 2 0 2 0 7 45 -1 -1 0.000 0 0 -1 0 0 5 + 525 0 4500 0 4500 600 525 600 525 0 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 0 0 525 0 525 600 0 600 0 0 +2 1 0 1 0 7 60 -1 20 0.000 0 0 -1 0 0 2 + 3900 1200 3900 7200 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 600 4200 6600 4200 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 1800 4275 4800 4275 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 4725 4125 4875 4125 4875 4875 4725 4875 4725 4125 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 1725 3225 1875 3225 1875 4350 1725 4350 1725 3225 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 8925 3225 9075 3225 9075 4350 8925 4350 8925 3225 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 11925 4125 12075 4125 12075 4875 11925 4875 11925 4125 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 6 + 9000 3675 9525 3675 9525 4275 11325 4275 11325 4575 12000 4575 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 9600 1200 9600 7200 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 11400 1200 11400 7200 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 7800 3600 13800 3600 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 7800 4500 13800 4500 +4 1 0 50 -1 14 24 0.0000 4 240 225 300 375 6\001 +4 0 0 45 -1 14 24 0.0000 4 240 2700 675 375 Self Slacken\001 +4 0 0 45 -1 14 20 0.0000 4 240 4620 9000 7800 [c/horizontal] is slackened.\001 diff --git a/kite/doc/images/RoutingEvent-15.pdf b/kite/doc/images/RoutingEvent-15.pdf new file mode 100644 index 00000000..a7af682a --- /dev/null +++ b/kite/doc/images/RoutingEvent-15.pdf @@ -0,0 +1,93 @@ +%PDF-1.4 +%Çì¢ +5 0 obj +<> +stream +xœ¥TMoÛ0 ½ëWðØ ¨+ê[×ÃÎm|+zÈòÑuuZ40`¿~$åHqëb[ 'öƒŸø(“Ô{Ý!h¾Æçj§.®#Ü”ë<üRÂÁõWe¼µàB¶°+8ƒZ¨LËÐý\ +Rpö"Š&b" #BnÂÊ{ƒqžðÚÏÁå×ðµ¿SœÆêÈ{töˆµýü³"„F®!3L ‰6WBp ™aJˆ±¾‚kÈ ³(E¶±ÖÛæ1ý d ·Ô•µ2‘ ÜZ [Dؤ| ×»Äo]ç5Ë”òeÇqt ÑOßz¦oE!b˜*œnÉ …9”MŽ&Ñ&dC§8$-8ú)Ž§›.cÄuò±uCpm`j,äÙ:N,ã:±&bcOf¹<·Âó&-ùÖBÓ°=+,x|¬vpÙÓé¡Z†Î@¿¥¥çܪZG_Ÿ»€ÉA¿SgËOýõ¥WW%‹ ø"Í«ÛàY^Ô¿MÕc¶U9¾¥îRü¨ºËXÕ[eê`£ã&hý" ¾£è9 {Í·jù8Œî{¿¦¨{çgÔå¬NíÔûzºÇcïп¶€æ¹£ke<1°bÆ”ù¸h4Œ'þSÜ;57ÍLòUckNnÉÈ-úžxCý›öÕr™m§},Z™IÞ$Ialò+ò¼´Ã®x±¶°–«‡Í#§¾$p9“sœ;ꆇ~­ÎnVߟö÷¿Ÿ.‡[¸?À¡ÄmÖ]ÝÝ•ú$mFendstream +endobj +6 0 obj +562 +endobj +4 0 obj +<> +/Contents 5 0 R +>> +endobj +3 0 obj +<< /Type /Pages /Kids [ +4 0 R +] /Count 1 +>> +endobj +1 0 obj +<> +endobj +7 0 obj +<>endobj +9 0 obj +<> +endobj +10 0 obj +<> +endobj +8 0 obj +<> +endobj +11 0 obj +<>stream + + + + + +fig2dev Version 3.2 Patchlevel 4 + +RoutingEvent-15.figjpc@lepka \(Jean-Paul Chaput\) + + + + + +endstream +endobj +2 0 obj +<>endobj +xref +0 12 +0000000000 65535 f +0000000875 00000 n +0000002577 00000 n +0000000816 00000 n +0000000666 00000 n +0000000015 00000 n +0000000647 00000 n +0000000940 00000 n +0000001040 00000 n +0000000981 00000 n +0000001010 00000 n +0000001107 00000 n +trailer +<< /Size 12 /Root 1 0 R /Info 2 0 R +/ID [<78D2C3B92E435ABC4DEAFD28D69952A8><78D2C3B92E435ABC4DEAFD28D69952A8>] +>> +startxref +2799 +%%EOF diff --git a/kite/doc/images/RoutingEvent-15.png b/kite/doc/images/RoutingEvent-15.png new file mode 100644 index 0000000000000000000000000000000000000000..c2e3d1d425cf9c51675df2c5dc7f8e7dff170f73 GIT binary patch literal 5077 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/RoutingEvent-2.fig b/kite/doc/images/RoutingEvent-2.fig new file mode 100644 index 00000000..b554b66b --- /dev/null +++ b/kite/doc/images/RoutingEvent-2.fig @@ -0,0 +1,82 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 2100 7350 2325 8100 +4 1 4 50 -1 15 18 1.5708 4 165 660 2325 7725 Free\001 +-6 +6 7500 3600 7725 4350 +4 1 4 50 -1 15 18 1.5708 4 165 660 7725 3975 Free\001 +-6 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 8400 6600 1125 6600 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6900 5400 1125 5400 +2 1 0 2 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 1800 1575 1800 9900 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 1800 1575 1800 5400 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 1200 4200 1200 5400 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1200 5400 1200 6600 +2 1 0 1 4 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 1200 8400 1200 6600 +2 4 0 2 0 7 45 -1 -1 6.000 0 0 7 0 0 5 + 3150 6150 3150 5850 1650 5850 1650 6150 3150 6150 +2 4 0 2 0 7 45 -1 -1 6.000 0 0 7 0 0 5 + 8325 6150 8325 5850 6750 5850 6750 6150 8325 6150 +2 2 1 0 4 7 60 -1 45 2.000 0 0 -1 0 0 5 + 2100 1500 2400 1500 2400 5400 2100 5400 2100 1500 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 8100 6000 8100 2700 +2 1 0 2 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 8100 1500 8100 9900 +2 1 1 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 8100 6675 8100 9900 +2 1 0 4 4 7 50 -1 -1 10.000 0 0 -1 0 0 4 + 1650 5325 1650 5400 1950 5400 1950 5325 +2 1 0 4 4 7 50 -1 -1 10.000 0 0 -1 0 0 4 + 7950 6675 7950 6600 8250 6600 8250 6675 +2 2 0 0 7 4 60 -1 38 2.000 0 0 -1 0 0 5 + 2100 5400 2400 5400 2400 9900 2100 9900 2100 5400 +2 2 0 0 7 4 60 -1 38 2.000 0 0 -1 0 0 5 + 7500 1500 7800 1500 7800 6600 7500 6600 7500 1500 +2 2 1 0 4 7 60 -1 45 2.000 0 0 -1 0 0 5 + 7500 6600 7800 6600 7800 9900 7500 9900 7500 6600 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 6000 6900 6000 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 4500 6900 4500 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3000 6900 6900 6900 +2 2 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 5 + 3000 4500 6900 4500 6900 6900 3000 6900 3000 4500 +2 2 0 0 0 7 55 -1 10 0.000 0 0 -1 0 0 5 + 3000 5100 6900 5100 6900 6300 3000 6300 3000 5100 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 1800 9300 1800 6000 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 2925 5925 3075 5925 3075 6075 2925 6075 2925 5925 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 1725 5925 1875 5925 1875 6075 1725 6075 1725 5925 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 1725 9225 1875 9225 1875 9375 1725 9375 1725 9225 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 6825 5925 6975 5925 6975 6075 6825 6075 6825 5925 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 8025 5925 8175 5925 8175 6075 8025 6075 8025 5925 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 8025 2625 8175 2625 8175 2775 8025 2775 8025 2625 +4 1 4 50 -1 14 12 1.5708 4 180 1470 1125 7575 _perpandicular\001 +4 1 0 45 -1 14 14 0.0000 4 135 270 7500 6075 AC\001 +4 1 0 45 -1 14 14 0.0000 4 135 270 2400 6075 AC\001 +4 1 4 45 -1 14 18 1.5708 4 180 825 1725 1950 Track\001 +4 1 4 45 -1 14 18 1.5708 4 180 825 8025 1950 Track\001 diff --git a/kite/doc/images/RoutingEvent-2.pdf b/kite/doc/images/RoutingEvent-2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..47a7e05bc45c0b169c08496cf34ddd37dc2a5ae1 GIT binary patch literal 4559 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 bzv{zZb@IPO2jhqjGVHtdn-)d>nGyd6MT7YH literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-1.fig b/kite/doc/images/Track-1.fig new file mode 100644 index 00000000..0bf2e96e --- /dev/null +++ b/kite/doc/images/Track-1.fig @@ -0,0 +1,87 @@ +#FIG 3.2 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 495 405 4320 6120 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 1800 585 45 45 1755 585 1845 585 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 2250 585 45 45 2205 585 2295 585 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 2700 585 45 45 2655 585 2745 585 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 3150 585 45 45 3105 585 3195 585 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 3600 585 45 45 3555 585 3645 585 +1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 4050 585 45 45 4005 585 4095 585 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2025 450 2025 675 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2475 450 2475 675 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2925 450 2925 675 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3375 450 3375 675 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3825 450 3825 675 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 3600 630 3600 1755 +2 2 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5 + 3375 1755 3825 1755 3825 4680 3375 4680 3375 1755 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 3150 630 3150 1710 +2 2 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5 + 2925 1710 3375 1710 3375 4635 2925 4635 2925 1710 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 2700 630 2700 1665 +2 2 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5 + 2475 1665 2925 1665 2925 4590 2475 4590 2475 1665 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 2250 630 2250 1620 +2 2 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5 + 2025 1620 2475 1620 2475 4545 2025 4545 2025 1620 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 1800 630 1800 1575 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 3375 5175 3150 4680 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 3375 5175 3600 4725 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1575 1575 2025 1575 2025 4500 1575 4500 1575 1575 +2 1 0 3 0 7 60 -1 10 0.000 0 0 -1 1 0 2 + 3 1 2.00 120.00 240.00 + 1575 5850 4275 5850 +2 1 0 3 0 7 60 -1 10 0.000 0 0 -1 0 0 2 + 1575 5805 1575 5895 +2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 + 3 0 1.00 60.00 120.00 + 4050 630 4050 1800 +2 2 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 5 + 3825 1800 4275 1800 4275 4725 3825 4725 3825 1800 +2 2 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1575 450 4275 450 4275 675 1575 675 1575 450 +4 2 0 50 -1 14 12 0.0000 4 165 945 1440 630 _segments\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 3555 4590 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 945 3645 3105 [32,35[\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 3105 4545 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 945 3195 3060 [31,38[\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 2655 4500 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 945 2745 3015 [12,30[\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 2205 4455 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 810 2295 2970 [8,10[\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 1755 4410 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 675 1845 2925 [5,8[\001 +4 1 0 50 -1 18 12 0.0000 4 135 825 3375 5400 same net\001 +4 0 0 50 -1 14 12 1.5708 4 180 1260 4005 4635 TrackSegment\001 +4 0 0 50 -1 14 14 1.5708 4 180 945 4095 3150 [40,45[\001 +4 1 0 50 -1 19 12 0.0000 4 180 1140 2925 6075 sorting order\001 +-6 +2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5 + 0 0 4725 0 4725 6525 0 6525 0 0 diff --git a/kite/doc/images/Track-1.pdf b/kite/doc/images/Track-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d7365f02d307e6af0fe74d1f912e22055235a268 GIT binary patch literal 2720 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-2.fig b/kite/doc/images/Track-2.fig new file mode 100644 index 00000000..0d1538f8 --- /dev/null +++ b/kite/doc/images/Track-2.fig @@ -0,0 +1,150 @@ +#FIG 3.2 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 360 855 540 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 405 900 405 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 495 900 495 1350 +-6 +6 7785 855 7965 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7830 900 7830 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7920 900 7920 1350 +-6 +6 0 0 135 720 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 113 22 68 68 68 135 68 248 68 315 23 360 + 0.000 1.000 1.000 1.000 1.000 0.000 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 113 698 68 653 68 585 68 473 68 405 23 360 + 0.000 1.000 1.000 1.000 1.000 0.000 +-6 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 1485 1935 135 135 1350 1935 1620 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 2160 1935 135 135 2025 1935 2295 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 3510 1935 135 135 3375 1935 3645 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 5310 1935 135 135 5175 1935 5445 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 6300 1935 135 135 6165 1935 6435 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 7335 1935 135 135 7200 1935 7470 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 2610 135 135 765 2610 1035 2610 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3060 135 135 765 3060 1035 3060 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3510 135 135 765 3510 1035 3510 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3960 135 135 765 3960 1035 3960 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 4410 135 135 765 4410 1035 4410 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 4860 135 135 765 4860 1035 4860 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 810 1935 135 135 675 1935 945 1935 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 315 1125 8010 1125 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 1125 1035 1800 1035 1800 1215 1125 1215 1125 1035 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 2475 1035 3600 1035 3600 1215 2475 1215 2475 1035 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 5850 1035 6750 1035 6750 1215 5850 1215 5850 1035 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 1125 0 1125 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 2475 0 2475 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 5850 0 5850 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 3375 0 3375 810 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 1125 540 1125 450 2250 450 2475 540 2250 630 1125 630 + 1125 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 2475 540 2475 450 3150 450 3375 540 3150 630 2475 630 + 2475 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 3375 540 3375 450 5625 450 5850 540 5625 630 3375 630 + 3375 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 5850 540 5850 450 7650 450 7875 540 7650 630 5850 630 + 5850 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 450 540 450 450 900 450 1125 540 900 630 450 630 + 450 540 +2 2 0 0 0 7 70 -1 19 0.000 0 0 -1 0 0 5 + 3375 990 4500 990 4500 1260 3375 1260 3375 990 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + -1575 -675 8325 -675 8325 5400 -1575 5400 -1575 -675 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 6795 945 6750 945 6750 1305 6795 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 5895 945 5850 945 5850 1305 5895 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 4545 855 4500 855 4500 1395 4545 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 3645 945 3600 945 3600 1305 3645 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 3420 855 3375 855 3375 1395 3420 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2520 945 2475 945 2475 1305 2520 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 1845 945 1800 945 1800 1305 1845 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 1170 945 1125 945 1125 1305 1170 1305 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 675 2385 4410 2385 4410 5085 675 5085 675 2385 +4 1 0 50 -1 14 12 0.0000 4 135 105 1125 -45 3\001 +4 1 0 50 -1 14 12 0.0000 4 135 105 2475 -45 9\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 3375 -45 13\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 5850 -45 24\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 810 225 [0]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 1800 225 [1]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 2925 225 [2]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 4635 225 [3]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 6975 225 [4]\001 +4 0 0 50 -1 14 12 1.5708 4 120 420 7920 0 _max\001 +4 0 0 50 -1 14 12 1.5708 4 165 420 450 0 _min\001 +4 2 0 50 -1 18 12 0.0000 4 180 1125 -90 405 lower_bound\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 810 2025 1\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 1485 2025 2\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 2160 2025 3\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 3510 2025 2\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 5310 2025 3\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 6300 2025 4\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 7335 2025 5\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 4905 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 4455 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 4005 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 3555 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 3105 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 2655 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 3105 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 540 1395 2655 _min\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 3150 ,\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 2925 3105 max(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 1440 3105 min(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 2655 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 2925 2655 min(i)\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 2700 ,\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 3555 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 4005 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 4455 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 4905 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 2925 3555 min(i)\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 2925 4005 max(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 135 540 2925 4455 _max\001 +4 0 0 50 -1 14 14 0.0000 4 135 540 2925 4905 _max\001 +4 0 0 50 -1 14 14 0.0000 4 180 1215 1440 3555 _max(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 1440 4005 min(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 1440 4455 max(i-1)\001 +4 0 0 50 -1 14 14 0.0000 4 180 540 1440 4905 _min\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 3600 ,\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 4050 ,\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 4500 ,\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 4950 ,\001 +4 1 7 40 -1 10 14 0.0000 4 135 90 900 2700 1\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 3150 2\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 3600 3\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 4050 4\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 4500 5\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 4950 6\001 diff --git a/kite/doc/images/Track-2.pdf b/kite/doc/images/Track-2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0a62cebf14f25d6aff0801f175429169a260c366 GIT binary patch literal 4361 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 KKM()WL;njp-5#9) literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-3.fig b/kite/doc/images/Track-3.fig new file mode 100644 index 00000000..6808410d --- /dev/null +++ b/kite/doc/images/Track-3.fig @@ -0,0 +1,165 @@ +#FIG 3.2 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 360 855 540 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 405 900 405 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 495 900 495 1350 +-6 +6 7785 855 7965 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7830 900 7830 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7920 900 7920 1350 +-6 +6 0 0 135 720 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 113 22 68 68 68 135 68 248 68 315 23 360 + 0.000 1.000 1.000 1.000 1.000 0.000 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 113 698 68 653 68 585 68 473 68 405 23 360 + 0.000 1.000 1.000 1.000 1.000 0.000 +-6 +6 630 1755 990 2115 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 810 1935 135 135 675 1935 945 1935 +4 1 7 40 -1 18 14 0.0000 4 150 120 810 2025 1\001 +-6 +6 1305 1755 1665 2115 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 1485 1935 135 135 1350 1935 1620 1935 +4 1 7 40 -1 18 14 0.0000 4 150 120 1485 2025 2\001 +-6 +6 1980 1755 2340 2115 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 2160 1935 135 135 2025 1935 2295 1935 +4 1 7 40 -1 18 14 0.0000 4 150 120 2160 2025 3\001 +-6 +6 3330 1755 3690 2115 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 3510 1935 135 135 3375 1935 3645 1935 +4 1 7 40 -1 18 14 0.0000 4 150 120 3510 2025 2\001 +-6 +6 5130 1755 5490 2115 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 5310 1935 135 135 5175 1935 5445 1935 +4 1 7 40 -1 18 14 0.0000 4 150 120 5310 2025 3\001 +-6 +6 675 2340 4410 4635 +6 720 2385 1080 2745 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 2565 135 135 765 2565 1035 2565 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 2655 1\001 +-6 +6 720 2835 1080 3195 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3015 135 135 765 3015 1035 3015 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 3105 2\001 +-6 +6 720 3285 1080 3645 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3465 135 135 765 3465 1035 3465 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 3555 3\001 +-6 +6 720 3735 1080 4095 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 3915 135 135 765 3915 1035 3915 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 4005 4\001 +-6 +6 720 4185 1080 4545 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 900 4365 135 135 765 4365 1035 4365 +4 1 7 40 -1 18 14 0.0000 4 150 120 900 4455 5\001 +-6 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 675 2340 4410 2340 4410 4635 675 4635 675 2340 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 3960 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 3510 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 3060 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 2610 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 3060 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 540 1395 2610 _min\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 3105 ,\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 2925 3060 max(i)\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 1440 3060 min(i)\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 2610 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 2925 2610 min(i)\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 2655 ,\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 3510 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 3960 ]\001 +4 0 0 50 -1 14 14 0.0000 4 180 1080 2925 3510 min(i+1)\001 +4 0 0 50 -1 14 14 0.0000 4 135 540 2925 3960 _max\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 1440 3510 max(i)\001 +4 0 0 50 -1 14 14 0.0000 4 180 810 1440 3960 max(i)\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 3555 ,\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 4005 ,\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 1215 4410 [\001 +4 0 0 50 -1 14 14 0.0000 4 180 540 1440 4410 _min\001 +4 0 0 50 -1 14 14 0.0000 4 60 135 2700 4455 ,\001 +4 0 0 50 -1 14 14 0.0000 4 135 540 2925 4410 _max\001 +4 0 0 50 -1 14 14 0.0000 4 180 135 4140 4410 ]\001 +-6 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 7335 1935 135 135 7200 1935 7470 1935 +1 4 0 1 0 7 50 -1 0 0.000 1 0.0000 6300 1935 135 135 6165 1935 6435 1935 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 315 1125 8010 1125 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 1125 1035 1800 1035 1800 1215 1125 1215 1125 1035 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 2475 1035 3600 1035 3600 1215 2475 1215 2475 1035 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 5850 1035 6750 1035 6750 1215 5850 1215 5850 1035 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 1125 0 1125 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 2475 0 2475 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 5850 0 5850 900 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 3375 0 3375 810 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 1125 540 1125 450 2250 450 2475 540 2250 630 1125 630 + 1125 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 2475 540 2475 450 3150 450 3375 540 3150 630 2475 630 + 2475 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 3375 540 3375 450 5625 450 5850 540 5625 630 3375 630 + 3375 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 5850 540 5850 450 7650 450 7875 540 7650 630 5850 630 + 5850 540 +2 1 0 0 0 7 60 -1 15 0.000 0 0 -1 0 0 7 + 450 540 450 450 900 450 1125 540 900 630 450 630 + 450 540 +2 2 0 0 0 7 70 -1 19 0.000 0 0 -1 0 0 5 + 3375 990 4500 990 4500 1260 3375 1260 3375 990 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + -1800 -675 8325 -675 8325 4950 -1800 4950 -1800 -675 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 1170 945 1125 945 1125 1305 1170 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 1845 945 1800 945 1800 1305 1845 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2520 945 2475 945 2475 1305 2520 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 3420 855 3375 855 3375 1395 3420 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 3645 945 3600 945 3600 1305 3645 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 4545 855 4500 855 4500 1395 4545 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 5895 945 5850 945 5850 1305 5895 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 6795 945 6750 945 6750 1305 6795 1305 +4 1 0 50 -1 14 12 0.0000 4 135 105 1125 -45 3\001 +4 1 0 50 -1 14 12 0.0000 4 135 105 2475 -45 9\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 3375 -45 13\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 5850 -45 24\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 810 225 [0]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 1800 225 [0]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 2925 225 [1]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 4635 225 [2]\001 +4 1 0 50 -1 14 12 0.0000 4 165 315 6975 225 [3]\001 +4 0 0 50 -1 14 12 1.5708 4 120 420 7920 0 _max\001 +4 0 0 50 -1 14 12 1.5708 4 165 420 450 0 _min\001 +4 2 0 50 -1 18 12 0.0000 4 180 1425 -90 405 lower_bound - 1\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 6300 2025 2\001 +4 1 7 40 -1 18 14 0.0000 4 150 120 7335 2025 4\001 diff --git a/kite/doc/images/Track-3.pdf b/kite/doc/images/Track-3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..edb754051d6f5304d76deb5398f55815bba6df1a GIT binary patch literal 3438 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 LfQpK-wF&S);vl18 literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-3.png b/kite/doc/images/Track-3.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8404b22a90f82ff99ea068fad3158758985433 GIT binary patch literal 7643 zcmeHLXH-;Kw!T1<3XoKQ2uKit0tu1?R73>3M6`^sM#Xul`YW?>+0Bd-mPu+uyhM4pCQCq=H<4002Ox ztR#;B0Kz5!AP6HP1V`Z94ISWx+(8NH3;>iWXFr0TuX(EAAiIl#o{OfvrHi|nlLerl zsm`HjZSU;j{K)CCgA0e$RS6*x(Kxp^i~zuRU0MFNmPgX+m~v%~WEF{eg<8TFThRc@ zn?y<^QI6cc6C|gczutkK01P&zyJdBZglSBismlO>#km{p9r%n3kpSu#EdCU~DhdD+ zG%z3l;35WSu8)LJOpi4I`dIV-}81whkVg`WA`+v)=;U>OvxARAz{Qa2A$lo%7BnM4X7enb(>Y z0MyDBdWgLi8+4bO9MGY9L*InJ*yGTb4FHjZg?0kVf2 z;sU2eoAU;UmNK&IFdxs~BB%}9M)aAw)fFZp0Fj;ct64whiN$%lc)^~$b0!QBe*_z} z;vfccF4}O&hk7k!0H*z7RKL=*yY@ULsO9h6H%&PYUUhvORLgi}n^dGn=&%`G3CwFx zMZGQd({hQYL~W|2I&)#@cNdFk627SU4u8Lr_%1d^Pb`O2=CTmkgi`K?8ATzL`NC_G zJL%c2+wLcJ%JJ8AuXu^fmkUYi z8Q3M-=F4x6^4v(-oHfmksvEH&H)SZdWaP>_oE|M~m4|qAY`?w|frqu|Wc96AdURhw z6B=8d!jYMt54{$HeO?qoM{S0Uhr1udcrcIaee1uMA@Bsb--DaGWpqIFw4(j_hlB$& zA`E|Z;KI>(2=&=v*U?il4I*4Rphg~qLv-h#LnWMXL;>3F;xt?e#veYy34lCWm?+l+ zKwSvUb^WUjpw5NnV!DV1mtTIf_0F8Dr#{RXA)83^L!IahfWC4+* z+j;p5Un`SoV1pV%X~Y5sNxvf7NPQX#7Rh*JfqaAAP|d6JQa#%Uzy}WRecn&c{z4uS zP|!jz0 zZD^HAk*{7^tm<>Vl)G>#Y2S3Mg$PF>!;@p{*pr|?SkC%>R`sTCU8O8snE2FDBqWY* z5HzSHlW|wD*+%VV+}BF1oG=(r92^MNl?#x)_C3D?L77It`d8yn7Pe0Mm!v>O7%RNc zE4*X#-D=*aIOh)I2mX%_k?K_@HHVyWolzlVKnYK799MUVJ#!XoioMI!hF!0xaJ1P0 zXD^d5?^8`RTc;5K;HUAKesmb$jD$<0lC7>yz5ZHt7-$kZ75%u7-TK>(6`&p*EX1X9 zEvdMqdve3;X&9xP#l;%o&$!hnxUG5|=ljMCAb_uqS2nZL{6gZOyjOg9Dy1|9M*lZ^ zS@V9YsbMD1VH&`dEDTyq8btNV@A(Yyl90=x|gu*!A$4I<&s?28EQ0z{`QivTYBgq5B*d@1$=av(2cs{nTIIxwk4XCG+`BW_WCpviRJ!(-VdIz`G?hU8cy*;e7S@Pp2of2|e(- zRn|sZSmlrHZAmgbELB3Fqo1)nZx>q6j4fo2uGfRKTACDREc~$kY=D71y5pZ__`>)S zeLG^`*<>!%(|@*94`szgE7iG5+tv;7S2~@28TjfJE0vu$ioV~>JSsf%mfzuz^qE%S z|Kw12lOK$X4&$7m_GJLnS12A+lp*5CaLO!x! zoB{;kpUJ^|ioe~Pi+s;Oa{j3_4%1KPzk|c}Oq`ku1MMdM$2)GcEqA&TuX6ra^{?JlZzQjenOkDN+q93{jF}I&*q@2KHO}9#Fks@(cGAMBY^5z` z6)xe4S)bYVKRwgT_uHVVQyg?S}{kL&J^V_~DohpqC z-vm_zZ8bxUixrq;+5aKH=Rv#`Rm#Bs)t#wv@A%sq1)ma$+mw=56c}}ZTnq|xK!LdH zj*%t>g;mHuc2rIWYRhkc&(Ask8yWxa6N2^L5n>K^-wA4eAK4Ulc+Z@Eyinw(`Q;pm z{^-^x*rLzO{grzQRh6;9e7%Bx-wvoUqw8HdP7{jsHC5i{egkRreI=7hx~b5ZdBnvL z+lc6_j(YRU7ZbXjiq-2G3+o(1L~bmXRfwztA_BGwCv6F2h`{d7L%P(1tc;d^=OlVVQJ zt%S~M4>kUB{-pg$e>YMpl!`<1uJd|T?5nYos|B%EhelQOeM>Dt*9@e~E6Y^eKH_}r zZXL)eHa&{1Fodi6V1!cyy^$}O+9Z#be4Z@2BJ(mc`^r^tHG&y&8C?;Oy$n;${^-W?Izj2UDu=VSj&}@&L^cR^1O`@avWXr%8B{Cjdi0z$`*nGr?iTWR zwg9%g-Mc3bsStAHhZ>tDUQvh|8y_ivY7KPK`yS}|R2=BE7h~8{CekDdR%GM=+^f<&wK6o6 zVqC;bsMRz!vZ8e9V8)8+rz#;1QFke>3XacjF`uwOB)x5H^5?2{l>2%%$NE23hU+J| zYH%<4*f6GwauLtZ;<#ThKRj%H^6GVRp^5;cN$5u$@ssHwYC zj3%Uf9knR}IZ&ld$>Ph|gKzfNHo05G*8y};G{yVrL^$O;**vy_0X14ru3$nr3VDc- ze)t8q(MZQZs@Wz6_7$mQy4jH6_YNEaT*OBaH=LBWc10M@%{GNlN9fnc7x$JCbh*A! zszVa~0_1=S_-BhDFxN@K_*f3sKD`BiSk^G`q!odV|VDH$@8a&jqGSODMIGkad zdsXS()y6DT$ICqVj678lZ^uffxYCj%>9+c4gncbB7qPCbgc$XCvBvF43xkU5Gi$oG zzWO1gqd75>zBVFQtYMR|0BT1puocuMX<=h^FG1`Jl(~yzE2e7lxY4P}qJX59u?E_e zk9-)P3AqWWMS8(1?4%>i4!!dDZEWa0AKplV7PZ9mvtZKWf&>T+5@voYFgQmR&+y3A zdP-ztg+B8YDqP%U`Ogf+Kqc!RFNVB~*D&>?vUkEo`tvCV8zzuH~q; z`1|#-`$jfBbgvlPvug|#M5C&iO4|{0l5z_mkJoXa2+t8;MW)_92l8 z+GBPs?0Wsec1B(2&_TVj^lk27A)}a(As3RDt=X^6q3eTrEWz6DwhaQVkn-yByAAK= z&GvDluM&bwwn0O8P`+9ZV{LtrkK4*Kdu==D^rVTkB|uLPR}Dm*Gm$A1pJ6wEnK660 zh1CpCt4;{!^IDeol*L+09>>%z22NyV1*oAN(4RBQ z&#p{htgU&F`VfTSsH4(hxV-<#rpZM~BjK07Xtl3D$X8~i($PpGed=&MX&tJ)3B*`S7&0%yn;g<6D&v@ za>s>|#`L~AExpv@xW+}yTkVZ~RH|WeQYg`e6R&bsVQ?SydD}ymvOZ^?rK9MmO(nHa zmpOOQ-)o!M51-0pZ|CtL?Q+V@w*h-nPj^!7mCxCtkkP!)SJ!igFUXXS((>Awb`2$6 zG%uO)?GsGu->ac#Pm0AFZhd)K(th>Y8EOU{Z(MGnr~ZkjT{dRPx1Qed5K^a^Mp8x8 z*ud=(5|9NQVgaz_0G70Wwj~3?iuXziv*h|DHLwkei%zoACt|rv@{rvf-%l(T(jfs& zAyAM38Nj>P5U70RnXo);bN=vyejq!CBqV|~Fr|+e3T*YjiI1#3)z-?9-%idM@5C&8 z&Z8JU%TUJL{QNv}Z%A9CJP9J4X<@q6Jw>XQzW&e@xTv?g^ng^GQ_#?~?HOd~#ky_ilA;5{2!``4WN*DTOL0{|G~+k8Cy?G`uKI zbLiuxfu~P~j-KnKf3w@>Ka?RGNI}^-n{;XHL^zpdQF8c`BlqH7huI~nrAIsDT6fbY zf8Drpw5=c6OxW1v6^-w(Eun-R;><)4^M*E83r`?2wDMg-}b*NuF~Y zjuIy7K(oMEUl4|TDf$p4d{Zao%w?*2H}xWAg8UsTCTNne)U4Fk5swx%VmB;WwN;Qb zMVAp#n|g|$mpcp`Js&!J4;pNGPwEj+2whQ1A(aSjo3wh&)$@l8+0A@9|jLcG%Upp5`Szei`pa7%=tPaO1#iXDpbg zxs(SrtoDv@5~TT4M}r3dcIsb~#($?Jf2vsv z04)utM7A<%xaEPmw_wK^P*zZt&%a|D6!L%HvnI*^ThAI-M-Fh()Yfht;ynfH131JO zW?xH)u>-ZQPu&1uo$#!ty#fj<229m!&!Xb5fxrCm7aabIhQG+*FE0Fl(*{XpN)q}x Lv39QC%jEw6G}%a^ literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-4.fig b/kite/doc/images/Track-4.fig new file mode 100644 index 00000000..23c699f6 --- /dev/null +++ b/kite/doc/images/Track-4.fig @@ -0,0 +1,83 @@ +#FIG 3.2 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 360 855 540 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 405 900 405 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 495 900 495 1350 +-6 +6 7785 855 7965 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7830 900 7830 1350 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 7920 900 7920 1350 +-6 +1 4 0 1 0 7 50 -1 -1 0.000 1 0.0000 3600 1800 90 90 3510 1800 3690 1800 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 315 1125 8010 1125 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 1395 855 1350 855 1350 1395 1395 1395 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2295 945 2250 945 2250 1305 2295 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 3195 945 3150 945 3150 1305 3195 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 4095 945 4050 945 4050 1305 4095 1305 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 4050 1035 4950 1035 4950 1215 4050 1215 4050 1035 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 2250 1035 3150 1035 3150 1215 2250 1215 2250 1035 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 7470 945 7425 945 7425 1305 7470 1305 +2 2 0 0 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 6525 1035 7425 1035 7425 1215 6525 1215 6525 1035 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 6570 945 6525 945 6525 1305 6570 1305 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 5895 855 5850 855 5850 1395 5895 1395 +2 2 0 0 0 7 70 -1 19 0.000 0 0 -1 0 0 5 + 1350 990 5850 990 5850 1260 1350 1260 1350 990 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 2250 0 2250 855 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 1350 0 1350 765 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 4050 0 4050 855 +2 1 0 2 0 7 50 -1 19 0.000 0 0 -1 0 0 2 + 6525 0 6525 855 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 3600 2250 3600 1215 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 3510 1800 2295 1800 +2 1 3 2 0 7 50 -1 -1 4.500 0 0 -1 0 0 2 + 2250 1395 2250 2250 +2 1 3 2 0 7 50 -1 -1 4.500 0 0 -1 0 0 2 + 1350 1485 1350 2250 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 3 1 1.00 60.00 120.00 + 2250 2025 1350 2025 +2 1 0 4 0 7 50 -1 -1 0.000 0 0 7 0 0 4 + 4995 945 4950 945 4950 1305 4995 1305 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 0 -675 8325 -675 8325 3375 0 3375 0 -675 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 1350 2475 1575 2700 1800 2700 3150 2700 3375 2700 3600 2925 + 0.000 1.000 1.000 1.000 1.000 0.000 +3 0 0 2 0 7 50 -1 -1 0.000 0 0 0 6 + 5850 2475 5625 2700 5400 2700 4050 2700 3825 2700 3600 2925 + 0.000 1.000 1.000 1.000 1.000 0.000 +4 1 0 50 -1 14 12 0.0000 4 135 105 1350 -45 4\001 +4 1 0 50 -1 14 12 0.0000 4 135 105 2250 -45 8\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 4050 -45 16\001 +4 1 0 50 -1 14 12 0.0000 4 135 210 6525 -45 27\001 +4 1 0 50 -1 14 12 0.0000 4 180 840 3600 2475 position\001 +4 1 0 50 -1 18 14 0.0000 4 210 2820 3600 3150 Overlaping TrackSegments\001 diff --git a/kite/doc/images/Track-4.pdf b/kite/doc/images/Track-4.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d44edafc14618ba81fc2d3edfb20b42647b553c1 GIT binary patch literal 2979 zcma)8c|25m8;@)aW9b%=<=8?r`v|9V>@m z0R+GZ41<`M!0jpY{p?V{5JX(yR#Y0B!UW(}G%}k)qy#a7DW;|n7Mn>SAB1p=u6lOT zRd7=zkH(swzkfS~tUmn<}uu$a+;lzD@-nq1yKXUfYIR34YXG@SbucmR^Kz8dp zFFxF(b4B41spX;QtXkY*)%059ePxx#j9x zTR=}ze0Ol6gtP)o)6JOBongcd zN~vLLReE==rgC`jC{{#`95(yQtB3enuO98D(NoFd@xCzJo7`}lH^F+7A`9imUImI{ zwrL(Xt97Eavdl_H>aBm$b|y}?Kfj`?Bfd&=>b#zBF2>DQIeiIHMI+2tHc8%m9M}y=1=s_d(qO8VaKT7phoZQ{! zHs9={adsv#j+1gpt7ppWj_e2pQ;Oy~$pbNgVk^KKhv;nxX?Ma0n97HKV3Ve^9IR z4O$J^%KVjsz9|CHyXdpBaEu|h{L3*T^0^{&$(X3_dRYt0BYPdpBv%J83g(*=s!t?_KN(JUG){KTl8NyB@b`< zZFCU#(3;xwsVv1PB*Js~0bxO6i(DP7Xjk31(@E#+mzA=g2Z$aXy-$aSCg%O7gd|r* z`Bu@74szu(UhWbz9r9M-CFFWT$=V+JJvvYCnztL~2f+EeMvh|gBd-MnXl-xYdayJZ z!avu$C5XrG@<)hmro!FvqyRm636i*o9ZhIa$%U=(cABZ~m zJ21JeAVK&%jW&LB!X_pBu1MIqnn0fTlLj{cF-RjPU3Mi1&!aY+Y88?&n^Autgkt^Y zd5x5WW~c*nx*Mh@5t!kaUQZ|#Yi{0HVBlP6PPY+yeLpGt-lO~NvI`?^o5F~(wVA9- zVtdH$*ryYr8zOPdie;M|?CKTOL)EriSLY3nrp7$^Fqm+{Y?)}Qf-G$kjOBWs9>K{DgPn2`i$d5VPj=kmGsiEG@;yY-+&7@{ z!==*aRg2_<^&8qnw;z{|xXXqGiix+RxcNJ~+-*q**r}U`pWKoilZ$=P;-R5lm{lgS z)vtqg1Q{kN8Qs?KQHE8P<&19M30-jV-$&hcoY()pG~=y%J6_q2@MuPOcgMa^-kIQQ zBuk#157xjvsqLEk(_dsPN-XK0TjBkQw8J77E6fcCYjVWcHBcS=#h1M^$+V zLRt?#g6ia9X{zjvg>`zS(_$A$NR2sm;-I!4PV8CDd{ye?*!HZ!%Fy!dS&9_*9Zlr8 z467T^Ci3WMx5_@KzD`O39iP6)C*qWQUjH0fOg{_+nDjucEjr%a!6_5a*GbaW48~F- z(`mDOjk!^^D!+i~Ii^spmUmm&yBy;zE#_HwjwF4dvDarxnXihT9X3j_OvBns-OglQ zicLD~TyGbdUgk+^ZrPZhP(ZG?noebDENgb>RS5MHrMi0(QZW&GiNzyb#jHoWtyU6Q zL~GTqBF*76^0@M-l6F^7MW?|;0Sj}W=75F@w8R^2WBvN@d!lhdp8j)AuUunkEY8N- zEKFW(PIt6llTVIYdx)M3uf@%$aqy?^|MYfRG6mHKs7@%j&Jay(P7kByjxBZ~--g$4 zyY7&V4(%V;v-FrQ;L83UZExar=n6N7JG>CaRawjAQA@5JI+3z;E@NWiz^f0s;&+o8 zxi{+7RBn4`pMA-39x%*a8n069s+lvuoxU>5QPQK zeAuTY@Y8TrEI0&@bSNV=Mq}M-65HJ`jQ1E)YKeWZ(!W|6wX%U*Agpv?P$(WEx}t zUlf0O|Me=|xB6ebhQJ-28~~)L>AFu}f>>vE!9fIeE?;TBMD>>x55Wtha2F$p(YI;> zd|k_e%%TVqB8Y)Wr7(9{FlfPFqWzL52%N+TWD9B{2m^HEuiOY2zo)RF&>|^pY7qJV zB|&{90c#h`38FA{ElEy*btr?yW(6^+;cNhp#KI6LJ+MsR=EkNn=tQuVx1 z5NH$viALZ-xdS8ke~bRk9hXT7fgk`R3WE6i0ESpB8ViH~>lg}!1ZyKW0R3+aivaWd z9frh$<^K*tAbzk#Adp~NeXEBw!vCO$LK%WR^Q|5Vjr$S9puy^WuZI9L`8|gI2gYWS zsWb``T#^Aei5d<53n&2Y!eD?+E9eXWZc7hg0D^LW|A#FR@X?J_&Tdy7N_rex@|d@Q e%DbocBjP9McNUw>WPeF47yurkt!?RO1^F+IH^80% literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-4.png b/kite/doc/images/Track-4.png new file mode 100644 index 0000000000000000000000000000000000000000..3903f8e0612dfddf3298cf349d159b5fd564a601 GIT binary patch literal 4174 zcmeHJc{r47AAXs#Hc>*z*up2Wj4WkI2O&`jEz@9(-B=ookr_*4DN)u*vUOCl69>nZ zCB#@dG>n}hpD_$mwhX?}>0GDteb@E;E( z006*drbbo(z-|fvY~oz(tO|CJPl`2g`)&H`Oi+>;j z?F<-Sz9?zp=Hut@heW&k`b%o7X(+2gA7V0u0D$*^nb8?*Z2H0&oS1eF6m@CC);su! zNMi@nBz~Xd2h+t3<*U)HQ@KXQPsWEg^GEzkMN`_@MSZjYuD&tvss?&5gabH|Jzukv zp~nGeCzi7D8&iNg(kQ^_fF|%Wml$v<0vz_QW)6cx2#{pVKk=BcKx11Hf)9f2KjT9e zO+|kT7(?3xA4+>a)vzC-D3X~+*0abJ8zO_1IYqTx3##}OCvy0G=8d(2Z(&7oQKe1h zZT?8Y5X_eI>_3ml(cK1(O zV~odVxp@SaZ@0#>ROa)jEY9R+dzB>#2DrWUU>_gctIiUkb{jE|dN~Wctz^TuZIy4A zWWyKY(DqG{@PsLk(KuD;dbzdUx_RC$ivb-hqLxmdc;(7B6~qxLM2Ie@2y*`}U)IYZ zJKOkGeo^OczuK{otuFzq{MViSSnE4=&v~ot1Z~h_9sx@ggGv64bK9gdPB_Sj_Q%tq z+vz%q@;E#mY|mtFd>T#Aooas|(IPy+jCL;EP((Sk6`7DP5I}=Zdy$~9S?>R8p?i|i zo7-EPLx$DqB_$<%=_{_gTiM>2%_@(6E3K}1{Y0kd{^{N3JK{T&kP_*#6^=1RLPVGf zygQAIiO$If=)5LfsyJb1TEZ<5?%H-X=LXMyD{feI@jP|xwixqTK7{$qx?XNxysq@O z_;dEp8Vw`jqTXQ}LD=M1NRsu65VMFt-wa8us-Lqf4DwDX>B#3it%}SsW>bMXkYFw- zQc=_bmqEF$z*2*9YT4Kodfu70k}6jtjuQtp-^%U!K)JNmNo6h;Z_a-O&++6mP+>+n zm#>d(pf-VYEq*7Q7PDvg=&mp-uih_X^Ez00F!&RY|5Yk~Ol2{~?A9g}$2=(O3yNim z2eVH#3z?^cYktM=I1!05c+A=WJb^V7y?!d+`*yQ}3h$ouNWR%W;S^mkerJEZ41|0^H06Gh4De_82Xhf<%?s7U(Wq3xWvb zB-jfa=7yPdY2NeVJRiDhB=k{Wq zq*CDtvX%He-Ix65DUL%J&@LMCLVy1IuFJNfW5I4orFt&fmzlInK&cr8Gq1nM1SHOmYp$I!(&weniNX5WktbO46`M3wU3tt{vs?SacHH0CjrPTv@)zZvP)cb8BUsg2Jv4Z?=lO7_KVk1Zrc;L`vjUyDx0Ck$rfH zr#JqMXOlptq~IXjvANE4}qdB9dNhtr?fyvL}_)-=E~U5fo7%=AovE z6n#Jzs}1cIdYN7yXP&t|&yeR``-Le~&5n?X?gF$BIXoZsp-u_H#Cv=EX-2$wc`lJ{sQ%7yb*`d z-*2QMW>k7P!xe0ho#j*dB_h?(l8eu~C>S*#f~ROMBfl-Vbm3<&UyYt2#J$pmXI{SI z`DepR^$bQPd9350h~O@YW)R`>3(-LCkrp1|zP;n;$P`0L<`b`_pby;f`DY)gJKMjv zMy>+_8mpfIQ6=a%;BgBwHkrGf4VMV5BU}->uw=4n!jO*0!D=j@Ko8 z$CTDT1o^brd=wz(;0itUJFSf<%1t?{sm0M5zpO8v8<|ke(m(YQvaX8Av4u$#WZVpF z?2m|})^93-T-6NV5pn!<%7n9o=sQ!&9kfG?HTc*}r;O1_s%U1h8JCTK=FfGM%4Mos zBFD->&AwRmB9jr9H5n&eR;H3uUX5)a zH(g`;v(n*g^G{}yh3yWH4-5wSq(?o)g?BO>F#Fwic(RpPK30c3Jv}EKs!+}Db1++ SNakHP*sC>pPrmwl5Bm??H zl`7ZM8&En^+ocWKl_gwkbuUhqi&-iIZ7dL}ro6OgT~izI#6i>H;# zFsR$BGxAmx^BEHvj4P`DnDE`1m26d8*Oty_k2$TE_YChlmQF9zvtz^<@>DOUT^_r% z1rL*SCnxnNCvOXmXwjWoJ22(PT`~%7T9e_@ zd)CwANF@zvNMhG7sr1ax=nK{i5VqYv8w{s_gfHH znP=TgyM{NmQ!55_{ieYC`!%8x7cJ{p+#N|6)Ywr6d2UoKnNM^wO>i4zgzs;x3~sCr z0rj`I>@RBiX)srhHXS~^>}9}mQe#4kvD@ueZs!e`MV>d${AHE8C~a>?S`_9HXYaxw ziYL9($s?VC2zM&mgd0l#bBHTXj_;+tR ziHW?h$C*!0Z8q1ubuB-n``|z#cJ%f^=`fVJipno9FP%E`@l$;(4) z>4z0@igBkkb4+(mHpWGygp4KEzRcExMbB+ljQ7Xg-Hqi~{>a%aIkv`WZjjW>eL|w5 z>iY^jrrD*f^&$6G>xsIZbW>TVsd32DSIZgZqQ+q_w&Z5PfuWsmuBL{R{g1)*J$hnD zX(*sIO!iPVx=!Wu2$u!}Rg>d3Z5NIttK-&3yu3J6n|%S;&w3oZ+8HjbXZejQiFSFb zm$xlmRrqu;e!aP8;jIui(}EVb3yj(YL!pN!=R}IV-hI$>N?%c9x@K^Z`G`93xxG{? zDvxut`h}HaPO-{BES%AlWjB98s@ZsNQ*m}p6n=>@T+kNTgy;9H=G{Y@o%gtPJy-cP zS8~YAevEZPS`(T((zn4WQmbJ@@xBH#{z(5Lo2|lq%!G72dsPMBE=Y5cBgZ~;jpaKW zcHo9OMq+S(&zj?&dQ7FfeTLc%Ooa3xFS}~P%jy;N*Al`PO)p)mcO&nqi;IK4@g{vt zTzi@1Ou6E9jz^Kh-H9+yYEt(Qwm-l)S;`McW?HeKCM*_FjZJB?QEbI)8z!rtka*TA;Y+1!ci_E;+{HJk9!X98;i z)sZZ11%EZoC$0TUq;V%{(WVd0a*7w#$23x(0a=s@z)PD@b{e%y@al(aU^#<%ZFl=Mg%~D>x{+=>r zPF_0{AL|432RbB_M)T;q^GRIN`31I0?K(aRQz^36OBEZf_7ns@w#Nm}Ya1_|tJ*8| zS36N95SL}*1L;z74IW(a*0Q3Rb%%PgYN1--O=?#7p?JN>w`CZD`tbuJ2JIE)9lzB8 zMradzw&WkhHMSLE2=;+oH-+W+3ff*^PI1>}D@BR{e_+sA0T3RmDVg)=CVT#6A4Ob8 zOz7BAOd;&Y++@JgE=kE$R+ii*ZeNP27bFHdS?-Q{F6_~?WZm~SU_SUSMVupY#J%VE zYq!&=w{~Y4Y8J>8e>gqO)Ye6a>Xx9i+L@p|r>-W4pl!Dyj-ImzjPF#xTBev>klb3P zXs>&w)hoZ{WclL4yS?2-V0=&2px$b`7tLjJm0~56mG<*FvPZJ@8OjQ6)Qq{FDX*v* zO-T~_dFQt2hiAv90!^ndYDT#vFyvwH!QH9zu-EleuQZpb_;D28tlTyfK*UA9CSe{# zj#c5_XbE30`JkA1uI*)QO6G^>XD;qY>&B?2NqhUJZ^squxV!AvKpa|Md-wELT#V6c zYr|T{x*e%C|5(jlQQ}oMcD3e-+M#EA)0@>2<`C*dN&Kse&c3pUdmlS3dw(abEPBf8 zILW&sU%AzE?&uXQQGl}yD?3l9osNk4&&PrBiCa?Bo=@SU&!(PqJ|BDf(4GEzTp@F) zU#t|c4|Zl$1R zI@K7Y(oK8-)F={!As|hzu>hGP5W^87o@7YGgH-{RtCV3TgeW99L*zAxf&`*1hh;fj!%)>4fa3_w@c+Q|m^ E9V^gpWB>pF literal 0 HcmV?d00001 diff --git a/kite/doc/images/Track-5.png b/kite/doc/images/Track-5.png new file mode 100644 index 0000000000000000000000000000000000000000..d0a6dc12189b6db8aaf7ba8472cf490e5f86e047 GIT binary patch literal 4102 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 EADac8>;M1& literal 0 HcmV?d00001 diff --git a/kite/doc/images/TrackSegmentCost-1.png b/kite/doc/images/TrackSegmentCost-1.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7de99233b7dca6de7d66dd961f9e7aafbec2e4 GIT binary patch literal 3712 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 literal 0 HcmV?d00001 diff --git a/kite/doc/images/TrackSegmentCost-3.fig b/kite/doc/images/TrackSegmentCost-3.fig new file mode 100644 index 00000000..02549997 --- /dev/null +++ b/kite/doc/images/TrackSegmentCost-3.fig @@ -0,0 +1,105 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 3525 3225 3675 3225 3675 3375 3525 3375 3525 3225 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 5025 3225 5175 3225 5175 3375 5025 3375 5025 3225 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 9825 3225 9975 3225 9975 3375 9825 3375 9825 3225 +2 1 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 2 + 3600 3300 9900 3300 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 3600 3300 3600 600 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 5100 4500 5100 1500 +2 1 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 2 + 9900 5100 9900 3300 +2 2 0 4 0 7 50 -1 -1 10.000 0 0 -1 0 0 5 + 7125 3225 7275 3225 7275 3375 7125 3375 7125 3225 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 7050 3000 7350 3000 7350 3600 7050 3600 7050 3000 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 3525 525 3675 525 3675 675 3525 675 3525 525 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 5025 1425 5175 1425 5175 1575 5025 1575 5025 1425 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 5025 4425 5175 4425 5175 4575 5025 4575 5025 4425 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 3525 2025 3675 2025 3675 2175 3525 2175 3525 2025 +2 2 0 4 4 7 60 -1 -1 10.000 0 0 -1 0 0 5 + 9825 5025 9975 5025 9975 5175 9825 5175 9825 5025 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 3750 600 11700 600 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 5250 1500 11700 1500 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 10050 3300 11700 3300 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 10050 5100 11700 5100 +2 1 0 1 0 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 3600 3450 3600 6000 +2 1 0 1 0 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 5100 4650 5100 6000 +2 1 0 1 0 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 7200 3675 7200 6000 +2 1 0 1 0 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 9900 5250 9900 6000 +2 1 0 1 4 7 60 -1 -1 4.000 0 0 -1 0 0 2 + 5250 4500 11700 4500 +2 1 0 1 0 7 60 -1 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 120.00 240.00 + 2700 5700 10500 5700 +2 1 0 1 4 7 60 -1 -1 0.000 0 0 -1 1 0 2 + 1 0 1.00 120.00 240.00 + 3000 6000 3000 0 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 4500 3075 4500 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 5100 3075 5100 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 2100 3075 2100 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 3300 3075 3300 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 600 3075 600 +2 1 0 4 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 3600 5625 3600 5775 +2 1 0 4 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 5100 5625 5100 5775 +2 1 0 4 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 9900 5625 9900 5775 +2 1 0 4 0 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 7200 5625 7200 5775 +2 1 0 4 4 7 60 -1 -1 0.000 0 0 -1 0 0 2 + 2925 1500 3075 1500 +2 2 0 2 0 7 60 -1 -1 6.000 0 0 -1 0 0 5 + 2100 -600 12300 -600 12300 6600 2100 6600 2100 -600 +4 0 4 60 -1 18 14 0.0000 4 210 1260 10200 1425 right @7: 16\001 +4 0 4 60 -1 18 14 0.0000 4 210 1260 10200 525 right @2: 19\001 +4 0 4 60 -1 18 14 0.0000 4 210 1800 10200 3225 punctual @14: 10\001 +4 0 4 60 -1 18 14 0.0000 4 180 1080 10200 5025 left @23: 4\001 +4 0 4 60 -1 18 14 0.0000 4 180 960 10200 4425 left @7: 6\001 +4 1 4 60 -1 18 14 0.0000 4 165 150 3450 1725 A\001 +4 1 4 60 -1 18 14 0.0000 4 165 150 3750 2775 B\001 +4 1 4 60 -1 18 14 0.0000 4 165 165 5250 2475 C\001 +4 1 4 60 -1 18 14 0.0000 4 165 165 7500 3600 D\001 +4 1 4 60 -1 18 14 0.0000 4 165 135 9750 4200 E\001 +4 1 0 60 -1 18 14 0.0000 4 150 120 3600 6300 2\001 +4 1 0 60 -1 18 14 0.0000 4 150 120 5100 6300 7\001 +4 1 0 60 -1 18 14 0.0000 4 150 240 7200 6300 14\001 +4 1 0 60 -1 18 14 0.0000 4 150 240 9900 6300 23\001 +4 2 4 60 -1 18 14 0.0000 4 150 120 2850 5100 4\001 +4 2 4 60 -1 18 14 0.0000 4 150 120 2850 4500 6\001 +4 2 4 60 -1 18 14 0.0000 4 150 240 2850 3300 10\001 +4 2 4 60 -1 18 14 0.0000 4 150 240 2850 2100 14\001 +4 2 4 60 -1 18 14 0.0000 4 150 240 2850 600 19\001 +4 1 4 60 -1 14 14 0.0000 4 135 135 3000 -75 Y\001 +4 1 0 60 -1 14 14 0.0000 4 135 135 10650 5775 X\001 +4 2 4 60 -1 18 14 0.0000 4 150 240 2850 1500 16\001 diff --git a/kite/doc/images/TrackSegmentCost-3.pdf b/kite/doc/images/TrackSegmentCost-3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7467904e989cac2ef839b7a6ae7635158c7c3c6d GIT binary patch literal 3504 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 +#include + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Query.h" +#include "kite/RoutingPlane.h" +#include "kite/TrackBlockage.h" +#include "kite/Track.h" +#include "kite/KiteEngine.h" + + +namespace { + + using namespace std; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::DbU; + using Hurricane::Box; + using Hurricane::Interval; + using Hurricane::Query; + using Hurricane::Go; + using Hurricane::Rubber; + using Hurricane::Layer; + using Hurricane::BasicLayer; + using Hurricane::RegularLayer; + using Hurricane::Transformation; + using namespace Kite; + + +// ------------------------------------------------------------------- +// Class : "::BlockagesPlanes". + + + class BlockagesPlanes { + private: + class Track { + public: + Track ( Kite::Track* ); + void add ( Interval ); + inline DbU::Unit getAxis () const; + void dump ( DbU::Unit width ); + private: + Kite::Track* _ktrack; + list _blockages; + }; + private: + class Plane { + public: + Plane ( RoutingPlane* ); + ~Plane (); + void merge ( Box boundingBox ); + inline unsigned int getDirection () const; + inline const Layer* getLayer () const; + inline DbU::Unit getHalfWireWidth () const; + inline DbU::Unit getPitch () const; + void dump (); + private: + RoutingPlane* _routingPlane; + Interval _axisSpan; + vector _tracks; + }; + public: + static Track* createTrack ( Kite::Track* ); + public: + BlockagesPlanes ( KiteEngine* ); + ~BlockagesPlanes (); + bool hasPlane ( const BasicLayer* ); + bool setActivePlane ( const BasicLayer* ); + inline Plane* getActivePlane () const; + void add ( Box boundingBox ); + void dump (); + private: + KiteEngine* _kite; + map _planes; + Plane* _activePlane; + }; + + + BlockagesPlanes::Track::Track ( Kite::Track* ktrack ) + : _ktrack(ktrack) + , _blockages() + { } + + + inline DbU::Unit BlockagesPlanes::Track::getAxis () const { return _ktrack->getAxis(); } + + + void BlockagesPlanes::Track::add ( Interval obstacle ) + { + if ( (obstacle.getVMax() <= _ktrack->getMin()) + or (obstacle.getVMin() >= _ktrack->getMax()) ) return; + + list::iterator imerge = _blockages.end(); + list::iterator iblockage = _blockages.begin(); + + while ( iblockage != _blockages.end() ) { + if ( obstacle.getVMax() < (*iblockage).getVMin() ) break; + + if ( obstacle.intersect(*iblockage) ) { + if ( imerge == _blockages.end() ) { + imerge = iblockage; + (*imerge).merge ( obstacle ); + } else { + (*imerge).merge ( *iblockage ); + iblockage = _blockages.erase ( iblockage ); + continue; + } + } + iblockage++; + } + + if ( imerge == _blockages.end() ) { + _blockages.insert ( iblockage, obstacle ); + ltrace(190) << "| Add on " << DbU::getValueString(_ktrack->getAxis()) << " " << obstacle << endl; + } + } + + + void BlockagesPlanes::Track::dump ( DbU::Unit width ) + { + list::iterator iinterval = _blockages.begin(); + + if ( _ktrack->getDirection() == Constant::Horizontal ) { + DbU::Unit ymin = _ktrack->getAxis() - width/2; + DbU::Unit ymax = _ktrack->getAxis() + width/2; + + for ( ; iinterval != _blockages.end() ; iinterval++ ) { + Box bb ( (*iinterval).getVMin(), ymin, (*iinterval).getVMax(), ymax ); + TrackBlockage::create ( _ktrack, bb ); + } + } else { + DbU::Unit xmin = _ktrack->getAxis() - width/2; + DbU::Unit xmax = _ktrack->getAxis() + width/2; + + for ( ; iinterval != _blockages.end() ; iinterval++ ) { + Box bb ( xmin, (*iinterval).getVMin(), xmax, (*iinterval).getVMax() ); + TrackBlockage::create ( _ktrack, bb ); + } + } + } + + + BlockagesPlanes::Plane::Plane ( RoutingPlane* plane ) + : _routingPlane(plane) + , _axisSpan (plane->getAxisMin(),plane->getAxisMax()) + , _tracks () + { + Kite::Track* ktrack = plane->getTrackByIndex(0); + + for ( ; ktrack != NULL ; ktrack=ktrack->getNext() ) { + _tracks.push_back ( BlockagesPlanes::createTrack(ktrack) ); + } + } + + + BlockagesPlanes::Plane::~Plane () + { + for ( size_t i=0 ; i<_tracks.size() ; i++ ) delete _tracks[i]; + } + + + inline unsigned int BlockagesPlanes::Plane::getDirection () const { return _routingPlane->getDirection(); } + inline const Layer* BlockagesPlanes::Plane::getLayer () const { return _routingPlane->getLayer(); } + inline DbU::Unit BlockagesPlanes::Plane::getHalfWireWidth () const { return _routingPlane->getLayerGauge()->getHalfWireWidth(); } + inline DbU::Unit BlockagesPlanes::Plane::getPitch () const { return _routingPlane->getLayerGauge()->getPitch(); } + + + void BlockagesPlanes::Plane::merge ( Box boundingBox ) + { + ltrace(190) << "| Add on plane " << _routingPlane->getLayer() << " " << boundingBox << endl; + + DbU::Unit delta = getPitch() - getHalfWireWidth() - 1; + + if ( getDirection() == Constant::Horizontal ) { + boundingBox.inflate ( 0, delta, 0, delta ); + + ltrace(190) << "Track range: " << DbU::getValueString(boundingBox.getYMin()) + << ":" << DbU::getValueString(boundingBox.getYMax()) << endl; + for ( size_t i=0 ; (i<_tracks.size()) and (_tracks[i]->getAxis() < boundingBox.getYMax()) ; i++ ) { + if ( _tracks[i]->getAxis() < boundingBox.getYMin() ) continue; + + _tracks[i]->add ( Interval(boundingBox.getXMin(),boundingBox.getXMax()) ); + } + } else { + boundingBox.inflate ( delta, 0, delta, 0 ); + for ( size_t i=0 ; (i<_tracks.size()) and (_tracks[i]->getAxis() < boundingBox.getXMax()) ; i++ ) { + if ( _tracks[i]->getAxis() < boundingBox.getXMin() ) continue; + + _tracks[i]->add ( Interval(boundingBox.getYMin(),boundingBox.getYMax()) ); + } + } + } + + + void BlockagesPlanes::Plane::dump () + { + for ( size_t i=0 ; i<_tracks.size() ; i++ ) _tracks[i]->dump(DbU::lambda(2.0)); + } + + + BlockagesPlanes::Track* BlockagesPlanes::createTrack ( Kite::Track* ktrack ) + { return new Track ( ktrack ); } + + + BlockagesPlanes::BlockagesPlanes ( KiteEngine* kite ) + : _kite (kite) + , _planes () + , _activePlane(NULL) + { + RoutingGauge* rg = _kite->getConfiguration()->getRoutingGauge(); + size_t gaugeDepth = rg->getDepth (); + + for ( size_t depth=0 ; depth(rg->getRoutingLayer(depth)); + if ( not routingLayer ) continue; + + const BasicLayer* blockageLayer = routingLayer->getBasicLayer()->getBlockageLayer(); + if ( not blockageLayer ) continue; + + _planes.insert ( make_pair(blockageLayer,new Plane(_kite->getRoutingPlaneByIndex(depth))) ); + } + } + + + BlockagesPlanes::~BlockagesPlanes () + { + while ( not _planes.empty() ) { + delete _planes.begin()->second; + _planes.erase ( _planes.begin() ); + } + } + + + bool BlockagesPlanes::hasPlane ( const BasicLayer* basicLayer ) + { return (_planes.find(basicLayer) != _planes.end()); } + + + bool BlockagesPlanes::setActivePlane ( const BasicLayer* basicLayer ) + { + map::iterator iplane = _planes.find(basicLayer); + if ( iplane == _planes.end() ) return false; + + _activePlane = iplane->second; + return true; + } + + + inline BlockagesPlanes::Plane* BlockagesPlanes::getActivePlane () const + { return _activePlane; } + + + void BlockagesPlanes::add ( Box boundingBox ) + { + if ( not _activePlane ) return; + _activePlane->merge ( boundingBox ); + } + + + void BlockagesPlanes::dump () + { + map::iterator iplane = _planes.begin(); + for ( ; iplane != _planes.end() ; iplane++ ) { + iplane->second->dump(); + } + } + + + +// ------------------------------------------------------------------- +// Class : "::QueryBlockages". + + + class QueryBlockages : public Query { + public: + QueryBlockages ( KiteEngine* ); + virtual bool hasGoCallback () const; + virtual void setBasicLayer ( const BasicLayer* ); + virtual void goCallback ( Go* ); + virtual void rubberCallback ( Rubber* ); + virtual void extensionGoCallback ( Go* ); + virtual void masterCellCallback (); + void addBlockage ( const Go* go + , const BasicLayer* basicLayer + , const Box& area + , const Transformation& transformation + ); + virtual void doQuery (); + inline void dump (); + inline unsigned int getBlockagesCount () const; + private: + KiteEngine* _kite; + BlockagesPlanes _blockagesPlanes; + unsigned int _blockagesCount; + }; + + + QueryBlockages::QueryBlockages ( KiteEngine* kite ) + : Query () + , _kite (kite) + , _blockagesPlanes(kite) + , _blockagesCount (0) + { + setCell ( kite->getCell() ); + setArea ( kite->getCell()->getBoundingBox() ); + setBasicLayer ( NULL ); + setFilter ( Query::DoTerminalCells|Query::DoComponents ); + } + + + inline unsigned int QueryBlockages::getBlockagesCount () const + { return _blockagesCount; } + + + inline void QueryBlockages::dump () + { return _blockagesPlanes.dump(); } + + + void QueryBlockages::setBasicLayer ( const BasicLayer* basicLayer ) + { + _blockagesPlanes.setActivePlane ( basicLayer ); + Query::setBasicLayer ( basicLayer ); + } + + + void QueryBlockages::doQuery () + { + if ( not _blockagesPlanes.getActivePlane() ) return; + Query::doQuery (); + } + + + void QueryBlockages::masterCellCallback () + { } + + + bool QueryBlockages::hasGoCallback () const + { return true; } + + + void QueryBlockages::goCallback ( Go* go ) + { + addBlockage ( go, getBasicLayer(), getArea(), getTransformation() ); + } + + + void QueryBlockages::addBlockage ( const Go* go + , const BasicLayer* basicLayer + , const Box& area + , const Transformation& transformation + ) + { + const Component* component = dynamic_cast(go); + if ( component ) { + _blockagesCount++; + Box bb ( transformation.getBox(component->getBoundingBox(basicLayer)) ); + ltrace(190) << "Blockage: " << bb << " in " << basicLayer->getName() << endl; + + _blockagesPlanes.add ( bb ); + } + } + + + void QueryBlockages::rubberCallback ( Rubber* ) + { } + + + void QueryBlockages::extensionGoCallback ( Go* ) + { } + + +} // End of anonymous namespace. + + +namespace Kite { + + + using Hurricane::DataBase; + using Hurricane::Technology; + using Hurricane::BasicLayer; + using Hurricane::ForEachIterator; + + + void KiteEngine::buildBlockages () + { + cmess1 << " o Building blockages." << endl; + + if ( not _obstacleNet ) { + _obstacleNet = getCell()->getNet("obstaclenet"); + if ( not _obstacleNet ) + _obstacleNet = Net::create ( getCell(), "obstaclenet" ); + } + + QueryBlockages query ( this ); + Technology* technology = DataBase::getDB()->getTechnology(); + + forEach ( BasicLayer*, iLayer, technology->getBasicLayers() ) { + if ( iLayer->getMaterial() != BasicLayer::Material::blockage ) continue; + + cmess1 << " - Blockages in " << iLayer->getName() << " ..." << endl; + + query.setBasicLayer ( *iLayer ); + query.doQuery (); + } + query.dump (); + cmess1 << " - " << query.getBlockagesCount() << " blockages found." << endl; + + Session::revalidate (); + } + + +} // End of Kite namespace. diff --git a/kite/src/BuildPowerRails.cpp b/kite/src/BuildPowerRails.cpp new file mode 100644 index 00000000..0ce37594 --- /dev/null +++ b/kite/src/BuildPowerRails.cpp @@ -0,0 +1,595 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./BuildPowerRails.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include + +#include "hurricane/DataBase.h" +#include "hurricane/Technology.h" +#include "hurricane/BasicLayer.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "hurricane/NetExternalComponents.h" +#include "hurricane/Query.h" +#include "kite/RoutingPlane.h" +#include "kite/TrackFixedSegment.h" +#include "kite/Track.h" +#include "kite/KiteEngine.h" + + +namespace { + + using namespace std; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ForEachIterator; + using Hurricane::DbU; + using Hurricane::Box; + using Hurricane::Interval; + using Hurricane::Horizontal; + using Hurricane::Vertical; + using Hurricane::NetExternalComponents; + using Hurricane::Query; + using Hurricane::Go; + using Hurricane::Rubber; + using Hurricane::Layer; + using Hurricane::BasicLayer; + using Hurricane::RegularLayer; + using Hurricane::Transformation; + using Hurricane::Technology; + using Hurricane::DataBase; + using namespace Kite; + + +// ------------------------------------------------------------------- +// Class : "::PowerRailsPlanes". + + + class PowerRailsPlanes { + private: + class Rails; + class Plane; + class Rail { + public: + Rail ( Rails*, DbU::Unit axis, DbU::Unit width ); + inline DbU::Unit getAxis () const; + inline DbU::Unit getWidth () const; + inline Rails* getRails () const; + inline RoutingPlane* getRoutingPlane () const; + inline Constant::Direction getDirection () const; + inline Net::Type getType () const; + void merge ( DbU::Unit source, DbU::Unit target ); + void doLayout ( const Layer*, Net* ); + private: + Rails* _rails; + DbU::Unit _axis; + DbU::Unit _width; + list _chunks; + }; + private: + class RailCompare { + public: + bool operator() ( const Rail* lhs, const Rail* rhs ); + }; + class RailMatch : public unary_function { + public: + inline RailMatch ( DbU::Unit axis, DbU::Unit width ); + inline bool operator() ( const Rail* ); + private: + DbU::Unit _axis; + DbU::Unit _width; + }; + private: + class Rails { + public: + Rails ( Plane*, Constant::Direction, Net::Type ); + ~Rails (); + inline Plane* getPlane (); + inline RoutingPlane* getRoutingPlane (); + inline Constant::Direction getDirection () const; + inline Net::Type getType () const; + void merge ( Point& source, Point& target, DbU::Unit width ); + void doLayout ( const Layer*, Net* ); + private: + Plane* _plane; + Constant::Direction _direction; + Net::Type _type; + vector _rails; + }; + private: + class Plane { + public: + Plane ( const RegularLayer*, RoutingPlane* ); + ~Plane (); + inline RoutingPlane* getRoutingPlane (); + void merge ( Point& source, Point& target, DbU::Unit width, Net::Type ); + void doLayout ( Net* powerNet, Net* groundNet ); + private: + const RegularLayer* _layer; + RoutingPlane* _routingPlane; + Rails _railsPowerHorizontal; + Rails _railsPowerVertical; + Rails _railsGroundHorizontal; + Rails _railsGroundVertical; + }; + public: + PowerRailsPlanes ( KiteEngine* ); + ~PowerRailsPlanes (); + bool hasPlane ( const BasicLayer* ); + bool setActivePlane ( const BasicLayer* ); + inline Plane* getActivePlane () const; + void merge ( Point& source, Point& target, DbU::Unit width, Net::Type ); + void doLayout (); + private: + KiteEngine* _kite; + map _planes; + Plane* _activePlane; + }; + + + PowerRailsPlanes::Rail::Rail ( Rails* rails, DbU::Unit axis, DbU::Unit width ) + : _rails (rails) + , _axis (axis) + , _width (width) + , _chunks() + { + cinfo << " New rail @" << DbU::getValueString(axis) + << " " << getRoutingPlane()->getLayer()->getName() + << " " << getRails()->getType() << endl; + } + + inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; } + inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; } + inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; } + inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); } + inline Constant::Direction PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); } + inline Net::Type PowerRailsPlanes::Rail::getType () const { return _rails->getType(); } + + + void PowerRailsPlanes::Rail::merge ( DbU::Unit source, DbU::Unit target ) + { + Interval chunkMerge ( source, target ); + + list::iterator imerge = _chunks.end(); + list::iterator ichunk = _chunks.begin(); + + while ( ichunk != _chunks.end() ) { + if ( chunkMerge.getVMax() < (*ichunk).getVMin() ) break; + + if ( chunkMerge.intersect(*ichunk) ) { + if ( imerge == _chunks.end() ) { + imerge = ichunk; + (*imerge).merge ( chunkMerge ); + } else { + (*imerge).merge ( *ichunk ); + ichunk = _chunks.erase ( ichunk ); + continue; + } + } + ichunk++; + } + + if ( imerge == _chunks.end() ) { + _chunks.insert ( ichunk, chunkMerge ); + ltrace(190) << "| Add on " << DbU::getValueString(_axis) << " " << chunkMerge << endl; + } + } + + + void PowerRailsPlanes::Rail::doLayout ( const Layer* layer, Net* net ) + { + cinfo << "Doing layout of rail: " << layer->getName() << " @" << DbU::getValueString(_axis) << endl; + + RoutingPlane* plane = getRoutingPlane(); + Segment* segment = NULL; + DbU::Unit delta = plane->getLayerGauge()->getPitch() - plane->getLayerGauge()->getHalfWireWidth() - 1; + unsigned int type = plane->getLayerGauge()->getType(); + + if ( getDirection() == Constant::Horizontal ) { + list::iterator ichunk = _chunks.begin(); + for ( ; ichunk != _chunks.end() ; ichunk++ ) { + segment = Horizontal::create ( net, layer, _axis, _width, (*ichunk).getVMin(), (*ichunk).getVMax() ); + if ( segment ) + NetExternalComponents::setExternal ( segment ); + + if ( type == Constant::PinOnly ) continue; + + DbU::Unit axisMin = _axis - _width/2 - delta; + DbU::Unit axisMax = _axis + _width/2 + delta; + + Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); + for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) { + TrackFixedSegment::create ( track, segment ); + } + } + } else { + list::iterator ichunk = _chunks.begin(); + for ( ; ichunk != _chunks.end() ; ichunk++ ) { + segment = Vertical::create ( net, layer, _axis, _width, (*ichunk).getVMin(), (*ichunk).getVMax() ); + if ( segment ) + NetExternalComponents::setExternal ( segment ); + + if ( type == Constant::PinOnly ) continue; + + DbU::Unit axisMin = _axis - _width/2 - delta; + DbU::Unit axisMax = _axis + _width/2 + delta; + + Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior ); + for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) { + TrackFixedSegment::create ( track, segment ); + } + } + } + } + + + inline bool PowerRailsPlanes::RailCompare::operator() ( const Rail* lhs, const Rail* rhs ) + { + if ( lhs->getAxis () < rhs->getAxis () ) return true; + if ( lhs->getWidth() < rhs->getWidth() ) return true; + return false; + } + + + inline PowerRailsPlanes::RailMatch::RailMatch ( DbU::Unit axis, DbU::Unit width ) + : _axis(axis) + , _width(width) + { } + + + inline bool PowerRailsPlanes::RailMatch::operator() ( const Rail* rail ) + { return (rail->getAxis() == _axis) and (rail->getWidth() == _width); } + + + PowerRailsPlanes::Rails::Rails ( PowerRailsPlanes::Plane* plane, Constant::Direction direction, Net::Type type ) + : _plane (plane) + , _direction(direction) + , _type (type) + { + } + + + PowerRailsPlanes::Rails::~Rails () + { + while ( not _rails.empty() ) { + delete (*_rails.begin()); + _rails.erase ( _rails.begin() ); + } + } + + + inline PowerRailsPlanes::Plane* PowerRailsPlanes::Rails::getPlane () { return _plane; } + inline RoutingPlane* PowerRailsPlanes::Rails::getRoutingPlane () { return getPlane()->getRoutingPlane(); } + inline Constant::Direction PowerRailsPlanes::Rails::getDirection () const { return _direction; } + inline Net::Type PowerRailsPlanes::Rails::getType () const { return _type; } + + + void PowerRailsPlanes::Rails::merge ( Point& source, Point& target, DbU::Unit width ) + { + DbU::Unit axis = (_direction == Constant::Horizontal) ? source.getY() : source.getX(); + vector::iterator irail = find_if ( _rails.begin(), _rails.end(), RailMatch(axis,width) ); + + Rail* rail = NULL; + if ( irail == _rails.end() ) { + rail = new Rail(this,axis,width); + _rails.push_back ( rail ); + sort ( _rails.begin(), _rails.end(), RailCompare() ); + } else { + rail = *irail; + } + + if ( _direction == Constant::Horizontal ) + rail->merge ( source.getX(), target.getX() ); + else + rail->merge ( source.getY(), target.getY() ); + } + + + void PowerRailsPlanes::Rails::doLayout ( const Layer* layer, Net* net ) + { + cinfo << "Doing layout of plane: " << layer->getName() << " " << net->getName() << endl; + + for ( size_t irail=0 ; irail<_rails.size() ; irail++ ) + _rails[irail]->doLayout ( layer, net ); + } + + + PowerRailsPlanes::Plane::Plane ( const RegularLayer* layer, RoutingPlane* routingPlane ) + : _layer (layer) + , _routingPlane (routingPlane) + , _railsPowerHorizontal (this,Constant::Horizontal,Net::Type::POWER) + , _railsPowerVertical (this,Constant::Vertical ,Net::Type::POWER) + , _railsGroundHorizontal(this,Constant::Horizontal,Net::Type::GROUND) + , _railsGroundVertical (this,Constant::Vertical ,Net::Type::GROUND) + { + cinfo << "New Plane " << _layer->getName() << " " << _routingPlane << endl; + } + + + PowerRailsPlanes::Plane::~Plane () + { + } + + + inline RoutingPlane* PowerRailsPlanes::Plane::getRoutingPlane () { return _routingPlane; } + + + void PowerRailsPlanes::Plane::merge ( Point& source, Point& target, DbU::Unit width, Net::Type type ) + { + if ( source.getY() == target.getY() ) { + switch ( type ) { + case Net::Type::POWER: _railsPowerHorizontal .merge(source,target,width); break; + case Net::Type::GROUND: _railsGroundHorizontal.merge(source,target,width); break; + default: break; + } + } else { + switch ( type ) { + case Net::Type::POWER: _railsPowerVertical .merge(source,target,width); break; + case Net::Type::GROUND: _railsGroundVertical.merge(source,target,width); break; + default: break; + } + } + } + + + void PowerRailsPlanes::Plane::doLayout ( Net* powerNet, Net* groundNet ) + { + _railsPowerHorizontal .doLayout ( _layer, powerNet ); + _railsPowerVertical .doLayout ( _layer, powerNet ); + _railsGroundHorizontal.doLayout ( _layer, groundNet ); + _railsGroundVertical .doLayout ( _layer, groundNet ); + } + + + PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite ) + : _kite (kite) + , _planes () + , _activePlane(NULL) + { + Technology* technology = DataBase::getDB()->getTechnology(); + RoutingGauge* rg = _kite->getConfiguration()->getRoutingGauge(); + + forEach ( Layer*, iLayer, technology->getLayers() ) { + RegularLayer* regular = dynamic_cast(*iLayer); + if ( not regular + or (regular->getBasicLayer()->getMaterial() != BasicLayer::Material::metal) ) continue; + + RoutingLayerGauge* lg = rg->getLayerGauge(regular); + if ( not lg ) continue; + + cinfo << "Gauge: [" << lg->getDepth() << "] " << lg << endl; + + RoutingPlane* rp = _kite->getRoutingPlaneByIndex(lg->getDepth()); + cinfo << "Plane:" << rp << endl; + + _planes.insert ( make_pair(regular->getBasicLayer(),new Plane(regular,rp)) ); + } + } + + + PowerRailsPlanes::~PowerRailsPlanes () + { + while ( not _planes.empty() ) { + delete _planes.begin()->second; + _planes.erase ( _planes.begin() ); + } + } + + + bool PowerRailsPlanes::hasPlane ( const BasicLayer* layer ) + { return (_planes.find(layer) != _planes.end()); } + + + bool PowerRailsPlanes::setActivePlane ( const BasicLayer* layer ) + { + map::iterator iplane = _planes.find(layer); + if ( iplane == _planes.end() ) return false; + + _activePlane = iplane->second; + return true; + } + + + inline PowerRailsPlanes::Plane* PowerRailsPlanes::getActivePlane () const + { return _activePlane; } + + + void PowerRailsPlanes::merge ( Point& source, Point& target, DbU::Unit width, Net::Type type ) + { + if ( not _activePlane ) return; + _activePlane->merge ( source, target, width, type ); + } + + + void PowerRailsPlanes::doLayout () + { + Net* powerNet = NULL; + Net* groundNet = NULL; + + forEach ( Net*, inet, _kite->getCell()->getNets() ) { + if ( not powerNet and (inet->getType() == Net::Type::POWER)) powerNet = *inet; + if ( not groundNet and (inet->getType() == Net::Type::GROUND)) groundNet = *inet; + if ( powerNet and groundNet ) break; + } + + cinfo << "Doing power/ground layout " << powerNet->getName() + << "/" << groundNet->getName() << endl; + + map::iterator iplane = _planes.begin(); + for ( ; iplane != _planes.end() ; iplane++ ) + iplane->second->doLayout ( powerNet, groundNet ); + } + + + +// ------------------------------------------------------------------- +// Class : "::QueryPowerRails". + + + class QueryPowerRails : public Query { + public: + QueryPowerRails ( KiteEngine* ); + virtual bool hasGoCallback () const; + virtual void setBasicLayer ( const BasicLayer* ); + virtual void goCallback ( Go* ); + virtual void rubberCallback ( Rubber* ); + virtual void extensionGoCallback ( Go* ); + virtual void masterCellCallback (); + void addToPowerRail ( const Go* go + , const BasicLayer* basicLayer + , const Box& area + , const Transformation& transformation + ); + virtual void doQuery (); + inline void doLayout (); + inline unsigned int getGoMatchCount () const; + private: + KiteEngine* _kite; + PowerRailsPlanes _powerRailsPlanes; + unsigned int _goMatchCount; + }; + + + QueryPowerRails::QueryPowerRails ( KiteEngine* kite ) + : Query () + , _kite (kite) + , _powerRailsPlanes(kite) + , _goMatchCount (0) + { + setCell ( kite->getCell() ); + setArea ( kite->getCell()->getBoundingBox() ); + setBasicLayer ( NULL ); + setFilter ( Query::DoTerminalCells|Query::DoComponents ); + } + + + inline unsigned int QueryPowerRails::getGoMatchCount () const + { return _goMatchCount; } + + + inline void QueryPowerRails::doLayout () + { return _powerRailsPlanes.doLayout(); } + + + void QueryPowerRails::setBasicLayer ( const BasicLayer* basicLayer ) + { + _powerRailsPlanes.setActivePlane ( basicLayer ); + Query::setBasicLayer ( basicLayer ); + } + + + void QueryPowerRails::doQuery () + { + if ( not _powerRailsPlanes.getActivePlane() ) return; + Query::doQuery (); + } + + + void QueryPowerRails::masterCellCallback () + { } + + + bool QueryPowerRails::hasGoCallback () const + { return true; } + + + void QueryPowerRails::goCallback ( Go* go ) + { + addToPowerRail ( go, getBasicLayer(), getArea(), getTransformation() ); + } + + + void QueryPowerRails::addToPowerRail ( const Go* go + , const BasicLayer* basicLayer + , const Box& area + , const Transformation& transformation + ) + { + const Component* component = dynamic_cast(go); + if ( component ) { + Net::Type netType = component->getNet()->getType(); + if ( (netType != Net::Type::POWER) and (netType != Net::Type::GROUND) ) return; + + const Segment* segment = dynamic_cast(component); + if ( not segment ) return; + + _goMatchCount++; + cinfo << " Merging PowerRail element: " << segment << endl; + + Point source = segment->getSourcePosition(); + Point target = segment->getTargetPosition(); + + transformation.applyOn ( source ); + transformation.applyOn ( target ); + + _powerRailsPlanes.merge ( source, target, segment->getWidth(), netType ); + } + } + + + void QueryPowerRails::rubberCallback ( Rubber* ) + { } + + + void QueryPowerRails::extensionGoCallback ( Go* ) + { } + + +} // End of anonymous namespace. + + +namespace Kite { + + + using Hurricane::DataBase; + using Hurricane::Technology; + using Hurricane::BasicLayer; + using Hurricane::ForEachIterator; + + + void KiteEngine::buildPowerRails () + { + cmess1 << " o Building power rails." << endl; + + QueryPowerRails query ( this ); + Technology* technology = DataBase::getDB()->getTechnology(); + + forEach ( BasicLayer*, iLayer, technology->getBasicLayers() ) { + if ( iLayer->getMaterial() != BasicLayer::Material::metal ) continue; + + cmess1 << " - PowerRails in " << iLayer->getName() << " ..." << endl; + + query.setBasicLayer ( *iLayer ); + query.doQuery (); + } + query.doLayout (); + cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl; + + Session::revalidate (); + } + + +} // End of Kite namespace. diff --git a/kite/src/CMakeLists.txt b/kite/src/CMakeLists.txt new file mode 100644 index 00000000..286c4331 --- /dev/null +++ b/kite/src/CMakeLists.txt @@ -0,0 +1,95 @@ + + include ( ${QT_USE_FILE} ) + + include_directories ( ${Boost_INCLUDE_DIRS} + ${KITE_SOURCE_DIR}/src + ${HURRICANE_INCLUDE_DIR} + ${CORIOLIS_INCLUDE_DIR} + ) + set ( includes kite/TrackSegmentCost.h + kite/TrackCost.h + kite/DataNegociate.h + kite/TrackElement.h kite/TrackElements.h + kite/TrackSegment.h + kite/TrackBlockage.h + kite/TrackFixedSegment.h + kite/TrackMarker.h + kite/Track.h + kite/Tracks.h + kite/HorizontalTrack.h + kite/VerticalTrack.h + kite/Session.h + kite/RoutingEvent.h + kite/RoutingEventQueue.h + kite/RoutingEventHistory.h + kite/GCell.h + kite/GCellGrid.h + kite/GCellRoutingSet.h + kite/RoutingPlane.h + kite/NegociateWindow.h + kite/Configuration.h + kite/KiteEngine.h + kite/GraphicKiteEngine.h + ) + set ( mocIncludes kite/GraphicKiteEngine.h ) + set ( cpps TrackSegmentCost.cpp + TrackCost.cpp + DataNegociate.cpp + TrackElement.cpp + TrackElements.cpp + TrackSegment.cpp + TrackBlockage.cpp + TrackFixedSegment.cpp + TrackMarker.cpp + Track.cpp + Tracks.cpp + HorizontalTrack.cpp + VerticalTrack.cpp + Session.cpp + RoutingEvent.cpp + RoutingEventQueue.cpp + RoutingEventHistory.cpp + GCell.cpp + GCellGrid.cpp + GCellRoutingSet.cpp + RoutingPlane.cpp + BuildBlockages.cpp + BuildPowerRails.cpp + PreProcess.cpp + NegociateWindow.cpp + Configuration.cpp + KiteEngine.cpp + GraphicKiteEngine.cpp + ) + set ( kitecpps KiteMain.cpp ) + qt4_wrap_cpp ( mocCpps ${mocIncludes} ) + + + add_library ( kite ${cpps} ${mocCpps} ) + target_link_libraries ( kite ${KATABATIC_LIBRARIES} + ${KNIK_LIBRARIES} + ${CORIOLIS_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${QT_LIBRARIES} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ) + add_executable ( kite-text ${kitecpps} ) + target_link_libraries ( kite-text kite + ${KATABATIC_LIBRARIES} + ${KNIK_LIBRARIES} + ${CORIOLIS_LIBRARIES} + ${HURRICANE_LIBRARIES} + ${HURRICANE_GRAPHICAL_LIBRARIES} + ${QT_LIBRARIES} + ${LEFDEF_LIBRARIES} + ${OA_LIBRARIES} + ${Boost_LIBRARIES} + ) + install ( TARGETS kite DESTINATION /lib ) + install ( TARGETS kite-text DESTINATION /bin ) + + install ( FILES ${includes} + ${mocIncludes} DESTINATION /include/coriolis/kite ) + diff --git a/kite/src/Configuration.cpp b/kite/src/Configuration.cpp new file mode 100644 index 00000000..fdaef9cf --- /dev/null +++ b/kite/src/Configuration.cpp @@ -0,0 +1,178 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Configuartion.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "kite/Configuration.h" +#include "kite/KiteEngine.h" + + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::ostringstream; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::Error; + using Hurricane::Technology; + + +// ------------------------------------------------------------------- +// Class : "Kite::Configuration". + + + float Configuration::_defaultEdgeCapacity = 0.80; + + + void Configuration::setDefaultEdgeCapacity ( float percent ) + { + if ( percent > 1.0 ) + throw Error("Configuration::setDefaultEdgeCapacity(): edge capacity ratio greater than 1.0 (%.1f)." + ,percent); + + _defaultEdgeCapacity = percent; + } + + + Configuration::Configuration ( Katabatic::Configuration* base ) + : Katabatic::Configuration() + , _base (base) + , _postEventCb () + , _edgeCapacityPercent(_defaultEdgeCapacity) + , _expandStep (0.30) + , _ripupLimits () + , _ripupCost (3) + { + _ripupLimits[BorderRipupLimit] = 26; + _ripupLimits[StrapRipupLimit] = 16; + _ripupLimits[LocalRipupLimit] = 7; + _ripupLimits[GlobalRipupLimit] = 7; + _ripupLimits[LongGlobalRipupLimit] = 7; + } + + + Configuration::~Configuration () + { } + + + bool Configuration::isGMetal ( const Layer* layer ) const + { return _base->isGMetal(layer); } + + + size_t Configuration::getDepth () const + { return _base->getDepth(); } + + + size_t Configuration::getLayerDepth ( const Layer* layer ) const + { return _base->getLayerDepth(layer); } + + + RoutingGauge* Configuration::getRoutingGauge () const + { return _base->getRoutingGauge(); } + + + RoutingLayerGauge* Configuration::getLayerGauge ( size_t depth ) const + { return _base->getLayerGauge(depth); } + + + const Layer* Configuration::getRoutingLayer ( size_t depth ) const + { return _base->getRoutingLayer(depth); } + + + Layer* Configuration::getContactLayer ( size_t depth ) const + { return _base->getContactLayer(depth); } + + + DbU::Unit Configuration::getExtensionCap () const + { return _base->getExtensionCap(); } + + + float Configuration::getSaturateRatio () const + { return _base->getSaturateRatio(); } + + + DbU::Unit Configuration::getGlobalThreshold () const + { return _base->getGlobalThreshold(); } + + + void Configuration::setSaturateRatio ( float ratio ) + { _base->setSaturateRatio(ratio); } + + + void Configuration::setGlobalThreshold ( DbU::Unit threshold ) + { _base->setGlobalThreshold(threshold); } + + + void Configuration::setRipupLimit ( unsigned int limit, unsigned int type ) + { + if ( type >= RipupLimitsTableSize ) { + cerr << Error("setRipupLimit(): Bad ripup limit index: %ud (> %ud)." + ,type,RipupLimitsTableSize) << endl; + return; + } + + _ripupLimits [ type ] = limit; + } + + + unsigned int Configuration::getRipupLimit ( unsigned int type ) const + { + if ( type >= RipupLimitsTableSize ) { + cerr << Error("getRipupLimit(): Bad ripup limit index: %ud (> %ud)." + ,type,RipupLimitsTableSize) << endl; + return 0; + } + return _ripupLimits[type]; + } + + + string Configuration::_getTypeName () const + { + return "Configuration"; + } + + + string Configuration::_getString () const + { + ostringstream os; + + os << "<" << _getTypeName() << " " << getRoutingGauge()->getName() << ">"; + + return os.str(); + } + + + Record* Configuration::_getRecord () const + { + Record* record = _base->_getRecord(); + //record->add ( getSlot ( "_rg" , _rg ) ); + + return record; + } + + + +} // End of Kite namespace. diff --git a/kite/src/DataNegociate.cpp b/kite/src/DataNegociate.cpp new file mode 100644 index 00000000..2e499561 --- /dev/null +++ b/kite/src/DataNegociate.cpp @@ -0,0 +1,111 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./DataNegociate.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include + +#include "kite/DataNegociate.h" + + +namespace Kite { + + using std::ostringstream; + + +// ------------------------------------------------------------------- +// Class : "DataNegociate". + + + DataNegociate::DataNegociate ( TrackElement* trackSegment ) + : _routingEvent(NULL) + , _trackSegment(trackSegment) + , _cost (trackSegment) + , _gcellOrder ((unsigned int)-1) + , _state (RipupPerpandiculars) + , _stateCount (1) + , _leftBorder (false) + , _rightBorder (false) + , _ring (false) + //, _z (RoutingGauge::getLayerDepth(trackSegment->getLayer())) + { } + + + DataNegociate::~DataNegociate () + { } + + + void DataNegociate::update () + { + _cost.update ( _trackSegment ); + } + + + string DataNegociate::_getString () const + { + return "<" + _getTypeName() + " " + + getString(_trackSegment) + + ">"; + } + + + Record* DataNegociate::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_routingEvent", _routingEvent ) ); + record->add ( getSlot ( "_trackSegment", _trackSegment ) ); + record->add ( getSlot ( "_cost" , &_cost ) ); + record->add ( getSlot ( "_gcellOrder" , _gcellOrder ) ); + //record->add ( getSlot ( "_z" , _z ) ); + + return record; + } + + + string DataNegociate::getStateString ( DataNegociate* data ) + { + ostringstream s; + switch ( data->_state ) { + case RipupPerpandiculars: s << "RipupPerpandiculars"; break; + case Minimize: s << "Minimize"; break; + case DogLeg: s << "DogLeg"; break; + case Desalignate: s << "Desalignate"; break; + case Slacken: s << "Slacken"; break; + case ConflictSolve1: s << "ConflictSolve1"; break; + case ConflictSolve2: s << "ConflictSolve2"; break; + case LocalVsGlobal: s << "LocalVsGlobal"; break; + case MoveUp: s << "MoveUp"; break; + case MaximumSlack: s << "MaximumSlack"; break; + case Unimplemented: s << "Unimplemented"; break; + default: + s << "Unknown(" << data->_state << ")"; break; + } + s << ":" << data->_stateCount; + return s.str(); + } + + +} // End of Kite namespace. diff --git a/kite/src/GCell.cpp b/kite/src/GCell.cpp new file mode 100644 index 00000000..8df83b5d --- /dev/null +++ b/kite/src/GCell.cpp @@ -0,0 +1,569 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./GCell.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include + +#include "hurricane/DebugSession.h" +#include "hurricane/Bug.h" +#include "hurricane/Error.h" +#include "hurricane/Component.h" +#include "hurricane/RoutingPad.h" +#include "katabatic/AutoSegment.h" +#include "katabatic/AutoContact.h" +#include "kite/DataNegociate.h" +#include "kite/TrackSegment.h" +#include "kite/RoutingPlane.h" +#include "kite/GCell.h" +#include "kite/GCellGrid.h" +#include "kite/NegociateWindow.h" + + +namespace { + + using namespace Hurricane; + using namespace Kite; + + + TrackElement* getCandidate ( RoutingPad* rp, Box bb ) + { + size_t depth = Session::getConfiguration()->getLayerDepth ( rp->getLayer() ); + if ( depth > 2 ) return NULL; + + DebugSession::open ( rp->getNet() ); + + //if ( (depth != 0) and (depth != 2) ) return NULL; + + ltrace(200) << "depth: " << depth << " " << rp->getSourcePosition() << " " << rp << endl; + + if ( depth%2 == 0 ) { + // Propagate from vertical Terminals. + forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet() ) { + if ( not bb.contains(icontact->getCenter()) ) continue; + + forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet() ) { + TrackElement* autoSegment = Session::lookup(*isegment); + if ( not autoSegment or autoSegment->isFixed() ) continue; + + DebugSession::close (); + return autoSegment; + } + } + } else { +#if DISABLED + // Propage from Horizontal Terminals. + bool hasM3protect = false; + AutoContact* toContact = NULL; + + forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet() ) { + if ( not bb.contains(icontact->getCenter()) ) continue; + + forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet() ) { + TrackElement* autoSegment = Session::lookup(*isegment); + if ( not autoSegment ) continue; + if ( autoSegment->isFixed() ) { + if ( Session::getConfiguration()->getLayerDepth(autoSegment->getLayer()) == 2 ) { + ltrace(200) << "M3 protection found for " << rp << endl; + hasM3protect = true; + } + continue; + } + toContact = autoSegment->base()->getAutoSource(); + if ( toContact->base() == *icontact ) + toContact = autoSegment->base()->getAutoTarget(); + } + } + + // Find M3 associated to this terminal. + if ( hasM3protect ) { + if ( toContact ) { + ltrace(200) << "toContact: " << toContact << endl; + forEach ( Segment*, isegment, toContact->base()->getSlaveComponents().getSubSet() ) { + ltrace(200) << "| slave: " << *isegment << endl; + if ( Session::getConfiguration()->getLayerDepth(isegment->getLayer()) == 2 ) { + TrackElement* autoSegment = Session::lookup(*isegment); + ltrace(200) << "M3 candidate: " << autoSegment << endl; + DebugSession::close (); + return autoSegment; + } + } + } + } +#endif + } + + DebugSession::close (); + return NULL; + } + + +} + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::swap; + using std::numeric_limits; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::roundfp; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::ForEachIterator; + using Hurricane::Component; + using Hurricane::RoutingPad; + + using Katabatic::AutoContact; + + +// ------------------------------------------------------------------- +// Class : "Kite::GCell::CompareByDensity". +// +// lhs < rhs --> true + + + bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs ) + { + //int difference = floatCompare ( lhs->base()->getDensity(), rhs->base()->getDensity() ); + //if ( abs(difference) > 1000 ) return difference > 0; + + float difference = roundfp ( lhs->base()->getDensity() - rhs->base()->getDensity() ); + if ( difference != 0.0 ) return (difference > 0.0); + + if ( lhs->getIndex() < rhs->getIndex() ) return true; + return false; + } + + +// ------------------------------------------------------------------- +// Class : "Kite::GCell::CompareByStiffness". +// +// lhs < rhs --> true + + + bool GCell::CompareByStiffness::operator() ( GCell* lhs, GCell* rhs ) + { + if ( lhs->isRouted() xor rhs->isRouted() ) return rhs->isRouted(); + + float difference = roundfp ( lhs->getStiffness() - rhs->getStiffness() ); + if ( difference != 0.0 ) return (difference > 0.0); + + return lhs->getIndex() < rhs->getIndex(); + } + + +// ------------------------------------------------------------------- +// Class : "Kite::GCell". + + + GCell::GCell ( GCellGrid* grid, Katabatic::GCell* gcell ) + : _gcellGrid (grid) + , _base (gcell) + , _segments () + , _order (numeric_limits::max()) + , _isInRoutingSet (false) + , _isRouted (false) + { + if ( !gcell ) + cerr << Bug("GCell:GCell() - NULL base.") << endl; + + _leftSegments [0] = NULL; + _leftSegments [1] = NULL; + _rightSegments[0] = NULL; + _rightSegments[1] = NULL; + } + + + GCell* GCell::create ( GCellGrid* grid, Katabatic::GCell* gcell ) + { + GCell* kiteGCell = new GCell ( grid, gcell ); + + ltrace(90) << "Kite::GCell::create() - " << (void*)kiteGCell << " " << kiteGCell << endl; + + return kiteGCell; + } + + + GCell::~GCell () + { } + + + void GCell::destroy () + { + ltrace(90) << "Kite::GCell::destroy() - " << (void*)this << " " << this << endl; + ltracein(90); + + for ( size_t i=0 ; i < _segments.size() ; i++ ) { + if ( !_segments[i]->getTrack() ) + _segments[i]->destroy (); + else { + cerr << Error("%s still bound to a track!\n" + " (not deleted: let's get the memory leak)" + ,getString(_segments[i]).c_str() + ) << endl; + } + } + delete this; + + ltraceout(90); + } + + + GCell* GCell::getLeft () const + { + return _gcellGrid->getGCellLeft(this); + } + + + GCell* GCell::getRight () const + { + return _gcellGrid->getGCellRight(this); + } + + + GCell* GCell::getUp () const + { + return _gcellGrid->getGCellUp(this); + } + + + GCell* GCell::getDown () const + { + return _gcellGrid->getGCellDown(this); + } + + + bool GCell::areDensityConnex ( GCell* a, GCell* b ) + { return Katabatic::GCell::areDensityConnex ( a->base(), b->base() ); } + + + GCell* GCell::getLowestOrder ( TrackElement* trackSegment ) + { + vector gcells; + trackSegment->getGCells ( gcells ); + + if ( gcells.empty() ) return NULL; + + size_t ilower = 0; + for ( size_t i=0 ; igetOrder() < gcells[ilower]->getOrder() ) + ilower = i; + + return gcells[ilower]; + } + + + void GCell::loadRouting ( unsigned int order ) + { + _segments.clear (); + _order = order; + + ltrace(200) << "GCell::loadRouting() - " << this << " Session:" << Session::getOrder() << endl; + ltracein(200); + + Segment* segment; + AutoSegment* autoSegment; + + ltrace(149) << "AutoSegments from AutoContacts" << endl; + vector* contacts = getContacts(); + for ( size_t i=0 ; isize() ; i++ ) { + forEach ( Component*, component, (*contacts)[i]->getSlaveComponents() ) { + segment = dynamic_cast(*component); + autoSegment = Session::base()->lookup ( segment ); + ltrace(149) << autoSegment << endl; + if ( autoSegment ) { + addTrackSegment ( this, autoSegment, true ); + } + } + } + + // // Effective deletion of rejecteds. + // set::iterator ireject = rejecteds.begin(); + // for ( ; ireject != rejecteds.end() ; ireject++ ) { + // } + + ltrace(149) << "Horizontal overcell AutoSegments" << endl; + vector* segments = getHSegments(); + for ( size_t i=0 ; isize() ; i++ ) { + addTrackSegment ( this, (*segments)[i], true ); + } + + ltrace(149) << "Vertical overcell AutoSegments" << endl; + segments = getVSegments(); + for ( size_t i=0 ; isize() ; i++ ) { + addTrackSegment ( this, (*segments)[i], true ); + } + + ltrace(149) << "_segments.size():" << _segments.size() << endl; + ltraceout(200); + } + + + void GCell::computeBorder () + { + ltrace(200) << "GCell::computeBorder() " << this << endl; + ltracein(200); + + vector* contacts = _base->getContacts(); + TrackElement* candidate; + DataNegociate* data; + Box bb = getBoundingBox(); + size_t iLeft = 0; + size_t iRight = 0; + + for ( size_t icontact=0 ; icontact < contacts->size() ; icontact++ ) { + Component* anchor = (*contacts)[icontact]->getAnchor(); + RoutingPad* rp = dynamic_cast(anchor); + + if ( not rp ) continue; + + // size_t depth = Session::getConfiguration()->getLayerDepth ( rp->getLayer() ); + // if ( (depth != 0) and (depth != 2) ) continue; + + // ltrace(200) << "depth: " << depth << " " << rp << endl; + + candidate = getCandidate ( rp, bb ); + if ( not candidate ) continue; + + data = candidate->getDataNegociate(); + if ( not data ) continue; + + // Ugly: hardwired pitch usage. + if ( (rp->getX() - getX() < DbU::lambda(11.0)) and (iLeft < 2) ) { + //data->setLeftBorder(true); + ltrace(200) << "Left Segments[" << iLeft << "]: " << candidate << endl; + _leftSegments[iLeft++] = candidate; + continue; + } + + if ( (getXMax() - rp->getX() < DbU::lambda(11.0)) and (iRight < 2) ) { + //data->setRightBorder(true); + ltrace(200) << "Right Segment[" << iRight << "]: " << candidate << endl; + _rightSegments[iRight++] = candidate; + } + } + + ltraceout(200); + } + + + TrackElement* GCell::addTrackSegment ( GCell* gcell, AutoSegment* autoSegment, bool loading ) + { + ltrace(200) << "GCell::addTrackSegment() - " << autoSegment << endl; + ltracein(159); + + // Special case: fixed AutoSegments must not interfere with blockages. + // Ugly: uses of getExtensionCap(). + if ( autoSegment->isFixed() ) { + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer()); + Track* track = plane->getTrackByPosition ( autoSegment->getAxis() ); + size_t begin; + size_t end; + Interval fixedSpan; + Interval blockageSpan; + + autoSegment->getCanonical ( fixedSpan ); + fixedSpan.inflate ( Session::getExtensionCap() ); + + track->getOverlapBounds ( fixedSpan, begin, end ); + for ( ; (begin < end) ; begin++ ) { + + TrackElement* other = track->getSegment(begin); + ltrace(200) << "| overlap: " << other << endl; + + if ( not other->isBlockage() ) continue; + + other->getCanonical ( blockageSpan ); + blockageSpan.inflate(Session::getExtensionCap()); + + ltrace(200) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl; + + if ( not fixedSpan.intersect(blockageSpan) ) continue; + + // Overlap between fixed & blockage. + ltrace(200) << "* Blockage overlap: " << autoSegment << endl; + Session::destroyRequest ( autoSegment ); + return NULL; + } + } + + Interval span; + autoSegment = autoSegment->getCanonical ( span ); + + bool created; + TrackElement* trackSegment = TrackSegment::create ( autoSegment, NULL, created ); + DataNegociate* data = trackSegment->getDataNegociate (); + GCell* previousGCell = trackSegment->getGCell(); + + if ( not loading ) + ltrace(159) << "* lookup: " << autoSegment << endl; + + if ( created ) + ltrace(159) << "* " << trackSegment << endl; + + if ( not created and not loading ) { + ltrace(200) << "TrackSegment already exists (and not in loading stage)." << endl; + ltrace(200) << "Previous owning GCell: " << previousGCell << endl; + if ( previousGCell != gcell ) { + previousGCell->removeTrackSegment ( trackSegment ); + trackSegment->setGCell ( NULL ); + } + } + + vector gcells; + trackSegment->getGCells ( gcells ); + GCell* lowest = gcells[0]; + bool validPrevious = false; + + for ( size_t igcell=0 ; igcellgetOrder() < lowest->getOrder()) { + lowest = gcells[igcell]; + } + if ( gcells[igcell] == previousGCell ) validPrevious = true; + } + if ( not validPrevious ) previousGCell = NULL; + + if ( not gcell ) { + gcell = lowest; + if ( previousGCell and (gcell->getOrder() == previousGCell->getOrder()) ) + gcell = previousGCell; + ltrace(200) << "New owner: " << gcell << endl; + } else if ( created ) { + if ( (lowest != gcell) && (lowest->getOrder() != gcell->getOrder() ) ) { + cerr << Bug("Not the right lowest: %s",getString(lowest).c_str()) << endl; + } + } + + if ( (gcell->getOrder() > Session::getOrder()) and not (data->isRing() or data->isBorder()) ) { + cinfo << "[INFO] GCell::addTrackSegment() - Owning GCell is not in active set (" + << gcell->getOrder() << " > Session:" << Session::getOrder() << ")." + << "\n " << trackSegment + << endl; + } + + if ( not trackSegment->getGCell() ) { + trackSegment->setGCell ( gcell ); + gcell->addTrackSegment ( trackSegment ); + + if ( loading ) { + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer()); + Track* track = plane->getTrackByPosition ( autoSegment->getAxis() ); + Interval uside = gcell->getUSide ( Constant::perpandicular(autoSegment->getDirection()), false ); + + if ( track->getAxis() > uside.getVMax() ) track = track->getPrevious(); + if ( track->getAxis() < uside.getVMin() ) track = track->getNext(); + + trackSegment->setAxis ( track->getAxis(), Katabatic::Realignate|Katabatic::AxisSet ); + trackSegment->invalidate (); + + if ( created and trackSegment->isFixed() ) { + Session::addInsertEvent ( trackSegment, track ); + } + } + } + + ltraceout(159); + + return trackSegment; + } + + + void GCell::addTrackSegment ( TrackElement* trackSegment ) + { + _segments.push_back ( trackSegment ); + } + + + void GCell::removeTrackSegment ( TrackElement* trackSegment ) + { + if ( _segments.empty() ) return; + + size_t i = 0; + for ( ; i<_segments.size() ; i++ ) + if ( _segments[i] == trackSegment ) { + swap ( _segments[i], _segments[_segments.size()-1] ); + break; + } + + if ( i < _segments.size() ) _segments.pop_back (); + } + + + double GCell::getOwnedWireLength () const + { + double ownedWL = 0; + + for ( size_t i=0 ; i<_segments.size() ; i++ ) { + ownedWL += DbU::getLambda ( _segments[i]->getLength() ); + } + + return ownedWL; + } + + + void GCell::anticipateRouting ( unsigned int order ) + { + if ( order < _order ) { + setRouted ( true ); + loadRouting ( order ); + // _order = order; + // for ( size_t isegment=0 ; isegment<_segments.size() ; ++isegment ) { + // DataNegociate* data = _segments[isegment]->getDataNegociate(); + // data->setGCellOrder ( order ); + // data->resetBorder (); + // } + } + } + + + string GCell::_getTypeName() const + { return "Kite::GCell"; } + + + string GCell::_getString () const + { + string s = _base->_getString(); + s.erase ( s.size()-1 ); + s += " o:"; + s += ((_order == numeric_limits::max()) ? "-" : getString(_order)); + s += " "; + s += ((_isRouted) ? "R" : "-"); + s += ">"; + return s; + } + + + Record* GCell::_getRecord () const + { return _base->_getRecord(); } + + +} // End of Kite namespace. diff --git a/kite/src/GCellGrid.cpp b/kite/src/GCellGrid.cpp new file mode 100644 index 00000000..7635f74d --- /dev/null +++ b/kite/src/GCellGrid.cpp @@ -0,0 +1,154 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./GCellGrid.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include + +#include "hurricane/Cell.h" +#include "katabatic/GCellGrid.h" +#include "kite/GCell.h" +#include "kite/GCellGrid.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using std::cerr; + using std::endl; + + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + + +// ------------------------------------------------------------------- +// Class : "GCellGrid". + + + GCellGrid::GCellGrid ( KiteEngine* kite ) + : Katabatic::Grid() + , _kite(kite) + { } + + + void GCellGrid::_postCreate () + { + // Clone the grid from Katabatic Here. + Katabatic::GCellGrid* base = _kite->base()->getGCellGrid(); + vector* baseGCells = base->getGCellVector(); + + ltrace(80) << "Kite GCell Matrix [" << baseGCells->size() << "]" << endl; + + for ( size_t i=0 ; isize() ; i++ ) + _gcells.push_back ( GCell::create(this,(*baseGCells)[i]) ); + + _rows = base->getRows(); + _columns = base->getColumns(); + _rawSize = base->getRawSize(); + _xGraduations = base->getXGrads(); + _yGraduations = base->getYGrads(); + } + + + GCellGrid::~GCellGrid () + { } + + + void GCellGrid::_preDestroy () + { + ltrace(90) << "Kite::GCellGrid::_preDestroy()" << endl; + ltracein(90); + + vector::iterator it = _gcells.begin(); + vector::iterator end = _gcells.end (); + for ( ; it != end ; it++ ) (*it)->destroy (); + + ltraceout(90); + } + + + Cell* GCellGrid::getCell () const + { + return _kite->getCell(); + } + + + GCellGrid* GCellGrid::create ( KiteEngine* kite ) + { + GCellGrid* subFCellGrid = new Kite::GCellGrid ( kite ); + + subFCellGrid->_postCreate (); + + return subFCellGrid; + } + + + double GCellGrid::getTotalWireLength () const + { + double totalWL = 0; + for ( size_t i=0 ; i < _gcells.size() ; i++ ) { + totalWL += _gcells[i]->getOwnedWireLength (); + } + return totalWL; + } + + + void GCellGrid::_check () const + { + cerr << " o Checking Kite GCell Grid." << endl; + for ( size_t i=0 ; i < _gcells.size() ; i++ ) { + if ( _gcells[i]->base() == NULL ) { + cerr << "[CHECK] _gcells[" << i << "]: " << (void*)_gcells[i] << " has NULL base." << endl; + } + } + cerr << " - Successful." << endl; + } + + + string GCellGrid::_getTypeName () const + { + return "Kite::GCellGrid"; + } + + + string GCellGrid::_getString () const + { + return "<" + _getTypeName() + " " + + getString(getRows()) + "x" + getString(getColumns()) + ">"; + } + + + Record* GCellGrid::_getRecord () const + { + Record* record = Katabatic::Grid::_getRecord (); + record->add ( getSlot ( "_kite", _kite ) ); + return record; + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/GCellRoutingSet.cpp b/kite/src/GCellRoutingSet.cpp new file mode 100644 index 00000000..4d5ad49e --- /dev/null +++ b/kite/src/GCellRoutingSet.cpp @@ -0,0 +1,402 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./GCellRoutingSet.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#include +#include +#include + +#include "hurricane/Error.h" +#include "hurricane/Contact.h" +#include "hurricane/Segment.h" +#include "hurricane/RoutingPad.h" +#include "katabatic/AutoSegment.h" +#include "kite/GCell.h" +#include "kite/GCellGrid.h" +#include "kite/GCellRoutingSet.h" +#include "kite/DataNegociate.h" + + +namespace Kite { + + + using std::numeric_limits; + using std::queue; + using std::cerr; + using std::endl; + using std::ostringstream; + using std::setprecision; + using Hurricane::roundfp; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::Error; + using Katabatic::getVectorString; + + + const char* usedGCellSeed = + "GCellRoutingSet::create() : %s is already in a GCellRoutingSet.\n"; + + +// ------------------------------------------------------------------- +// Class : "GCellRoutingSet". + + + GCellRoutingSet::GCellRoutingSet ( GCell* gcell, float expandStep, float minDensity ) + : _order (numeric_limits::max()) + , _minDensity (minDensity) + , _minDensities (new float [gcell->getDepth()]) + , _gcells (1,gcell) + , _borderSegments() + , _statistics () + { + gcell->setInRoutingSet ( true ); + + if ( _minDensity > expandStep ) _minDensity -= expandStep; + else _minDensity = 0.0; + _minDensity = roundfp ( _minDensity ); + for ( unsigned int i=0 ; i < gcell->getDepth() ; i++ ) { + _minDensities[i] = gcell->getDensity(i) * expandStep; + _minDensities[i] = roundfp ( _minDensities[i] ); + } + ltrace(200) << getVectorString(_minDensities,gcell->getDepth()) << endl; + } + + + void GCellRoutingSet::_postCreate () + { + ltrace(90) << "Kite::GCellRoutingSet::_postCreate() - " << (void*)this << " " << this << endl; + ltracein(90); + + ltraceout(90); + } + + + GCellRoutingSet::~GCellRoutingSet () + { + delete [] _minDensities; + } + + + void GCellRoutingSet::_preDestroy () + { } + + + void GCellRoutingSet::destroy () + { + _preDestroy (); + delete this; + } + + + GCellRoutingSet* GCellRoutingSet::create ( GCell* gcell, float expandStep ) + { + if ( gcell->isInRoutingSet() ) + throw Error ( usedGCellSeed, getString(gcell).c_str() ); + + GCellRoutingSet* rs = new GCellRoutingSet ( gcell + , expandStep + , gcell->getDensity() + ); + rs->_postCreate (); + + return rs; + } + + + void GCellRoutingSet::setRouted ( bool state ) + { + for ( size_t igcell=0 ; igcell<_gcells.size() ; ++igcell ) + _gcells[igcell]->setRouted ( true ); + } + + + vector& GCellRoutingSet::getOwnedSegments ( vector& segments ) const + { + for ( size_t i=0 ; i<_gcells.size() ; i++ ) { + if ( _gcells[i]->isRouted() ) continue; + + const vector& gcellSegments = _gcells[i]->getOwnedSegments(); + for ( size_t j=0 ; jisFixed() ) + segments.push_back ( gcellSegments[j] ); + } +// segments.insert ( segments.end() +// , _gcells[i]->getOwnedSegments().begin() +// , _gcells[i]->getOwnedSegments().end() +// ); + } + + for ( size_t i=0 ; i<_borderSegments.size() ; i++ ) { + TrackElement* segment = _borderSegments[i]._segment; + DataNegociate* data = segment->getDataNegociate(); + data->setGCellOrder ( _order ); + segments.push_back ( segment ); + } + + return segments; + } + + + void GCellRoutingSet::expand ( GCellGrid* grid ) + { +#if defined(CHECK_DETERMINISM) + cerr << "Order: Expanding " << this << endl; +#endif + + ltrace(200) << "Expanding: " << this << endl; + ltracein(200); + ltrace(200) << getVectorString(_minDensities,_gcells.front()->getDepth()) << endl; + + queue densityQueue; + densityQueue.push ( _gcells.front() ); + + while ( !densityQueue.empty() ) { + GCell* current = densityQueue.front (); + GCell* neighbor = NULL; + densityQueue.pop (); + + ltrace(200) << "Popping Density: " << current << endl; + + for ( size_t i=0 ; i<4 ; i++ ) { + switch ( i ) { + case 0: neighbor = grid->getGCellLeft (current); break; + case 1: neighbor = grid->getGCellRight(current); break; + case 2: neighbor = grid->getGCellUp (current); break; + case 3: neighbor = grid->getGCellDown (current); break; + } + + if ( neighbor ) { +#if defined(CHECK_DETERMINISM) + cerr << "Order: Looking at neighbor " << neighbor << endl; +#endif + float densities[32]; + neighbor->base()->getDensities ( densities ); + ltrace(200) << "Neighbor: " << neighbor << " " << getVectorString(densities,5) << endl; + } + + if ( neighbor and !neighbor->isInRoutingSet() ) { + if ( not neighbor->isAboveDensity(_minDensity) + and not GCell::areDensityConnex(current,neighbor) ) + continue; + +#if defined(CHECK_DETERMINISM) + cerr << "Order: Agglomerate " << neighbor << endl; +#endif + ltrace(200) << "Agglomerating: " << neighbor << endl; + + neighbor->setInRoutingSet ( true ); + _gcells.push_back ( neighbor ); + densityQueue.push ( neighbor ); + } + } + } + + // De-notching pass. + for ( size_t i=0 ; i<_gcells.size() ; i++ ) densityQueue.push ( _gcells[i] ); + + while ( not densityQueue.empty() ) { + GCell* current = densityQueue.front(); + GCell* neighbor = NULL; + + densityQueue.pop(); + + for ( size_t i=0 ; i<4 ; i++ ) { + switch ( i ) { + case 0: neighbor = grid->getGCellLeft (current); break; + case 1: neighbor = grid->getGCellRight(current); break; + case 2: neighbor = grid->getGCellUp (current); break; + case 3: neighbor = grid->getGCellDown (current); break; + } + + if ( not neighbor ) continue; + +#if defined(CHECK_DETERMINISM) + cerr << "Order: Denotching, looking at neighbor " << neighbor << endl; +#endif + if ( neighbor->isInRoutingSet() ) continue; + + GCell* left = grid->getGCellLeft (neighbor); + GCell* right = grid->getGCellRight(neighbor); + GCell* up = grid->getGCellUp (neighbor); + GCell* down = grid->getGCellDown (neighbor); + + bool hasLeft = (left) ? left ->isInRoutingSet() : true; + bool hasRight = (right) ? right->isInRoutingSet() : true; + bool hasUp = (up) ? up ->isInRoutingSet() : true; + bool hasDown = (down) ? down ->isInRoutingSet() : true; + + if ( (not (hasLeft and hasRight)) and (not (hasUp and hasDown)) ) continue; + +#if defined(CHECK_DETERMINISM) + cerr << "Order: Denotching, Agglomerate " << neighbor << endl; +#endif + ltrace(200) << "Denotching, Agglomerating: " << neighbor << endl; + + neighbor->setInRoutingSet ( true ); + _gcells.push_back ( neighbor ); + densityQueue.push ( neighbor ); + } + } + + ltrace(200) << "GCellRoutingSet (final): " << this << endl; + for ( size_t i=0 ; i<_gcells.size() ; i++ ) + ltrace(200) << "| " << _gcells[i] << endl; + + _statistics.setGCellsCount ( _gcells.size() ); + _statistics.setSegmentsCount ( 0 ); + for ( size_t i=0 ; i<_gcells.size() ; i++ ) { + const vector& gcellSegments = _gcells[i]->getOwnedSegments(); + _statistics.incSegmentsCount ( gcellSegments.size() ); + } + + ltraceout(200); + } + + + void GCellRoutingSet::loadBorder ( GCellGrid* grid ) + { + ltrace(200) << "loadBorder() " << this << endl; + unsigned int order = _order; + TrackElement* segment = NULL; + DataNegociate* data; + + for ( size_t igcell=0 ; igcell<_gcells.size() ; igcell++ ) { + if ( _gcells[igcell]->getOrder() < order ) continue; + + GCell* neighbor = NULL; + + for ( size_t i=0 ; i<2 ; i++ ) { + switch ( i ) { + case 0: neighbor = grid->getGCellLeft (_gcells[igcell]); break; + case 1: neighbor = grid->getGCellRight(_gcells[igcell]); break; + } + if ( not neighbor or (neighbor->getOrder() <= order) ) continue; + + neighbor->computeBorder (); + + for ( size_t iRight=0 ; iRight<2 ; iRight++ ) { + segment = neighbor->getRightRp(iRight); + if ( segment == NULL ) break; + + data = (segment) ? segment->getDataNegociate() : NULL; + if ( data ) { + if ( (i == 0) and (data->getGCellOrder() > order) and not data->isRing() ) { + ltrace(200) << "| border: [" << data->getGCellOrder() + << " > " << order << "] " << segment << endl; + data->setRightBorder ( true ); + _borderSegments.push_back ( BorderSegment(segment,data->getGCellOrder()) ); + } else + data->resetBorder(); + } + } + + for ( size_t iLeft=0 ; iLeft<2 ; iLeft++ ) { + segment = neighbor->getLeftRp(iLeft); + if ( segment == NULL ) break; + + data = (segment) ? segment->getDataNegociate() : NULL; + if ( data ) { + if ( (i == 1) and (data->getGCellOrder() > order) and not data->isRing() ) { + ltrace(200) << "| border: [" << data->getGCellOrder() + << " > " << order << "] " << segment << endl; + data->setLeftBorder ( true ); + _borderSegments.push_back ( BorderSegment(segment,data->getGCellOrder()) ); + } else + data->resetBorder(); + } + } + } + } + } + + + void GCellRoutingSet::freeBorder () + { + for ( size_t j=0 ; j<_borderSegments.size() ; j++ ) { + DataNegociate* data = _borderSegments[j]._segment->getDataNegociate(); + if ( not data->isBorder() ) continue; + + data->resetBorder (); + data->setGCellOrder ( _borderSegments[j]._order ); + Session::addRemoveEvent ( _borderSegments[j]._segment ); + //_borderSegments[j]._segment->base()->setFixed(true); + } + Session::revalidate (); + + vector().swap ( _borderSegments ); + } + + + unsigned int& GCellRoutingSet::loadRouting ( unsigned int& order ) + { + _order = order; + //cerr << "RoutingSet order:" << order << endl; + + for ( size_t i=0 ; i<_gcells.size() ; i++ ) + _gcells[i]->loadRouting ( order ); + + return ++order; + } + + + string GCellRoutingSet::_getTypeName () const + { return "GCellRoutingSet"; } + + + string GCellRoutingSet::_getString () const + { + ostringstream s; + + s << "::max()) ? getString(_order) : "-") + << " " << _gcells.front() << setprecision(9) + << " [" << ":" << _minDensity + << "] " << _gcells.size() + << ">"; + return s.str(); + + //return "::max()) ? getString(_order) : "-") + // + " " + getString(_gcells.front()) + // + " [" + /*getString(_minDensity)*/ + ":" + getString(_minDensity) + // + "] " + getString(_gcells.size()) + // + ">"; + } + + + Record* GCellRoutingSet::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_gcells" , &_gcells ) ); + record->add ( getSlot ( "_order" , _order ) ); + record->add ( getSlot ( "_minDensity", _minDensity ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/GraphicKiteEngine.cpp b/kite/src/GraphicKiteEngine.cpp new file mode 100644 index 00000000..9dc361b2 --- /dev/null +++ b/kite/src/GraphicKiteEngine.cpp @@ -0,0 +1,395 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./GraphicKiteEngine.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Kite { + + + using namespace std; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Breakpoint; + using Hurricane::DebugSession; + using Hurricane::UpdateSession; + using Hurricane::Net; + using Hurricane::Graphics; + using Hurricane::ColorScale; + using CRL::Catalog; + using CRL::AllianceFramework; + using Knik::KnikEngine; + + + size_t GraphicKiteEngine::_references = 0; + GraphicKiteEngine* GraphicKiteEngine::_singleton = NULL; + + + void GraphicKiteEngine::initKatabaticAc ( CellWidget* widget ) + { + //cerr << "GraphicKatabaticEngine::initKatabaticGo()" << endl; + } + + + void GraphicKiteEngine::drawKatabaticAc ( CellWidget* widget + , const Go* go + , const BasicLayer* basicLayer + , const Box& box + , const Transformation& transformation + ) + { } + + + void GraphicKiteEngine::initKatabaticGCell ( CellWidget* widget ) + { + widget->getDrawingPlanes().setPen ( Qt::NoPen ); + } + + + void GraphicKiteEngine::drawKatabaticGCell ( CellWidget* widget + , const Go* go + , const BasicLayer* basicLayer + , const Box& box + , const Transformation& transformation + ) + { + const Katabatic::GCell* gcell = static_cast(go); + + QPainter& painter = widget->getPainter(); + size_t density = (size_t)( gcell->getMaxHVDensity() * 255.0 ); + if ( density > 255 ) density = 255; + + painter.setBrush + ( Graphics::getColorScale(ColorScale::Fire).getBrush(density,widget->getDarkening()) ); + painter.drawRect + ( widget->dbuToDisplayRect(gcell->getBoundingBox().inflate(0 + ,0 + ,gcell->getTopRightShrink() + ,gcell->getTopRightShrink())) ); + } + + + KiteEngine* GraphicKiteEngine::createEngine ( const RoutingGauge* rg ) + { + Cell* cell = getCell (); + + KiteEngine* kite = KiteEngine::get ( cell ); + if ( not kite ) { + kite = KiteEngine::create ( rg, cell ); + kite->setPostEventCb ( boost::bind(&GraphicKiteEngine::postEvent,this) ); + } else + cerr << Warning("%s already has a Kite engine.",getString(cell).c_str()) << endl; + + return kite; + } + + + KiteEngine* GraphicKiteEngine::getForFramework () + { + // Currently, only one framework is avalaible: Alliance. + + KiteEngine* kite = KiteEngine::get ( getCell() ); + if ( kite ) return kite; + + AllianceFramework* af = AllianceFramework::get (); + kite = createEngine ( af->getRoutingGauge() ); + + if ( not kite ) + throw Error("Failed to create Kite engine on %s.",getString(getCell()).c_str()); + + return kite; + } + + + void GraphicKiteEngine::saveGlobalSolution () + { + KiteEngine* kite = KiteEngine::get ( getCell() ); + if ( kite ) kite->saveGlobalSolution (); + } + + + void GraphicKiteEngine::loadGlobalSolution () + { + + KiteEngine* kite = getForFramework (); + + emit cellPreModificated (); + kite->runGlobalRouter ( LoadGlobalSolution ); + emit cellPostModificated (); + } + + + void GraphicKiteEngine::runGlobal () + { + + KiteEngine* kite = getForFramework (); + + emit cellPreModificated (); + kite->runGlobalRouter ( BuildGlobalSolution ); + emit cellPostModificated (); + } + + + void GraphicKiteEngine::runDetailed () + { + static vector routingNets; + + KiteEngine* kite = KiteEngine::get ( getCell() ); + if ( not kite ) { + throw Error("KiteEngine not created yet, run the global router first."); + } + + emit cellPreModificated (); + + _viewer->clearToolInterrupt (); + + // kite->setSaturateRatio ( 0.85 ); + // kite->setExpandStep ( 0.20 ); + // kite->setRipupLimit ( 25, Configuration::BorderRipupLimit ); + // kite->setRipupLimit ( 15, Configuration::StrapRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::LocalRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::GlobalRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::LongGlobalRipupLimit ); + // kite->setRipupCost ( 3 ); + kite->loadGlobalRouting ( Katabatic::LoadGrByNet, routingNets ); + emit cellPostModificated (); + + //Breakpoint::stop ( 0, "Point d'arret:
      LayerAssingByTrunk()
    " + // "Assignment des layers, methode globale." ); + emit cellPreModificated (); + kite->layerAssign ( Katabatic::NoNetLayerAssign ); + emit cellPostModificated (); + + //Breakpoint::stop ( 0, "Point d'arret:
      runNegociate()
    " + // "Routage par Negociation." ); + emit cellPreModificated (); + kite->runNegociate (); + emit cellPostModificated (); + } + + + void GraphicKiteEngine::finalize () + { + emit cellPreModificated (); + KiteEngine* kite = KiteEngine::get ( getCell() ); + if ( kite ) { + kite->finalizeLayout (); + kite->destroy (); + } + emit cellPostModificated (); + } + + + void GraphicKiteEngine::save () + { + //KiteEngine* kite = KiteEngine::get ( getCell() ); + //if ( kite ) { + Cell* cell = getCell(); + AllianceFramework* af = AllianceFramework::get (); + + string name = getString(cell->getName()) + "_kite"; + cell->setName ( name ); + af->saveCell ( cell, Catalog::State::Physical ); + //} + } + + + void GraphicKiteEngine::postEvent () + { + static unsigned int count = 0; + + if ( not (count++ % 500) ) { + //UpdateSession::close (); + + //_viewer->getCellWidget()->refresh (); + QApplication::processEvents (); + + //UpdateSession::open (); + + if ( _viewer->isToolInterrupted() ) { + KiteEngine* kite = KiteEngine::get ( getCell() ); + if ( kite ) kite->setInterrupt ( true ); + + _viewer->clearToolInterrupt (); + } + } + } + + + void GraphicKiteEngine::addToMenu ( CellViewer* viewer ) + { + assert ( _viewer == NULL ); + + _viewer = viewer; + + QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); + QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); + if ( !prMenu ) { + QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); + if ( !menuBar ) { + cerr << Warning("GraphicKiteEngine::addToMenu() - No MenuBar in parent widget.") << endl; + return; + } + prMenu = menuBar->addMenu ( tr("P&&R") ); + prMenu->setObjectName ( "viewer.menuBar.placeAndRoute" ); + + stepMenu = prMenu->addMenu ( tr("&Step by Step") ); + stepMenu->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep" ); + + prMenu->addSeparator (); + } + + QAction* dRouteAction = _viewer->findChild("viewer.menuBar.placeAndRoute.detailedRoute"); + if ( dRouteAction ) + cerr << Warning("GraphicKiteEngine::addToMenu() - Kite detailed router already hooked in.") << endl; + else { + QAction* gLoadSolutionAction = new QAction ( tr("Kite - &Load Global Solution"), _viewer ); + gLoadSolutionAction->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep.loadSolution" ); + gLoadSolutionAction->setStatusTip ( tr("Load a solution for the global routing (.kgr)") ); + gLoadSolutionAction->setVisible ( true ); + stepMenu->addAction ( gLoadSolutionAction ); + + QAction* gSaveSolutionAction = new QAction ( tr("Kite - &Save Global Solution"), _viewer ); + gSaveSolutionAction->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep.saveSolution" ); + gSaveSolutionAction->setStatusTip ( tr("Save a global router solution (.kgr)") ); + gSaveSolutionAction->setVisible ( true ); + stepMenu->addAction ( gSaveSolutionAction ); + + QAction* gRouteAction = new QAction ( tr("Kite - &Global Route"), _viewer ); + gRouteAction->setObjectName ( "viewer.menuBar.placeAndRoute.globalRoute" ); + gRouteAction->setStatusTip ( tr("Run the Knik global router") ); + gRouteAction->setVisible ( true ); + prMenu->addAction ( gRouteAction ); + + dRouteAction = new QAction ( tr("Kite - &Detailed Route"), _viewer ); + dRouteAction->setObjectName ( "viewer.menuBar.placeAndRoute.detailedRoute" ); + dRouteAction->setStatusTip ( tr("Run the Kite detailed router") ); + dRouteAction->setVisible ( true ); + prMenu->addAction ( dRouteAction ); + + QAction* dFinalizeAction = new QAction ( tr("Kite - &Finalize Routing"), _viewer ); + dFinalizeAction->setObjectName ( "viewer.menuBar.placeAndRoute.finalize" ); + dFinalizeAction->setStatusTip ( tr("Closing Routing") ); + dFinalizeAction->setVisible ( true ); + prMenu->addAction ( dFinalizeAction ); + + QAction* dSaveAction = new QAction ( tr("Kite - &Save Design"), _viewer ); + dSaveAction->setObjectName ( "viewer.menuBar.placeAndRoute.save" ); + dSaveAction->setStatusTip ( tr("Save routed design (temporary hack)") ); + dSaveAction->setVisible ( true ); + prMenu->addAction ( dSaveAction ); + + connect ( gLoadSolutionAction, SIGNAL(triggered()), this, SLOT(loadGlobalSolution()) ); + connect ( gSaveSolutionAction, SIGNAL(triggered()), this, SLOT(saveGlobalSolution()) ); + connect ( gRouteAction , SIGNAL(triggered()), this, SLOT(runGlobal ()) ); + connect ( dRouteAction , SIGNAL(triggered()), this, SLOT(runDetailed ()) ); + connect ( dFinalizeAction , SIGNAL(triggered()), this, SLOT(finalize ()) ); + connect ( dSaveAction , SIGNAL(triggered()), this, SLOT(save ()) ); + } + + connect ( this, SIGNAL(cellPreModificated ()), _viewer->getCellWidget(), SLOT(cellPreModificate ()) ); + connect ( this, SIGNAL(cellPostModificated()), _viewer->getCellWidget(), SLOT(cellPostModificate()) ); + } + + + const Name& GraphicKiteEngine::getName () const + { + return KiteEngine::staticGetName (); + } + + + Cell* GraphicKiteEngine::getCell () + { + if ( !_viewer ) { + throw Error ( "Kite: GraphicKiteEngine not bound to any Viewer." ); + return NULL; + } + + if ( !_viewer->getCell() ) { + throw Error ( "Kite: No Cell is loaded into the Viewer." ); + return NULL; + } + + return _viewer->getCell(); + } + + + GraphicKiteEngine* GraphicKiteEngine::grab () + { + if ( !_references ) { + _singleton = new GraphicKiteEngine (); + } + _references++; + + return _singleton; + } + + + size_t GraphicKiteEngine::release () + { + _references--; + if ( !_references ) { + delete _singleton; + _singleton = NULL; + } + return _references; + } + + + GraphicKiteEngine::GraphicKiteEngine () + : GraphicTool() + , _viewer(NULL) + { + addDrawGo ( "Katabatic::Ac" , initKatabaticAc , drawKatabaticAc ); + addDrawGo ( "Katabatic::GCell", initKatabaticGCell, drawKatabaticGCell ); + } + + + GraphicKiteEngine::~GraphicKiteEngine () + { } + + +} // End of Kite namespace. diff --git a/kite/src/HorizontalTrack.cpp b/kite/src/HorizontalTrack.cpp new file mode 100644 index 00000000..70ea05da --- /dev/null +++ b/kite/src/HorizontalTrack.cpp @@ -0,0 +1,84 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./HorizontalTrack.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "kite/HorizontalTrack.h" + + +namespace Kite { + + +// ------------------------------------------------------------------- +// Class : "HorizontalTrack". + + + HorizontalTrack::HorizontalTrack ( RoutingPlane* routingPlane, unsigned int index ) + : Track(routingPlane,index) + { } + + + void HorizontalTrack::_postCreate () + { } + + + HorizontalTrack* HorizontalTrack::create ( RoutingPlane* routingPlane, unsigned int index ) + { + HorizontalTrack* track = new HorizontalTrack ( routingPlane, index ); + + track->_postCreate (); + return track; + } + + + HorizontalTrack::~HorizontalTrack () + { } + + + void HorizontalTrack::_preDestroy () + { } + + + bool HorizontalTrack::isHorizontal () const { return true; } + bool HorizontalTrack::isVertical () const { return false; } + unsigned int HorizontalTrack::getDirection () const { return Constant::Horizontal; } + + + Point HorizontalTrack::getPosition ( DbU::Unit coordinate ) const + { + return Point ( coordinate, getAxis() ); + } + + + string HorizontalTrack::_getTypeName () const + { return "HorizontalTrack"; } + + + Record* HorizontalTrack::_getRecord () const + { + Record* record = Track::_getRecord (); + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp new file mode 100644 index 00000000..0f785575 --- /dev/null +++ b/kite/src/KiteEngine.cpp @@ -0,0 +1,652 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./KiteEngine.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/Error.h" +#include "hurricane/Warning.h" +#include "hurricane/Layer.h" +#include "hurricane/Net.h" +#include "hurricane/Pad.h" +#include "hurricane/Plug.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" +#include "hurricane/Vertical.h" +#include "hurricane/Horizontal.h" +#include "hurricane/UpdateSession.h" + +#include "knik/KnikEngine.h" +#include "katabatic/AutoContact.h" +#include "kite/DataNegociate.h" +#include "kite/GCellGrid.h" +#include "kite/RoutingPlane.h" +#include "kite/Session.h" +#include "kite/GCellRoutingSet.h" +#include "kite/NegociateWindow.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using std::cout; + using std::cerr; + using std::endl; + using std::setw; + using std::left; + using std::ostringstream; + using std::setprecision; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::ForEachIterator; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Warning; + using Hurricane::Layer; + using Hurricane::Cell; + using Knik::KnikEngine; + + + const char* missingRW = + "%s :\n\n" + " Cell %s do not have any KiteEngine (or not yet created).\n"; + + +// ------------------------------------------------------------------- +// Class : "Kite::KiteEngine". + + + Name KiteEngine::_toolName = "Kite"; + + + const Name& KiteEngine::staticGetName () + { return _toolName; } + + + KiteEngine* KiteEngine::get ( const Cell* cell ) + { + return static_cast(ToolEngine::get(cell,staticGetName())); + } + + + KiteEngine::KiteEngine ( const RoutingGauge* gauge, Cell* cell ) + : KatabaticEngine (gauge,cell) + , _knik (NULL) + , _obstacleNet (NULL) + , _configuration (getKatabaticConfiguration()) + , _routingPlanes () + , _kiteGrid (NULL) + , _negociateWindow (NULL) + , _trackSegmentLut () + , _minimumWL (0.0) + , _toolSuccess (false) + { + } + + + void KiteEngine::_postCreate () + { + KatabaticEngine::_postCreate (); + +#ifdef KNIK_NOT_EMBEDDED + size_t maxDepth = getRoutingGauge()->getDepth(); + + _kiteGrid = GCellGrid::create ( this ); + + _routingPlanes.reserve ( maxDepth ); + for ( size_t depth=0 ; depth < maxDepth ; depth++ ) { + _routingPlanes.push_back ( RoutingPlane::create ( this, depth ) ); + } +#endif + } + + + KiteEngine* KiteEngine::create ( const RoutingGauge* gauge, Cell* cell ) + { + KiteEngine* kite = new KiteEngine ( gauge, cell ); + + kite->_postCreate (); + return kite; + } + + + void KiteEngine::_preDestroy () + { + ltrace(90) << "KiteEngine::_preDestroy ()" << endl; + ltracein(90); + + cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <" + << _cell->getName() << ">" << endl; + + if ( getState() < Katabatic::StateGutted ) + setState ( Katabatic::StatePreDestroying ); + + _gutKite (); + KatabaticEngine::_preDestroy (); + + cmess2 << " - RoutingEvents := " << RoutingEvent::getAllocateds() << endl; + + //_knik->destroy (); + + ltraceout(90); + } + + + KiteEngine::~KiteEngine () + { } + + + const Name& KiteEngine::getName () const + { return _toolName; } + + + Configuration* KiteEngine::getConfiguration () + { return &_configuration; } + + + unsigned int KiteEngine::getRipupLimit ( const TrackElement* segment ) const + { + if ( segment->isBlockage() ) return 0; + + if ( segment->getDataNegociate() ) { + if ( segment->getDataNegociate()->isBorder() ) + return _configuration.getRipupLimit(Configuration::BorderRipupLimit); + + if ( segment->getDataNegociate()->isRing() ) + return _configuration.getRipupLimit(Configuration::GlobalRipupLimit); + } + + if ( segment->isStrap () ) return _configuration.getRipupLimit(Configuration::StrapRipupLimit); + if ( segment->isGlobal() ) { + vector gcells; + segment->getGCells(gcells); + if ( gcells.size() > 2 ) + return _configuration.getRipupLimit(Configuration::LongGlobalRipupLimit); + return _configuration.getRipupLimit(Configuration::GlobalRipupLimit); + } + return _configuration.getRipupLimit(Configuration::LocalRipupLimit); + } + + + RoutingPlane* KiteEngine::getRoutingPlaneByIndex ( size_t index ) const + { + if ( index >= getRoutingPlanesSize() ) return NULL; + + return _routingPlanes[index]; + } + + + RoutingPlane* KiteEngine::getRoutingPlaneByLayer ( const Layer* layer ) const + { + for ( size_t index=0 ; index < getRoutingPlanesSize() ; index++ ) { + if ( _routingPlanes[index]->getLayer() == layer ) + return _routingPlanes[index]; + } + return NULL; + } + + + Track* KiteEngine::getTrackByPosition ( const Layer* layer, DbU::Unit axis, unsigned int mode ) const + { + RoutingPlane* plane = getRoutingPlaneByLayer ( layer ); + if ( !plane ) return NULL; + + return plane->getTrackByPosition ( axis, mode ); + } + + + void KiteEngine::setInterrupt ( bool state ) + { + if ( _negociateWindow ) { + _negociateWindow->setInterrupt ( state ); + cerr << "Interrupt [CRTL+C] of " << this << endl; + } + } + + + void KiteEngine::createGlobalGraph ( unsigned int mode ) + { + Cell* cell = getCell(); + if ( not _knik ) { + if ( cell->getRubbers().getFirst() == NULL ) + cell->flattenNets ( (mode==BuildGlobalSolution) ); + KnikEngine::setEdgeCapacityPercent ( getEdgeCapacityPercent() ); + _knik = KnikEngine::create ( cell + , 1 // _congestion + , 2 // _preCongestion + , false // _benchMode + , true // _useSegments + , 2.5 // _edgeCost + ); + //if ( mode == LoadGlobalSolution ) + _knik->createRoutingGraph (); + } + } + + + void KiteEngine::createDetailedGrid () + { + KatabaticEngine::createDetailedGrid (); + _kiteGrid = GCellGrid::create ( this ); + + size_t maxDepth = getRoutingGauge()->getDepth(); + + _routingPlanes.reserve ( maxDepth ); + for ( size_t depth=0 ; depth < maxDepth ; depth++ ) { + _routingPlanes.push_back ( RoutingPlane::create ( this, depth ) ); + } + } + + + void KiteEngine::saveGlobalSolution () + { + if ( getState() < Katabatic::StateGlobalLoaded ) + throw Error ("KiteEngine::saveGlobalSolution() : global routing not present yet."); + + if ( getState() > Katabatic::StateGlobalLoaded ) + throw Error ("KiteEngine::saveGlobalSolution() : cannot save after detailed routing."); + + _knik->saveSolution (); + } + + + void KiteEngine::annotateGlobalGraph () + { + cmess1 << " o Back annotate global routing graph." << endl; + + for ( size_t depth=0 ; depth<_routingPlanes.size() ; ++depth ) { + RoutingPlane* rp = _routingPlanes[depth]; + if ( rp->getLayerGauge()->getType() == Constant::PinOnly ) continue; + + size_t tracksSize = rp->getTracksSize(); + for ( size_t itrack=0 ; itrackgetTrackByIndex ( itrack ); + TrackElement* element = track->getSegment ( (size_t)0 ); + + if ( element == NULL ) continue; + if ( element->getNet() == NULL ) continue; + if ( not element->getNet()->isSupply() ) continue; + + cinfo << "Capacity from: " << element << endl; + + if ( track->getDirection() == Constant::Horizontal ) { + for ( ; element != NULL ; element = element->getNext() ) { + GCell* gcell = _kiteGrid->getGCell ( Point(element->getSourceU(),track->getAxis()) ); + GCell* end = _kiteGrid->getGCell ( Point(element->getTargetU(),track->getAxis()) ); + GCell* right = NULL; + if ( not gcell ) { + cerr << Warning("annotageGlobalGraph(): TrackElement outside GCell grid.") << endl; + continue; + } + while ( gcell and (gcell != end) ) { + right = gcell->getRight(); + if ( right == NULL ) break; + + _knik->increaseEdgeCapacity ( gcell->getColumn() + , gcell->getRow() + , right->getColumn() + , right->getRow() + , -1 ); + gcell = right; + } + } + } else { + for ( ; element != NULL ; element = element->getNext() ) { + GCell* gcell = _kiteGrid->getGCell ( Point(track->getAxis(),element->getSourceU()) ); + GCell* end = _kiteGrid->getGCell ( Point(track->getAxis(),element->getTargetU()) ); + GCell* up = NULL; + if ( not gcell ) { + cerr << Warning("annotageGlobalGraph(): TrackElement outside GCell grid.") << endl; + continue; + } + while ( gcell and (gcell != end) ) { + up = gcell->getUp(); + if ( up == NULL ) break; + + _knik->increaseEdgeCapacity ( gcell->getColumn() + , gcell->getRow() + , up->getColumn() + , up->getRow() + , -1 ); + + gcell = up; + } + } + } + } + } + } + + + void KiteEngine::runGlobalRouter ( unsigned int mode ) + { + if ( getState() >= Katabatic::StateGlobalLoaded ) + throw Error ("KiteEngine::runGlobalRouter() : global routing already done or loaded."); + + Session::open ( this ); + + createGlobalGraph ( mode ); + createDetailedGrid (); + buildBlockages (); + buildPowerRails (); + + if ( mode == LoadGlobalSolution ) { + _knik->loadSolution (); + } else { + annotateGlobalGraph (); + _knik->run (); + } + + setState ( Katabatic::StateGlobalLoaded ); + + Session::close (); + } + + + void KiteEngine::loadGlobalRouting ( unsigned int method, vector& nets ) + { + KatabaticEngine::loadGlobalRouting ( method, nets ); + + Session::open ( this ); + getGCellGrid()->checkEdgeSaturation ( getEdgeCapacityPercent() ); + Session::close (); + } + + + void KiteEngine::runNegociate ( unsigned int slowMotion ) + { + if ( _negociateWindow ) return; + + unsigned int rows = _kiteGrid->getRows(); + unsigned int columns = _kiteGrid->getColumns(); + + startMeasures (); + + Session::open ( this ); + + cmess1 << " o Running Negociate Algorithm" << endl; + + _negociateWindow = NegociateWindow::create ( this, 0, 0, columns, rows ); + _negociateWindow->loadRouting (); + preProcess (); + _computeCagedConstraints (); + _negociateWindow->run ( slowMotion ); + _negociateWindow->printStatistics (); + _negociateWindow->destroy (); + _negociateWindow = NULL; + + Session::close (); + //if ( _editor ) _editor->refresh (); + + stopMeasures (); + printMeasures (); + printCompletion (); + + Session::open ( this ); + unsigned int overlaps = 0; + float edgeCapacity = 1.0; + KnikEngine* knik = KnikEngine::get ( getCell() ); + + if ( knik ) + edgeCapacity = knik->getEdgeCapacityPercent(); + + cmess2 << " o Post-checking Knik capacity overload " << (edgeCapacity*100.0) << "%." << endl; + + _kiteGrid->base()->checkEdgeSaturation ( edgeCapacity ); + _check ( overlaps ); + Session::close (); + + _toolSuccess = _toolSuccess and (overlaps == 0); + } + + + void KiteEngine::printCompletion () const + { + cout << " o Computing Completion ratios." << endl; + cout << " - Unrouted segments :" << endl; + + size_t routeds = 0; + size_t unrouteds = 0; + unsigned long long totalWireLength = 0; + unsigned long long routedWireLength = 0; + + TrackElementLut::const_iterator ilut = _trackSegmentLut.begin(); + for ( ; ilut != _trackSegmentLut.end() ; ilut++ ) { + unsigned long long wl = (unsigned long long)DbU::getLambda(ilut->second->getLength()); + if ( wl > 100000 ) { + cerr << Error("KiteEngine::printCompletion(): Suspiciously long wire: %llu for %p:%s" + ,wl,ilut->first,getString(ilut->second).c_str()) << endl; + continue; + } + totalWireLength += wl; + if ( ilut->second->getTrack() != NULL ) { + routeds++; + routedWireLength += wl; + } else { + cout << " " << setw(4) << ++unrouteds << "| " << ilut->second << endl; + } + } + + float segmentRatio = (float)(routeds) / (float)(_trackSegmentLut.size()) * 100.0; + float wireLengthRatio = (float)(routedWireLength) / (float)(totalWireLength) * 100.0; + + cout << " - Track Segment Completion Ratio := " + << setprecision(4) << segmentRatio + << "% [" << routeds << "/" << _trackSegmentLut.size() << "] " + << (_trackSegmentLut.size() - routeds) << " remains." << endl; + cout << " - Wire Length Completion Ratio := " + << setprecision(4) << wireLengthRatio + << "% [" << totalWireLength << "] " + << (totalWireLength - routedWireLength) << " remains." << endl; + + if ( _minimumWL != 0.0 ) { + float expandRatio = totalWireLength / _minimumWL; + cout << " - Wire Length Expand Ratio := " + << setprecision(4) << expandRatio + << "% [min:" << setprecision(9) << _minimumWL << "] " + << endl; + } + + _toolSuccess = (unrouteds == 0); + } + + + bool KiteEngine::_check ( unsigned int& overlap, const char* message ) const + { + cmess1 << " o Checking Kite Database coherency." << endl; + + bool coherency = true; + coherency = coherency && KatabaticEngine::_check ( message ); + for ( size_t i=0 ; i<_routingPlanes.size() ; i++ ) + coherency = _routingPlanes[i]->_check(overlap) && coherency; + + Katabatic::Session* ktbtSession = Session::base (); + forEach ( Net*, inet, getCell()->getNets() ) { + forEach ( Segment*, isegment, inet->getComponents().getSubSet() ) { + AutoSegment* autoSegment = ktbtSession->lookup ( *isegment ); + if ( !autoSegment ) continue; + if ( !autoSegment->isCanonical() ) continue; + + TrackElement* trackSegment = Session::lookup ( *isegment ); + if ( !trackSegment ) { + coherency = false; + cerr << Bug("%p %s whithout Track Segment" + ,autoSegment + ,getString(autoSegment).c_str() + ) << endl; + } else + trackSegment->_check (); + } + } + +#if defined(CHECK_DATABASE) + //Session::getKiteEngine()->setInterrupt ( !coherency ); +#endif + + return coherency; + } + + + void KiteEngine::finalizeLayout () + { + ltrace(90) << "KiteEngine::finalizeLayout()" << endl; + if ( getState() > Katabatic::StateDriving ) return; + + ltracein(90); + + setState ( Katabatic::StateDriving ); + _gutKite (); + + KatabaticEngine::finalizeLayout (); + ltrace(90) << "State: " << getState() << endl; + + ltraceout(90); + } + + + void KiteEngine::_gutKite () + { + ltrace(90) << "KiteEngine::_gutKite()" << endl; + ltracein(90); + ltrace(90) << "State: " << getState() << endl; + + if ( getState() < Katabatic::StateGutted ) { + Session::open ( this ); + + size_t maxDepth = getRoutingGauge()->getDepth(); + for ( size_t depth=0 ; depth < maxDepth ; depth++ ) { + _routingPlanes[depth]->destroy (); + } + + _kiteGrid->destroy (); + _kiteGrid = NULL; + Session::close (); + } + + ltraceout(90); + } + + + TrackElement* KiteEngine::_lookup ( Segment* segment ) const + { + TrackElementLut::const_iterator it = _trackSegmentLut.find ( segment ); + if ( it == _trackSegmentLut.end() ) { + AutoSegment* autoSegment = KatabaticEngine::_lookup ( segment ); + if ( not autoSegment or autoSegment->isCanonical() ) return NULL; + + Interval dummy; + autoSegment = autoSegment->getCanonical ( dummy ); + it = _trackSegmentLut.find ( autoSegment->base() ); + + if ( it == _trackSegmentLut.end() ) return NULL; + } + return (*it).second; + } + + + void KiteEngine::_link ( TrackElement* trackSegment ) + { + if ( getState() > Katabatic::StateActive ) return; + + if ( !trackSegment ) { + cerr << Bug("KiteEngine::_link(): Rejecting NULL TrackElement.") << endl; + return; + } + + _trackSegmentLut [ trackSegment->base()->base() ] = trackSegment; + // Not needed: Canonical search is done before lookup. +// forEach ( AutoSegment*, isegment, trackSegment->base()->getCollapseds() ) { +// _trackSegmentLut [ isegment->base() ] = trackSegment; +// } + } + + + void KiteEngine::_unlink ( TrackElement* trackSegment ) + { + if ( getState() > Katabatic::StateActive ) return; + + TrackElementLut::iterator it = _trackSegmentLut.find ( trackSegment->base()->base() ); + if ( it != _trackSegmentLut.end() ) + _trackSegmentLut.erase ( it ); + + // Not needed: Canonical search is done before lookup. +// forEach ( AutoSegment*, isegment, trackSegment->base()->getCollapseds() ) { +// TrackElementLut::iterator it = _trackSegmentLut.find ( isegment->base() ); +// if ( it != _trackSegmentLut.end() ) +// _trackSegmentLut.erase ( it ); +// } + } + + + void KiteEngine::_check ( Net* net ) const + { + cerr << " o Checking " << net << endl; + + forEach ( Segment*, isegment, net->getComponents().getSubSet() ) { + TrackElement* trackSegment = _lookup ( *isegment ); + if ( trackSegment ) { + trackSegment->_check (); + + AutoContact* autoContact = trackSegment->base()->getAutoSource(); + if ( autoContact ) autoContact->checkTopology (); + + autoContact = trackSegment->base()->getAutoTarget(); + if ( autoContact ) autoContact->checkTopology (); + } + } + } + + + string KiteEngine::_getTypeName () const + { return "Kite::KiteEngine"; } + + + string KiteEngine::_getString () const + { + ostringstream os; + + os << "<" << "KiteEngine " + << _cell->getName () << " " + // << getString(_rg->getName()) + << ">"; + + return os.str(); + } + + + Record* KiteEngine::_getRecord () const + { + Record* record = KatabaticEngine::_getRecord (); + + record->add ( getSlot ( "_routingPlanes", &_routingPlanes ) ); + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/KiteMain.cpp b/kite/src/KiteMain.cpp new file mode 100644 index 00000000..3ee7f77f --- /dev/null +++ b/kite/src/KiteMain.cpp @@ -0,0 +1,218 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./KiteMain.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +using namespace std; + +#include +namespace poptions = boost::program_options; + +#include "hurricane/DebugSession.h" +#include "hurricane/DataBase.h" +#include "hurricane/Cell.h" +#include "hurricane/Warning.h" +#include "hurricane/UpdateSession.h" +#include "hurricane/viewer/HApplication.h" +#include "hurricane/viewer/Graphics.h" +using namespace Hurricane; + +#include "crlcore/Utilities.h" +#include "crlcore/AllianceFramework.h" +#include "crlcore/Hierarchy.h" +#include "crlcore/ToolBox.h" +using namespace CRL; + +#include "knik/KnikEngine.h" +using namespace Knik; + +#include "kite/KiteEngine.h" +using namespace Kite; + + +namespace { + + +// ------------------------------------------------------------------- +// Function : "printHelp()". + + void printHelp () + { + cout << endl; + cout << "Usage: kite [-v|--verbose] [-V|--very-verbose] [-D|--core-dump] \\\n" + << " [-l|--trace-level ] [-c|--cell ] \\\n" + << endl; + cout << "Options:\n" + << " o [-v|--verbose] : First level of verbosity.\n" + << " o [-V|--very-verbose] : Second level of verbosity (very talkative).\n" + << " o [-D|--core-dump] : Enable core dumping.\n" + << " o [-l|--trace-level ] :\n" + << " Sets the level of trace, trace messages with a level superior to\n" + << " will be printed on .\n" + << " o [-c|--cell ] :\n" + << " The name of the Cell to load, without extention.\n" + << endl; + } + + +} // End of anonymous namespace. + + + + +// x-----------------------------------------------------------------x +// | Fonctions Definitions | +// x-----------------------------------------------------------------x + + +// ------------------------------------------------------------------- +// Function : "main()". + +int main ( int argc, char *argv[] ) +{ + int returnCode = 0; + bool kiteSuccess = false; + + try { + float edgeCapacity; + unsigned int traceLevel; + bool verbose1; + bool verbose2; + bool info; + bool coreDump; + bool logMode; + bool loadGlobal; + bool saveDesign; + + poptions::options_description options ("Command line arguments & options"); + options.add_options() + ( "help,h" , "Print this help." ) + ( "verbose,v" , poptions::bool_switch(&verbose1)->default_value(false) + , "First level of verbosity.") + ( "very-verbose,V", poptions::bool_switch(&verbose2)->default_value(false) + , "Second level of verbosity.") + ( "info,i" , poptions::bool_switch(&info)->default_value(false) + , "Lots of informational messages.") + ( "core-dump,D" , poptions::bool_switch(&coreDump)->default_value(false) + , "Enable core dumping.") + ( "log-mode,L" , poptions::bool_switch(&logMode)->default_value(false) + , "Disable ANSI escape sequences displaying.") + ( "global,g" , poptions::bool_switch(&loadGlobal)->default_value(false) + , "Reload the global routing from disk.") + ( "trace-level,l" , poptions::value(&traceLevel)->default_value(1000) + , "Set the level of trace, trace messages with a level superior to " + " will be printed on ." ) + ( "edge,e" , poptions::value(&edgeCapacity)->default_value(65.0) + , "The egde density ratio applied on global router's edges." ) + ( "cell,c" , poptions::value() + , "The name of the cell to load, whithout extension." ) + ( "save,s" , poptions::bool_switch(&saveDesign)->default_value(false) + , "Save the routed design."); + + poptions::variables_map arguments; + poptions::store ( poptions::parse_command_line(argc,argv,options), arguments ); + poptions::notify ( arguments ); + + if ( arguments.count("help") or not arguments.count("cell") ) { + cout << options << endl; + exit ( 0 ); + } + + System::getSystem()->setCatchCore ( not coreDump ); + + if ( verbose1 ) mstream::enable ( mstream::VerboseLevel1 ); + if ( verbose2 ) mstream::enable ( mstream::VerboseLevel2 ); + if ( info ) mstream::enable ( mstream::Info ); + if ( logMode ) tty::disable (); + + ltracelevel ( traceLevel ); + + dbo_ptr db ( DataBase::create() ); + dbo_ptr af ( AllianceFramework::create() ); + Cell* cell = NULL; + + if ( arguments.count("cell") ) { + cell = af->getCell (arguments["cell"].as().c_str(), Catalog::State::Views ); + if (!cell) { + cerr << af->getPrint() << endl; + cerr << "[ERROR] Cell not found: " << arguments["cell"].as() << endl; + exit ( 2 ); + } + } + + //KnikEngine::setEdgeCapacityPercent ( edgeCapacity ); + Kite::Configuration::setDefaultEdgeCapacity ( edgeCapacity ); + + cell->flattenNets ( not arguments.count("global") ); + + KnikEngine* knik = KnikEngine::create ( cell ); + if ( not loadGlobal ) { + knik->run (); + } else { + knik->createRoutingGraph (); + knik->loadSolution (); + } + + static vector routingNets; + KiteEngine* kite = KiteEngine::create ( af->getRoutingGauge(), cell ); + // kite->setSaturateRatio ( 0.85 ); + // kite->setExpandStep ( 0.20 ); + // kite->setRipupCost ( 3 ); + // kite->setRipupLimit ( 25, Configuration::BorderRipupLimit ); + // kite->setRipupLimit ( 15, Configuration::StrapRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::LocalRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::GlobalRipupLimit ); + // kite->setRipupLimit ( 5, Configuration::LongGlobalRipupLimit ); + kite->runGlobalRouter ( Kite::LoadGlobalSolution ); + kite->loadGlobalRouting ( Katabatic::LoadGrByNet, routingNets ); + kite->layerAssign ( Katabatic::NoNetLayerAssign ); + kite->runNegociate (); + kiteSuccess = kite->getToolSuccess (); + kite->finalizeLayout (); + kite->destroy (); + knik->destroy (); + + if ( saveDesign ) { + string name = getString(cell->getName()) + "_kite"; + cell->setName ( name ); + af->saveCell ( cell, Catalog::State::Physical ); + } + + returnCode = (kiteSuccess) ? 0 : 1; + } + catch ( poptions::error& e ) { + cerr << "[ERROR] " << e.what() << endl; + exit ( 1 ); + } + catch ( Error& e ) { + cerr << e.what() << endl; + exit ( 1 ); + } + catch ( ... ) { + cout << "[ERROR] Abnormal termination: unmanaged exception.\n" << endl; + exit ( 2 ); + } + + return returnCode; +} diff --git a/kite/src/NegociateWindow.cpp b/kite/src/NegociateWindow.cpp new file mode 100644 index 00000000..363070a7 --- /dev/null +++ b/kite/src/NegociateWindow.cpp @@ -0,0 +1,560 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./NegociateWindow.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Net.h" +#include "hurricane/Cell.h" +#include "crlcore/AllianceFramework.h" + +#include "kite/DataNegociate.h" +#include "kite/TrackElement.h" +#include "kite/TrackMarker.h" +#include "kite/TrackCost.h" +#include "kite/Track.h" +#include "kite/RoutingPlane.h" +#include "kite/GCellGrid.h" +#include "kite/GCellRoutingSet.h" +#include "kite/RoutingEventQueue.h" +#include "kite/RoutingEventHistory.h" +#include "kite/NegociateWindow.h" +#include "kite/KiteEngine.h" + + +namespace { + + + using namespace std; + using namespace Hurricane; + using namespace CRL; + using namespace Kite; + + + void NegociateOverlapCost ( const TrackElement* segment, TrackCost& cost ) + { + Interval intersect = segment->getCanonicalInterval(); + + if ( not intersect.intersect ( cost.getInterval() ) ) return; + + if ( segment->isBlockage() ) { + //ltrace(200) << "Infinite cost from: " << segment << endl; + cost.setInfinite (); + cost.setOverlap (); + cost.setHardOverlap (); + cost.setBlockage (); + return; + } + + if ( cost.getInterval().getVMax() > intersect.getVMax() ) cost.setLeftOverlap(); + if ( cost.getInterval().getVMin() < intersect.getVMin() ) cost.setRightOverlap(); + + if ( not intersect.contains(cost.getInterval()) ) + intersect.intersection ( cost.getInterval() ); + + DataNegociate* data = segment->getDataNegociate (); + if ( not data ) return; + + if ( data->getGCellOrder() >= Session::getOrder() ) { + cost.mergeRipupCount ( data->getRipupCount() ); + if ( segment->isLocal() ) { + cost.mergeDataState ( data->getState() ); + if ( data->getState() >= DataNegociate::LocalVsGlobal ) { + ltrace(200) << "MaximumSlack/LocalVsGlobal for " << segment << endl; + } + } + } + + if ( /*(data->getGCellOrder() < Session::getOrder()) ||*/ segment->isFixed() ) { + ltrace(200) << "Infinite cost from: " << segment << endl; + cost.setFixed (); + cost.setInfinite (); + cost.setOverlap (); + cost.setHardOverlap (); + return; + } + + if ( ( data->getGCellOrder() < Session::getOrder() ) + or ( ( data->getCost().getRightMinExtend() >= cost.getInterval().getVMin() ) + and ( data->getCost().getLeftMinExtend () <= cost.getInterval().getVMax() ) ) ) + cost.setHardOverlap (); + + cost.setOverlap (); + cost.incTerminals ( data->getCost().getTerminals()*100 ); + cost.incDelta ( intersect.getSize() ); + } + + + void loadRoutingPads ( NegociateWindow* nw ) + { + AllianceFramework* af = AllianceFramework::get (); + RoutingGauge* rg = nw->getKiteEngine()->getRoutingGauge(); + + forEach ( Net*, inet, nw->getCell()->getNets() ) { + if ( inet->getType() == Net::Type::POWER ) continue; + if ( inet->getType() == Net::Type::GROUND ) continue; + if ( inet->getType() == Net::Type::CLOCK ) continue; + if ( af->isOBSTACLE(inet->getName()) ) continue; + + forEach ( RoutingPad*, irp, inet->getRoutingPads() ) { + size_t depth = rg->getLayerDepth(irp->getLayer()); + if ( depth > 0 ) continue; + if ( depth == 0 ) { + TrackMarker::create ( *irp, 1 ); + } + } + } + } + + +} // End of local namespace. + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::setw; + using std::left; + using std::right; + using std::setprecision; + using Hurricane::Bug; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::ForEachIterator; + + +// ------------------------------------------------------------------- +// Class : "NegociateWindow::RingSegment". + + + bool NegociateWindow::RingSegment::orderReached ( const NegociateWindow::RingSegment& segment ) + { + return ( segment.getOrder() <= Session::getOrder() ); + } + + + + NegociateWindow::RingSegment::RingSegment ( TrackElement* segment ) + : _segment(segment), _order(0) + { + DataNegociate* data = segment->getDataNegociate (); + if ( data ) _order = data->getGCellOrder (); + } + + +// ------------------------------------------------------------------- +// Class : "NegociateWindow". + + + NegociateWindow::NegociateWindow ( KiteEngine* kite + , unsigned int columnMin + , unsigned int rowMin + , unsigned int columnMax + , unsigned int rowMax + ) + : _slowMotion (0) + , _interrupt (false) + , _kite (kite) + , _gridBox (NULL) + , _criticalGCells () + , _gcellOrder (0) + , _gcellRoutingSets() + , _eventQueue () + , _eventHistory () + , _ring () + { + _gridBox = GridBox::create ( _kite->getGCellGrid() + , columnMin + , rowMin + , columnMax + , rowMax + ); + } + + + NegociateWindow* NegociateWindow::create ( KiteEngine* kite + , unsigned int columnMin + , unsigned int rowMin + , unsigned int columnMax + , unsigned int rowMax + ) + { + NegociateWindow* negociateWindow = new NegociateWindow ( kite + , columnMin + , rowMin + , columnMax + , rowMax + ); + return negociateWindow; + } + + + NegociateWindow::~NegociateWindow () + { + for ( size_t i=0 ; i<_gcellRoutingSets.size() ; i++ ) + _gcellRoutingSets[i]->destroy (); + + if ( _gridBox ) delete _gridBox; + } + + + void NegociateWindow::destroy () + { delete this; } + + + Cell* NegociateWindow::getCell () const + { return _kite->getCell(); } + + + void NegociateWindow::addToRing ( TrackElement* segment ) + { + ltrace(200) << "addToRing: " << segment << endl; + + _ring.push_back ( RingSegment(segment) ); + + DataNegociate* data = segment->getDataNegociate (); + data->setRing ( true ); + data->setGCellOrder ( Session::getOrder() ); + + _eventQueue.add ( segment, 0 ); + } + + + void NegociateWindow::loadRouting () + { + vector gcells; + GCellGrid* grid = getKiteEngine()->getGCellGrid(); + + forEach ( GCell*, igcell, grid->getGCells() ) { + gcells.push_back ( *igcell ); + igcell->updateDensity (); + } + + sort ( gcells.begin(), gcells.end(), GCell::CompareByDensity() ); + +#if defined(CHECK_DETERMINISM) + cerr << "Order: After sort<>" << endl; + for ( size_t i=0 ; i < gcells.size() ; i++ ) { + cerr << "Order: " + << setw(9) << left << setprecision(6) << gcells[i]->base()->getDensity() + << setw(5) << right << gcells[i]->getIndex() + << " " << gcells[i] << endl; + } +#endif + + unsigned int order = 0; + for ( size_t i=0 ; i < gcells.size() ; i++ ) { + if ( !gcells[i]->isInRoutingSet() ) { + Session::setOrder ( order ); + GCellRoutingSet* rs = GCellRoutingSet::create ( gcells[i], _kite->getExpandStep() ); + rs->expand ( grid ); + rs->loadRouting ( order ); + + _gcellRoutingSets.push_back ( rs ); + } + } + + loadRoutingPads ( this ); + Session::revalidate (); + + TrackElement* segment; + TrackElementLut lut = Session::getKiteEngine()->_getTrackElementLut(); + TrackElementLut::iterator it = lut.begin (); + for ( ; it != lut.end() ; it++ ) { + segment = it->second; + segment->getDataNegociate()->update(); + } + + getKiteEngine()->setMinimumWL ( grid->getTotalWireLength() ); + +#if defined(CHECK_DATABASE) + unsigned int overlaps = 0; + Session::getKiteEngine()->_check(overlaps,"after LoadRouting"); +#endif + } + + + void NegociateWindow::addInsertEvent ( TrackElement* segment, unsigned int level ) + { + DataNegociate* data = segment->getDataNegociate(); + if ( not data or not data->hasRoutingEvent() ) + _eventQueue.add ( segment, level ); + else + cerr << Bug("NegociateWidow::addInsertEvent(): Try to adds twice the same TrackElement event." + "\n %p:%s." + ,(void*)segment->base()->base() + ,getString(segment).c_str() + ) << endl; + } + + + void NegociateWindow::_unloadRing () + { + _ring.erase ( remove_if(_ring.begin(),_ring.end(),RingSegment::orderReached), _ring.end() ); + for ( size_t i=0 ; i<_ring.size() ; ++i ) { + if ( _ring[i].getSegment()->getTrack() != NULL ) + Session::addRemoveEvent ( _ring[i].getSegment() ); + } + + Session::revalidate (); + } + + + void NegociateWindow::_loadRing () + { + unsigned int order = Session::getOrder (); + for ( size_t i=0 ; i<_ring.size() ; i++ ) { + TrackElement* segment = _ring[i].getSegment(); + DataNegociate* data = segment->getDataNegociate (); + + data->resetRipupCount (); + data->setGCellOrder ( order ); + if ( _ring[i].getOrder() == order ) { + ltrace(200) << "Removing from ring: " << segment << endl; + data->setRing ( false ); + } + + _eventQueue.add ( segment, 0 ); + } + _eventQueue.commit (); + } + + + size_t NegociateWindow::_negociate ( const vector& segments ) + { + ltrace(150) << "NegociateWindow::_negociate() - " << segments.size() << endl; + ltracein(149); + + _eventHistory.clear(); + _eventQueue.load ( segments ); + _loadRing (); + + size_t count = 0; + while ( not _eventQueue.empty() and not isInterrupted() ) { + RoutingEvent* event = _eventQueue.pop (); + + event->process ( _eventQueue, _eventHistory ); + if (tty::enabled()) { + cmess1 << " " << tty::cr; + cmess1.flush (); + } else { + cmess2 << " " + << event->getSegment()->getNet()->getName() + << endl; + cmess2.flush(); + } + + if ( RoutingEvent::getProcesseds() >= /*10471*/ 1000000 ) setInterrupt ( true ); + count++; + +#if ENABLE_STIFFNESS + if ( not (RoutingEvent::getProcesseds() % 1000) ) { + sort ( _criticalGCells.begin(), _criticalGCells.end(), GCell::CompareByStiffness() ); + for ( size_t igcell=0 ; igcell<_criticalGCells.size() ; ++igcell ) { + if ( _criticalGCells[igcell]->getStiffness () < 0.7 ) break; + if ( _criticalGCells[igcell]->getSegmentCount() < 20 ) continue; + + cerr << " - Anticipate: " << _criticalGCells[igcell] + << ":" << _criticalGCells[igcell]->getStiffness() << endl; + + _criticalGCells[igcell]->anticipateRouting ( Session::getOrder() ); + _eventQueue.load ( _criticalGCells[igcell]->getOwnedSegments() ); + _criticalGCells[igcell]->setRouted ( true ); + } + } +#endif + } + if (count and tty::enabled()) cmess1 << endl; + count = 0; + + ltrace(200) << "Dumping history." << endl; + for ( size_t i=0 ; (i<_eventHistory.size()) && !isInterrupted() ; i++ ) { + RoutingEvent* event = _eventHistory.getNth(i); + ltrace(200) << (void*)event << " [" + << (event->isCloned ()?"C":"-") + << (event->isDisabled ()?"d":"-") + << (event->isUnimplemented()?"u":"-") << "] " + << event->getSegment() << endl; + if ( !event->isCloned() and event->isUnimplemented() ) { + count++; + event->setProcessed ( false ); + event->setMode ( RoutingEvent::PostPack ); + event->process ( _eventQueue, _eventHistory ); + + if (tty::enabled()) { + cmess1 << " " << tty::cr; + cmess1.flush (); + } else { + cmess1 << " " << endl; + } + } + } + if (count and tty::enabled()) cmess1 << endl; + + size_t eventsCount = _eventHistory.size(); + + _unloadRing (); + _eventHistory.clear(); + _eventQueue.clear(); + + if ( RoutingEvent::getAllocateds() > 0 ) { + cerr << Bug("%d events remains after clear.",RoutingEvent::getAllocateds()) << endl; + } + + // if ( _slowMotion && getCellWidget() ) { + // Session::close (); + // getCellWidget()->refresh(); + // Session::open ( _kiteEngine ); + // } + + ltraceout(149); + + return eventsCount; + } + + + void NegociateWindow::_runOnGCellRoutingSet ( GCellRoutingSet* rs ) + { +#if defined(CHECK_DETERMINISM) + cerr << "Order: Routing set: " << rs << endl; +#endif + + ltrace(200) << "Routing " << rs << endl; + ltracein(200); + + cmess1 << " - Routing " << rs << endl; + + vector gcells = rs->getGCells (); + for ( size_t i=0 ; igetOrder() ); + + vector segments; + rs->loadBorder ( getKiteEngine()->getGCellGrid() ); + rs->getOwnedSegments ( segments ); + rs->setRouted ( true ); + rs->getStatistics ().setEventsCount ( _negociate(segments) ); + rs->freeBorder (); + + ltraceout(200); + } + + + void NegociateWindow::run ( int slowMotion ) + { + ltrace(150) << "NegociateWindow::run()" << endl; + ltracein(149); + + _criticalGCells = *(getKiteEngine()->getGCellGrid()->getGCellVector()); + + TrackElement::setOverlapCostCB ( NegociateOverlapCost ); + RoutingEvent::resetProcesseds (); + + // sort ( gcells.begin(), gcells.end(), GCell::CompareByStiffness() ); + // for ( size_t j=0 ; jgetStiffness() << endl; + // } + + _slowMotion = slowMotion; + _gcellOrder = 0; + for ( size_t i=0 ; (i<_gcellRoutingSets.size()) && !isInterrupted() ; i++ ) { + _runOnGCellRoutingSet ( _gcellRoutingSets[i] ); + + // sort ( gcells.begin(), gcells.end(), GCell::CompareByStiffness() ); + // for ( size_t j=0 ; jgetStiffness() << endl; + // } + } + + Session::get()->isEmpty(); + +# if defined(CHECK_DATABASE) + unsigned int overlaps = 0; + _kite->_check ( overlaps, "after negociation" ); +# endif + + ltraceout(149); + } + + + void NegociateWindow::printStatistics () const + { + cout << " o Computing statistics." << endl; + + Statistics globalStatistics; + size_t biggestEventsCount = 0; + size_t biggestRSsize = 0; + for ( size_t i=0; i<_gcellRoutingSets.size() ; i++ ) { + Statistics& statistics = _gcellRoutingSets[i]->getStatistics(); + globalStatistics += statistics; + + if ( statistics.getEventsCount() > biggestEventsCount ) + biggestEventsCount = statistics.getEventsCount(); + + if ( _gcellRoutingSets[i]->getGCells().size() > biggestRSsize ) + biggestRSsize = _gcellRoutingSets[i]->getGCells().size(); + } + + cout << " - Processeds Events Total := " << RoutingEvent::getProcesseds() << endl; + cout << " - Unique Events Total := " << (RoutingEvent::getProcesseds() - RoutingEvent::getCloneds()) << endl; + cout << " - Biggest Events Chunk := " << biggestEventsCount << endl; + cout << " - Biggest Routing Set := " << biggestRSsize << endl; + } + + + string NegociateWindow::_getString () const + { + ostringstream os; + + os << "<" << _getTypeName() << _gridBox << ">"; + return ( os.str() ); + } + + + Record* NegociateWindow::_getRecord () const + { + Record* record = new Record ( _getString() ); + + record->add ( getSlot ( "_gridBox" , _gridBox ) ); + return ( record ); + } + + +} // End of Kite namespace. diff --git a/kite/src/PreProcess.cpp b/kite/src/PreProcess.cpp new file mode 100644 index 00000000..23ac36c6 --- /dev/null +++ b/kite/src/PreProcess.cpp @@ -0,0 +1,319 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./PreProcess.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/RoutingPad.h" +#include "katabatic/AutoContact.h" +#include "kite/GCell.h" +#include "kite/DataNegociate.h" +#include "kite/TrackElement.h" +#include "kite/Track.h" +#include "kite/RoutingPlane.h" +#include "kite/Session.h" +#include "kite/KiteEngine.h" + + + +namespace { + + + using namespace std; + using namespace Hurricane; + using namespace CRL; + using namespace Kite; + + + void getPerpandiculars ( TrackElement* segment + , AutoContact* from + , unsigned int direction + , vector& perpandiculars + ) + { + //AutoContact* to = segment->base()->getAutoSource(); + //to = (to != from) ? to : segment->base()->getAutoTarget(); + + TrackElement* perpandicular; + forEach ( Segment*, isegment, segment->base()->getAutoSource()->getSlaveComponents().getSubSet() ) { + perpandicular = Session::lookup ( *isegment ); + ltrace(200) << "S " << perpandicular << endl; + + if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue; + + perpandiculars.push_back ( perpandicular ); + } + + forEach ( Segment*, isegment, segment->base()->getAutoTarget()->getSlaveComponents().getSubSet() ) { + perpandicular = Session::lookup ( *isegment ); + ltrace(200) << "T " << perpandicular << endl; + + if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue; + + perpandiculars.push_back ( perpandicular ); + } + } + + + void propagateCagedConstraints ( TrackElement* segment ) + { + if ( not segment->isFixed() ) return; + + ltrace(200) << "Propagate caging: " << segment << endl; + + Track* track = segment->getTrack(); + unsigned int direction = Session::getRoutingGauge()->getLayerDirection(segment->getLayer()); + AutoContact* source = segment->base()->getAutoSource(); + Interval uside = source->getGCell()->getUSide(direction); + DbU::Unit minConstraint = DbU::Min; + DbU::Unit maxConstraint = DbU::Max; + vector perpandiculars; + + if ( not track ) { + cerr << Bug("%s is not inserted in a ",getString(segment).c_str()) << endl; + return; + } + + // Computing constraints from fixed only TrackElements (caging). + TrackElement* parallel; + size_t i = segment->getIndex(); + while ( i > 0 ) { + parallel = track->getSegment(--i); + if ( not parallel ) continue; + if ( parallel->getTargetU() < uside.getVMin() ) break; + if ( parallel->getNet() == segment->getNet() ) continue; + if ( not parallel->isFixed() ) continue; + + ltrace(200) << "Min Constraint from: " << parallel << endl; + minConstraint = max ( minConstraint, parallel->getTargetU() ); + } + + i = segment->getIndex(); + while ( i < track->getSize()-1 ) { + parallel = track->getSegment(++i); + if ( not parallel ) continue; + if ( parallel->getSourceU() > uside.getVMax() ) break; + if ( parallel->getNet() == segment->getNet() ) continue; + if ( not parallel->isFixed() ) continue; + + ltrace(200) << "Max Constraint from: " << parallel << endl; + maxConstraint = min ( maxConstraint, parallel->getSourceU() ); + } + + if ( minConstraint > maxConstraint ) { + cerr << Bug("%s have too tight caging constraints.",getString(segment).c_str()) << endl; + return; + } + if ( (minConstraint <= uside.getVMin()) and (maxConstraint >= uside.getVMax()) ) { + ltrace(200) << "No constraints [" << DbU::getValueString(minConstraint) + << ":" << DbU::getValueString(maxConstraint) + << " vs. " << uside << endl; + return; + } + + // Finding perpandiculars, by way of the source & target RoutingPad. + if ( source->getAnchor() ) { + RoutingPad* rp = dynamic_cast(source->getAnchor()); + if ( rp ) { + TrackElement* parallel; + forEach ( Segment*, isegment, rp->getSlaveComponents().getSubSet() ) { + parallel = Session::lookup ( *isegment ); + ltrace(200) << "* " << parallel << endl; + + if ( parallel->isFixed () ) continue; + if ( parallel->isGlobal() ) continue; + getPerpandiculars ( parallel, source, direction, perpandiculars ); + getPerpandiculars ( parallel, segment->base()->getAutoTarget(), direction, perpandiculars ); + } + } else { + cerr << Bug("%s is not anchored on a \n (%s)" + ,getString(source).c_str() + ,getString(source->getAnchor()).c_str()) << endl; + } + } + + // Apply caging constraints to perpandiculars. + ltracein(200); + if ( perpandiculars.size() == 0 ) { + ltrace(200) << "No perpandiculars to " << segment << endl; + } + + Interval constraints ( minConstraint, maxConstraint ); + for ( size_t iperpand=0 ; iperpandbase()->mergeUserConstraints ( constraints ); + } + ltraceout(200); + } + + + void freeCagedTerminals ( Track* track ) + { + Configuration* configuration = Session::getConfiguration (); + const Layer* metal2 = configuration->getRoutingLayer ( 1 ); + const Layer* metal3 = configuration->getRoutingLayer ( 2 ); + + for ( size_t i=0 ; igetSize() ; i++ ) { + TrackElement* segment = track->getSegment ( i ); + if ( segment and segment->isFixed() and segment->isTerminal() ) { + Interval freeInterval = track->getFreeInterval ( segment->getSourceU(), segment->getNet() ); + + if ( freeInterval.getSize() < DbU::lambda(30.0) ) { + cinfo << "Caged terminal: " << segment << endl; + if ( segment->getLayer() != metal2 ) continue; + if ( segment->getLength() >= DbU::lambda(5.0) ) continue; + + AutoContact* support = segment->base()->getAutoSource(); + RoutingPad* rp = dynamic_cast(support->getAnchor()); + GCell* gcell = Session::lookup ( support->getGCell() ); + +#if 0 + Point point ( segment->base()->getSourceU(), track->getAxis() ); + GCell* gcell = Session::lookup ( segment->base()->getAutoSource()->getGCell() ); + AutoContact* source = AutoContact::create ( gcell->base(), segment->getNet(), metal3 ); + AutoContact* target = AutoContact::create ( gcell->base(), segment->getNet(), metal3 ); + source->setPosition ( point ); + target->setPosition ( point ); +#endif + + AutoContact* source = AutoContact::fromRp ( gcell->base() + , rp + , metal3 + , rp->getSourcePosition() + , DbU::lambda(1.0), DbU::lambda(1.0) + , true + ); + + AutoContact* target = AutoContact::fromRp ( gcell->base() + , rp + , metal3 + , rp->getSourcePosition() + , DbU::lambda(1.0), DbU::lambda(1.0) + , true + ); + + AutoSegment* segment = AutoSegment::create ( source + , target + , Constant::Vertical + , AutoSegment::Local + , true + , false + ); + segment->setFixed ( true ); + GCell::addTrackSegment ( gcell, segment, true ); + +#if DISABLED + // Force slackening. + bool breakFlag = false; + forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet() ) { + forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet() ) { + TrackElement* trackSegment = Session::lookup(*isegment); + if ( not trackSegment or trackSegment->isFixed() ) continue; + + if ( trackSegment->isHorizontal() ) { + ltrace(200) << "M2 to slacken for " << rp << endl; + breakFlag = true; + + const vector& dogLegs = Session::getDogLegs(); + + trackSegment->base()->makeDogLeg ( gcell->base(), true ); + GCell::addTrackSegment ( gcell, dogLegs[1], true ); + GCell::addTrackSegment ( gcell, dogLegs[2], true ); + Session::revalidate (); + } + + if ( breakFlag ) break; + } + if ( breakFlag ) break; + } +#endif + } + } + } + } + + +} // End of local namespace. + + +namespace Kite { + + + using Hurricane::Bug; + using Hurricane::Net; + using Hurricane::Name; + + + void KiteEngine::preProcess () + { + for ( size_t i=0 ; i<_routingPlanes.size() ; i++ ) { + RoutingPlane* plane = _routingPlanes[i]; + + Track* track = plane->getTrackByIndex ( 0 ); + while ( track ) { + freeCagedTerminals ( track ); + track = track->getNext (); + } + } + Session::revalidate (); + } + + + void KiteEngine::_computeCagedConstraints () + { + TrackElementLut::iterator isegment = _trackSegmentLut.begin(); + for ( ; isegment != _trackSegmentLut.end() ; isegment++ ) { + if ( not isegment->second->isFixed() ) continue; + propagateCagedConstraints ( isegment->second ); + } + } + + + void KiteEngine::_computeCagedConstraints ( Net* net ) + { + TrackElement* segment = NULL; + + forEach ( Segment*, isegment, net->getComponents().getSubSet() ) { + segment = Session::lookup ( *isegment ); + if ( not segment ) continue; + + segment->base()->resetUserConstraints(); + } + + forEach ( Segment*, isegment, net->getComponents().getSubSet() ) { + segment = Session::lookup ( *isegment ); + if ( not segment ) continue; + + propagateCagedConstraints ( segment ); + } + } + + +} // End of Kite namespace. diff --git a/kite/src/RoutingEvent.cpp b/kite/src/RoutingEvent.cpp new file mode 100644 index 00000000..93967ac0 --- /dev/null +++ b/kite/src/RoutingEvent.cpp @@ -0,0 +1,3648 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./RoutingEvent.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/DebugSession.h" +#include "hurricane/Net.h" +#include "hurricane/Layer.h" + +#include "katabatic/AutoContact.h" + +#include "kite/DataNegociate.h" +#include "kite/TrackElement.h" +#include "kite/Track.h" +#include "kite/Tracks.h" +#include "kite/GCell.h" +#include "kite/RoutingPlane.h" +#include "kite/RoutingEvent.h" +#include "kite/RoutingEventHistory.h" +#include "kite/RoutingEventQueue.h" +#include "kite/NegociateWindow.h" +#include "kite/Session.h" +#include "kite/KiteEngine.h" + + +namespace { + + /*! \defgroup ClassManipulator Manipulator Class + */ + + //! \addtogroup ClassManipulator + //! \{ + + /*! \class Manipulator + * \brief Handle \TrackElement ripup & topological modifications. + * + * Handles all \TrackElement modifications. + */ + + /*! \function Manipulator::Manipulator ( TrackElement* segment, State& state ); + * \param segment The \TrackElement to manipulate. + * \param state The \RoutingEvent state. + */ + + /*! \function TrackElement* Manipulator::getSegment () const; + * \Return The working \TrackElement. + */ + + /*! \function DataNegociate* Manipulator::getData () const; + * \Return The DataNegociate of the \TrackElement. + */ + + /*! \function RoutingEvent* Manipulator::getEvent () const; + * \Return The \RoutingEvent associated to the \TrackElement. May be + * \NULL if it belongs to a more prioritary GCell RoutingSet. + */ + + /*! \function bool Manipulator::canRipup () const; + * \return \true if the maximum ripup & reset count has not been reached. + */ + + /*! \function bool Manipulator::ripup ( Interval overlap, unsigned int type, DbU::Unit axisHint ); + * \param overlap The Interval that should be cleared. + * \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 cannot be riped up (it cames from a more + * prioritary GCell RoutingSet), then it tries to relax it. + */ + + /*! \function bool Manipulator::ripup ( DbU::Unit point, unsigned int type, DbU::Unit axisHint ); + * \param point The point around which the \Track should be cleared. + * \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. + * + * \see The other ripup method. + */ + + /*! \function bool Manipulator::relax ( Interval overlap ); + * \param overlap The overlaping interval to free. + * \return \true if the operation has succeeded. + * + * Finds the appropriate dogleg GCells to break the \TrackElement. + * There could be one or two breaks whether the overlap is fully + * enclosed or not. + */ + + /*! \function bool Manipulator::modifyTopology (); + * \return \true if the operation has succeeded. + * + * Try to changes the \TrackElement topology. + */ + + /*! \function bool Manipulator::insertInTrack ( size_t i ); + * \param i The index of \Track into which insert. + * \return \true if the operation has succeeded. + * + * Try to insert the \TrackElement into the \Track i. + * The index is relative to the State's \Track vector. + */ + + /*! \function bool Manipulator::desalignate (); + * \return \true if the operation has succeeded. + * + * Try to desalignate the \TrackElement. + */ + + /*! \function bool Manipulator::slacken (); + * \return \true if the operation has succeeded. + * + * Try to slacken the \TrackElement. + */ + + /*! \function bool Manipulator::moveUp (); + * \return \true if the operation has succeeded. + * + * Try to move up the \TrackElement. + */ + + /*! \function bool Manipulator::makeDogLeg (); + * \return \true if the operation has succeeded. + * + * Try to make a dog leg on the \TrackElement. + * This method is restricted to local \TrackElement only. + */ + + /*! \function bool Manipulator::minimize (); + * \return \true if the operation has succeeded. + * + * Try to mimize the wirelength of the \TrackElement. + * This operation can only be done once. + */ + + /*! \function bool Manipulator::relax ( size_t i ); + * \param i The index of the selected \Track. + * \return \true if the operation has succeeded. + * + * Try to make a dog leg on the \TrackElement. + * This method is restricted to local \TrackElement only. + */ + + //! \} + + + using namespace std; + using namespace Hurricane; + using namespace Kite; + + +// ------------------------------------------------------------------- +// Class : "LvGCandidate". + + + class LvGCandidate { + public: + struct Compare : public binary_function { + inline bool operator() ( const LvGCandidate& lhs, const LvGCandidate& rhs ) const; + }; + public: + inline LvGCandidate ( TrackElement* segment=NULL, Interval overlap=Interval(), size_t terminals=0 ); + inline TrackElement* getSegment () const; + inline const Interval& getOverlap () const; + inline size_t getTerminals () const; + private: + TrackElement* _segment; + Interval _overlap; + size_t _terminals; + }; + + inline LvGCandidate::LvGCandidate ( TrackElement* segment, Interval overlap, size_t terminals ) + : _segment (segment) + , _overlap (overlap) + , _terminals(terminals) + { } + + inline TrackElement* LvGCandidate::getSegment () const { return _segment; } + inline const Interval& LvGCandidate::getOverlap () const { return _overlap; } + inline size_t LvGCandidate::getTerminals () const { return _terminals; } + + inline bool LvGCandidate::Compare::operator() ( const LvGCandidate& lhs, const LvGCandidate& rhs ) const + { + if ( lhs.getTerminals() != rhs.getTerminals() ) + return lhs.getTerminals() < rhs.getTerminals(); + + if ( lhs.getOverlap() != rhs.getOverlap() ) + return lhs.getOverlap().getSize() > rhs.getOverlap().getSize(); + + return lhs.getSegment()->getAxis() < rhs.getSegment()->getAxis(); + } + + + +// ------------------------------------------------------------------- +// Class : "Cs1Candidate". + + + class Cs1Candidate { + public: + inline Cs1Candidate ( Track* track=NULL ); + inline Track* getTrack () const; + inline size_t getBegin () const; + inline size_t getEnd () const; + inline size_t getLength () const; + inline Interval getConflict ( size_t ); + inline void setBegin ( size_t ); + inline void setEnd ( size_t ); + inline void addConflict ( const Interval& ); + public: + friend inline bool operator< ( const Cs1Candidate&, const Cs1Candidate& ); + private: + Track* _track; + size_t _begin; + size_t _end; + vector _conflicts; + }; + + + inline Cs1Candidate::Cs1Candidate ( Track* track ) + : _track (track) + , _begin (0) + , _end (0) + , _conflicts() + { } + + inline Track* Cs1Candidate::getTrack () const { return _track; } + inline size_t Cs1Candidate::getBegin () const { return _begin; } + inline size_t Cs1Candidate::getEnd () const { return _end; } + inline size_t Cs1Candidate::getLength () const { return _conflicts.size(); } + inline void Cs1Candidate::setBegin ( size_t i ) { _begin=i; } + inline void Cs1Candidate::setEnd ( size_t i ) { _end=i; } + inline void Cs1Candidate::addConflict ( const Interval& conflict ) { _conflicts.push_back(conflict); } + + inline Interval Cs1Candidate::getConflict ( size_t i ) + { + if (i > _conflicts.size()) return Interval(); + return _conflicts[i]; + } + + inline bool operator< ( const Cs1Candidate& lhs, const Cs1Candidate& rhs ) + { return lhs._conflicts.size() < rhs._conflicts.size(); } + + +// ------------------------------------------------------------------- +// Class : "ShearAnalyze". + + + class ShearAnalyze { + public: + ShearAnalyze ( TrackElement* ); + void addPerpandicular ( DbU::Unit axis, Interval constraint ); + GCell* getShearGCell (); + private: + GCell* _compute (); + private: + TrackElement* _segment; + vector _gcells; + vector _constraints; + GCell* _shearGCell; + bool _computed; + }; + + + ShearAnalyze::ShearAnalyze ( TrackElement* segment ) + : _segment (segment) + , _gcells () + , _constraints() + , _shearGCell (NULL) + , _computed (false) + { + segment->getGCells ( _gcells ); + for ( size_t igcell=0 ; igcell<_gcells.size() ; igcell++ ) { + _constraints.push_back ( Interval() ); + } + } + + + GCell* ShearAnalyze::getShearGCell () + { + if ( not _computed ) _compute (); + return _shearGCell; + } + + + void ShearAnalyze::addPerpandicular ( DbU::Unit axis, Interval constraint ) + { + Interval uside; + for ( size_t igcell=0 ; igcell<_gcells.size() ; igcell++ ) { + uside = _gcells[igcell]->getUSide(_segment->getDirection(),true); + if ( uside.contains(axis) ) { + _constraints[igcell].merge ( constraint ); + } + } + } + + + GCell* ShearAnalyze::_compute () + { + _shearGCell = NULL; + + Interval trunk ( false ); + for ( size_t igcell=0 ; igcell<_gcells.size() ; igcell++ ) { + if ( not _constraints[igcell].isEmpty() ) { + trunk.intersection ( _constraints[igcell] ); + } + } + // Ugly: explicit pitch. + trunk.inflate ( DbU::lambda(5.0) ); + + // 0: intialisation, 1: left constrained, 2: right constrained. + unsigned int previousConstraint = 0; + size_t ishearBegin = 0; + size_t ishearEnd = 0; + for ( size_t igcell=0 ; igcell<_gcells.size() ; igcell++ ) { + if ( _constraints[igcell].isEmpty() ) continue; + + bool leftConstrained = (_constraints[igcell].getVMin() >= trunk.getVMin()); + bool rightConstrained = (_constraints[igcell].getVMax() <= trunk.getVMax()); + + if ( not leftConstrained and not rightConstrained ) continue; + if ( leftConstrained and rightConstrained ) { + ishearBegin = ishearEnd = 0; + break; + } + + if ( not previousConstraint ) { + previousConstraint = (leftConstrained) ? 1 : 2; + continue; + } + + if ( leftConstrained xor (previousConstraint == 1) ) { + if ( not ishearBegin ) { + ishearBegin = igcell; + continue; + } + + ishearBegin = ishearEnd = 0; + break; + } + } + + if ( ishearBegin ) { + if ( _constraints[ishearBegin-1].isEmpty() ) { + _shearGCell = _gcells[ishearBegin-1]; + } + } + + return _shearGCell; + } + + +// ------------------------------------------------------------------- +// Class : "UnionItervals". + + + class UnionIntervals { + public: + inline UnionIntervals (); + void addInterval ( Interval& ); + inline size_t size () const; + inline bool empty () const; + inline list::const_iterator begin () const; + inline list::const_iterator end () const; + inline DbU::Unit getVMin () const; + inline DbU::Unit getVMax () const; + string _getString (); + private: + list _intervals; + }; + + + inline UnionIntervals::UnionIntervals () : _intervals() { } + inline list::const_iterator UnionIntervals::begin () const { return _intervals.begin(); } + inline list::const_iterator UnionIntervals::end () const { return _intervals.end(); } + inline size_t UnionIntervals::size () const { return _intervals.size(); } + inline bool UnionIntervals::empty () const { return _intervals.empty(); } + inline DbU::Unit UnionIntervals::getVMin () const { return (empty()) ? DbU::Max : (*begin()).getVMin(); } + inline DbU::Unit UnionIntervals::getVMax () const { return (empty()) ? DbU::Min : (*begin()).getVMax(); } + + + void UnionIntervals::addInterval ( Interval& interval ) + { + ltrace(200) << "UnionInterval::addInterval() - " << interval << endl; + + list::iterator iintv = _intervals.begin (); + + bool merged = false; + while ( iintv != _intervals.end() ) { + if ( !merged ) { + if ( interval.getVMax() < (*iintv).getVMin() ) { _intervals.insert ( iintv, interval ); return; } + if ( interval.getVMin() > (*iintv).getVMax() ) { iintv++; continue; } + + merged = true; + interval = (*iintv).merge ( interval ); + iintv++; + } else { + if ( (*iintv).intersect ( interval ) ) { + interval = (*iintv).merge ( interval ); + iintv = _intervals.erase ( iintv ); + continue; + } else + break; + } + } + + if ( !merged ) _intervals.push_back ( interval ); + } + + + string UnionIntervals::_getString () + { + ostringstream s; + + list::iterator iintv = _intervals.begin(); + for ( ; iintv != _intervals.end() ; iintv++ ) { + s << " [" << DbU::getValueString((*iintv).getVMin()) + << ":" << DbU::getValueString((*iintv).getVMax()) << "]"; + } + return s.str(); + } + + +// ------------------------------------------------------------------- +// Class : "RipupHistory". + + + class RipupHistory { + public: + RipupHistory ( RoutingEvent* ); + inline bool isDislodger ( RoutingEvent* ) const; + inline size_t size () const; + inline size_t getDislodgersCount () const; + void addAxis ( DbU::Unit ); + void addAxis ( RoutingEvent* ); + bool hasAxis ( DbU::Unit ) const; + UnionIntervals* getUnionIntervals ( DbU::Unit ); + void addDislodger ( RoutingEvent* ); + void addDislodger ( TrackElement* ); + void print ( ostream& ); + private: + RoutingEvent* _masterEvent; + map _dislodgers; + size_t _dislodgersCount; + }; + + + RipupHistory::RipupHistory ( RoutingEvent* event ) + : _masterEvent(event) + , _dislodgers() + , _dislodgersCount(0) + { + const Interval& perpandicular = _masterEvent->getPerpandicular(); + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_masterEvent->getSegment()->getLayer()); + Track* track; + if ( !perpandicular.isEmpty() ) { + track = plane->getTrackByPosition(perpandicular.getVMin()); + + if ( track && (track->getAxis() < perpandicular.getVMin()) ) track = track->getNext(); + for ( ; track && (track->getAxis() <= perpandicular.getVMax()) + ; track = track->getNext() ) + addAxis ( track->getAxis() ); + } + + track = plane->getTrackByPosition(_masterEvent->getSegment()->getAxis()); + if ( track ) { + size_t begin; + size_t end; + Interval interval = _masterEvent->getSegment()->getCanonicalInterval(); + track->getOverlapBounds ( interval, begin, end ); + + if ( begin != Track::NPOS ) { + for ( ; begin < end ; begin++ ) { + TrackElement* other = track->getSegment(begin); + if ( other->getNet() == _masterEvent->getSegment()->getNet() ) continue; + if ( !interval.intersect(other->getCanonicalInterval()) ) continue; + + addDislodger ( other ); + } + } + } + } + + + inline bool RipupHistory::isDislodger ( RoutingEvent* event ) const { return hasAxis(event->getSegment()->getAxis()); } + inline size_t RipupHistory::size () const { return _dislodgers.size(); } + inline size_t RipupHistory::getDislodgersCount () const { return _dislodgersCount; } + + + void RipupHistory::addAxis ( DbU::Unit axis ) + { + if ( hasAxis(axis) ) return; + _dislodgers.insert ( make_pair(axis,UnionIntervals()) ); + } + + + void RipupHistory::addAxis ( RoutingEvent* event ) + { + addAxis ( event->getAxisHistory() ); + } + + + bool RipupHistory::hasAxis ( DbU::Unit axis ) const + { + return _dislodgers.find(axis) != _dislodgers.end(); + } + + + UnionIntervals* RipupHistory::getUnionIntervals ( DbU::Unit axis ) + { + map::iterator iunion = _dislodgers.find ( axis ); + if ( iunion == _dislodgers.end() ) return NULL; + + return &(iunion->second); + } + + + void RipupHistory::addDislodger ( RoutingEvent* event ) + { + if ( event->getSegment() == _masterEvent->getSegment() ) return; + if ( event->getSegment()->getLayer() != _masterEvent->getSegment()->getLayer() ) return; + + UnionIntervals* intervals = getUnionIntervals ( event->getAxisHistory() ); + if ( !intervals ) return; + + Interval canonical = event->getSegment()->getCanonicalInterval(); + intervals->addInterval ( canonical ); + + _dislodgersCount++; + } + + + void RipupHistory::addDislodger ( TrackElement* segment ) + { + if ( _masterEvent->getSegment()->getNet() == segment->getNet() ) return; + + UnionIntervals* intervals = getUnionIntervals ( segment->getAxis() ); + if ( !intervals ) return; + + Interval canonical = segment->getCanonicalInterval(); + intervals->addInterval ( canonical ); + + _dislodgersCount++; + } + + + void RipupHistory::print ( ostream& o ) + { + o << "[HISTORY] " << _masterEvent << endl; + + map::iterator iunion = _dislodgers.begin(); + for ( ; iunion != _dislodgers.end() ; iunion++ ) + o << " @" << DbU::getValueString(iunion->first) + << " " << (iunion->second)._getString() << endl; + } + + +// ------------------------------------------------------------------- +// Class : "::SegmentAction". + + + class SegmentAction { + public: + enum Type { Self = (1<< 0) + , Other = (1<< 1) + , Ripup = (1<< 2) + , Insert = (1<< 3) + , ResetRipup = (1<< 4) + , AxisHint = (1<< 5) + , Perpandicular = (1<< 6) + , EventLevel1 = (1<< 7) + , EventLevel2 = (1<< 8) + , EventLevel3 = (1<< 9) + , EventLevel4 = (1<<10) + , EventLevel5 = (1<<11) + , PackingMode = (1<<12) + , ToState = (1<<13) + , ToRipupLimit = (1<<14) + , SelfInsert = Self |Insert + , SelfRipup = Self |Ripup + , SelfRipupPerpand = Self |Ripup | Perpandicular + , SelfRipupAndReset = Self |Ripup | Perpandicular + , SelfShrinkPerpand = Self |Ripup | Perpandicular|EventLevel4 + , SelfRipupAndAxisHint = Self |Ripup | Perpandicular|EventLevel4| AxisHint + , OtherRipup = Other|Ripup + , OtherPushAside = Other|Ripup | Perpandicular|EventLevel3 + , OtherPacking = Other|Ripup | Perpandicular|PackingMode + }; + public: + SegmentAction ( TrackElement* + , unsigned int type + , DbU::Unit axisHint=0 + , unsigned int toState =0 + ); + inline TrackElement* getSegment () const; + inline unsigned int getType () const; + inline void setAxisHint ( DbU::Unit ); + inline unsigned int setFlag ( unsigned int ); + bool doAction ( RoutingEventQueue& ); + private: + TrackElement* _segment; + unsigned int _type; + DbU::Unit _axisHint; + unsigned int _toState; + }; + + + inline TrackElement* SegmentAction::getSegment () const { return _segment; } + inline unsigned int SegmentAction::getType () const { return _type; } + inline void SegmentAction::setAxisHint ( DbU::Unit axis ) { _axisHint = axis; } + inline unsigned int SegmentAction::setFlag ( unsigned int flag ) { _type |= flag; return _type; } + + + SegmentAction::SegmentAction ( TrackElement* segment + , unsigned int type + , DbU::Unit axisHint + , unsigned int toState + ) + : _segment (segment) + , _type (type) + , _axisHint(axisHint) + , _toState (toState) + { } + + + bool SegmentAction::doAction ( RoutingEventQueue& queue ) + { + // Note: + // "_immediate" ripup flags was associated with "perpandicular", as they + // must be re-inserted *before* any parallel. Must look to solve the redundancy. + + if ( _type & Perpandicular ) { + ltrace(200) << "* Riping Pp " << _segment << endl; + } else { + ltrace(200) << "* Riping // " << _segment << endl; + } + + if ( _segment->isFixed() ) return true; + + DataNegociate* data = _segment->getDataNegociate(); + if ( data == NULL ) return true; + + if ( _type & ResetRipup ) data->resetRipupCount (); + + if ( _type & ToState ) { + data->setState ( _toState ); + data->setRipupCount ( Session::getKiteEngine()->getRipupLimit(_segment) ); + } + + if ( data->getGCellOrder() == Session::getOrder() ) { + // Current order, default behavior: ripup. + if ( _segment->getTrack() ) + Session::addRemoveEvent ( _segment ); + } else if ( data->getGCellOrder() < Session::getOrder() ) { + // Order is lower: no longer able to displace it. + return false; + } else { + // Order is greater, do not route now. Ripup if needed. + if ( _segment->getTrack() ) + Session::addRemoveEvent ( _segment ); + return true; + } + + RoutingEvent* event = data->getRoutingEvent(); + if ( event == NULL ) { + if ( data->getGCellOrder() == Session::getOrder() ) { + cerr << Bug("Missing Event on %p:%s" + ,_segment->base()->base(),getString(_segment).c_str()) << endl; + } + ltrace(200) << "Not in current GCellRoutingSet, cancelled." << endl; + return true; + } + + if ( (_type & AxisHint) /*and not _segment->isSlackenDogLeg()*/ ) { + ltrace(200) << "Setting Axis Hint: @" << DbU::getValueString(_axisHint) << endl; + event->setAxisHint ( _axisHint ); + } + + if ( _type & ToRipupLimit ) { + unsigned int limit = Session::getKiteEngine()->getRipupLimit(_segment); + if ( limit > data->getRipupCount() ) + data->setRipupCount ( limit ); + } + + unsigned int eventLevel = 0; + if ( _type & EventLevel1 ) eventLevel = 1; + if ( _type & EventLevel2 ) eventLevel = 2; + if ( _type & EventLevel3 ) eventLevel = 3; + if ( _type & EventLevel4 ) eventLevel = 4; + if ( _type & EventLevel5 ) eventLevel = 5; + RoutingEvent* fork = event->reschedule ( queue, eventLevel ); + + if ( fork ) + fork->setMode ( (_type&PackingMode) ? RoutingEvent::Pack : RoutingEvent::Negociate ); + + return true; + } + + +// ------------------------------------------------------------------- +// Class Declaration : "::State". + + + class State { + + public: + enum StateValues { MissingData = (1<<0) + , EmptyTrackList = (1<<1) + , Inserted = (1<<2) + , Self = (1<<3) + , Other = (1<<4) + , Ripup = (1<<5) + , MaximumRipup = (1<<6) + , TopologyModificated = (1<<7) + , SelfInserted = Self | Inserted + , SelfMaximumRipup = Self | MaximumRipup + , OtherRipup = Other | Ripup + , OtherTopologyModificated = Other | TopologyModificated + , SelfTopologyModificated = Self | TopologyModificated + }; + enum SlackenFlags { NoRecursive = (1<<0) + , NoTransition = (1<<1) + }; + + public: + State ( RoutingEvent* + , RoutingEventQueue& + , RoutingEventHistory& + ); + inline RoutingEvent* getEvent (); + inline RoutingEventQueue& getQueue (); + inline RoutingEventHistory& getHistory (); + inline unsigned int getState (); + inline DataNegociate* getData (); + inline Interval& getConstraint (); + inline Interval& getOptimal (); + inline vector& getCosts (); + inline TrackCost& getCost ( size_t ); + inline Track* getTrack ( size_t ); + inline size_t getBegin ( size_t ); + inline size_t getEnd ( size_t ); + inline void setState ( unsigned int ); + inline void addAction ( TrackElement* + , unsigned int type + , DbU::Unit axisHint=0 + , unsigned int toState =0 + ); + inline vector& getActions (); + bool doActions (); + inline void clearActions (); + bool insertInTrack ( size_t ); + bool conflictSolve1 (); + bool conflictSolve2 (); + bool localVsGlobal (); + bool slackenTopology ( TrackElement*, unsigned int flags=0 ); + + private: + RoutingEvent* _event; + RoutingEventQueue& _queue; + RoutingEventHistory& _history; + unsigned int _state; + DataNegociate* _data; + Interval _constraint; + Interval _optimal; + vector _costs; + vector _actions; + }; + + +// ------------------------------------------------------------------- +// Class Declaration : "::Manipulator". + + + class Manipulator { + public: + enum { ToRipupLimit=1, AllowExpand =2, NoExpand=4, PerpandicularsFirst=8, ToMoveUp=16 }; + enum { LeftAxisHint=1, RightAxisHint=2 }; + public: + Manipulator ( TrackElement*, State& ); + ~Manipulator (); + inline TrackElement* getSegment () const; + inline DataNegociate* getData () const; + inline RoutingEvent* getEvent () const; + bool canRipup () const; + bool isCaged ( DbU::Unit ) const; + bool ripup ( Interval overlap + , unsigned int type + , DbU::Unit axisHint=0 + , unsigned int toState =0 + ); + bool ripup ( DbU::Unit point + , unsigned int type + , DbU::Unit axisHint=0 + ); + bool ripupPerpandiculars ( unsigned int flags=0 ); + bool ripple (); + bool goOutsideGCell (); + bool minimize (); + bool desalignate (); + bool slacken (); + bool pivotUp (); + bool moveUp (); + bool makeDogLeg (); + bool makeDogLeg ( Interval ); + bool relax ( Interval, unsigned int flags=AllowExpand ); + bool relax ( size_t ); + bool insertInTrack ( size_t ); + bool shrinkToTrack ( size_t + , unsigned int flags=0 + , DbU::Unit leftAxisHint=0 + , DbU::Unit rightAxisHint=0 + ); + bool forceToTrack ( size_t ); + void reprocessPerpandiculars (); + private: + TrackElement* _segment; + DataNegociate* _data; + RoutingEvent* _event; + State& _S; + }; + + +// ------------------------------------------------------------------- +// Class Definition : "::State". + + + State::State ( RoutingEvent* event, RoutingEventQueue& queue, RoutingEventHistory& history ) + : _event (event) + , _queue (queue) + , _history (history) + , _state (0) + , _data (NULL) + , _constraint () + , _optimal () + , _costs () + , _actions () + { + TrackElement* segment = _event->getSegment(); + _event->setTracksFree ( 0 ); + + _data = segment->getDataNegociate(); + if ( !_data ) { + _state = MissingData; + return; + } + +#if defined(CHECK_DETERMINISM) + cerr << "Order: " << _data->getGCellOrder() << " - " << _data->getCost() << endl; +#endif + + _data->update (); + _event->invalidate ( true ); // Optimizable. + _event->revalidate ( true ); + + _constraint = _event->getConstraints(); + _optimal = _event->getOptimal(); + + const Interval& perpandicular = _event->getPerpandicular (); + + ltrace(148) << "Katabatic intervals:" << endl; + ltrace(148) << "* Optimal: " << _optimal << endl; + ltrace(148) << "* Constraints: " << _constraint << endl; + ltrace(148) << "* Perpandicular: " << perpandicular << endl; + ltrace(148) << "* OptimalAxis: " << _event->getOptimalAxis() << endl; + ltrace(148) << "* AxisHint: " << DbU::getValueString(_event->getAxisHint()) << endl; + + if ( _event->getTracksNb() ) { + if ( _constraint.getIntersection(perpandicular).isEmpty() ) { + ltrace(200) << "Perpandicular free is too tight." << endl; + _state = EmptyTrackList; + } else + _constraint.intersection ( perpandicular ); + } else { + ltrace(200) << "No Track in perpandicular free." << endl; + _state = EmptyTrackList; + } + + if ( _state == EmptyTrackList ) return; + + ltrace(148) << "Negociate intervals:" << endl; + ltrace(148) << "* Optimal: " << _optimal << endl; + ltrace(148) << "* Constraints: " << _constraint << endl; + ltracein(148); + + bool inLocalDepth = (Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) < 3); + + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer()); + forEach ( Track*, itrack, Tracks_Range::get(plane,_constraint)) { + _costs.push_back ( itrack->getOverlapCost(segment) ); + _costs.back().setAxisWeight ( _event->getAxisWeight(itrack->getAxis()) ); + _costs.back().incDeltaPerpand ( _data->getCost().getWiringDelta(itrack->getAxis()) ); + + if ( inLocalDepth and (_costs.back().getDataState() == DataNegociate::MaximumSlack) ) + _costs.back().setInfinite (); + + _costs.back().consolidate (); + ltrace(149) << "| " << (*itrack) << " - " << _costs.back() << endl; + } + ltraceout(148); + + if ( _data->isBorder() and (_costs.size() == 1) and _costs[0].isInfinite() ) { + Interval span; + if ( _data->isLeftBorder() ) { + span = Interval ( segment->getCanonicalInterval().getVMin() + , segment->getCanonicalInterval().getVMin()+DbU::lambda(5.0) ); + } else { + span = Interval ( segment->getCanonicalInterval().getVMax()-DbU::lambda(5.0) + , segment->getCanonicalInterval().getVMax() ); + } + + Track* track = _costs[0].getTrack(); + _costs[0] = track->getOverlapCost ( span, segment->getNet() ); + _costs[0].setAxisWeight ( _event->getAxisWeight(track->getAxis()) ); + _costs[0].incDeltaPerpand ( _data->getCost().getWiringDelta(track->getAxis()) ); + + if ( segment->isGlobal() and (_costs[0].getDataState() == DataNegociate::MaximumSlack) ) + _costs[0].setInfinite (); + + _costs[0].consolidate (); + ltrace(200) << "Replace: " << _costs[0] << endl; + } + + if ( _costs.empty() ) { + Track* nearest = plane->getTrackByPosition(_constraint.getCenter()); + + if ( (nearest->getAxis() < _constraint.getVMin()) + || (nearest->getAxis() > _constraint.getVMax()) ) { + //setUnimplemented (); + //cerr << "[UNIMPLEMENTED] " << segment << " no Track in constraint interval " + // << _constraint << " " << "." << endl; + } else { + cerr << Bug(" %s Track_Range() failed to find Tracks in %s (they exists)." + ,getString(segment).c_str() + ,getString(_constraint).c_str() + ) << endl; + } + _state = EmptyTrackList; + } + + sort ( _costs.begin(), _costs.end() ); + size_t i=0; + for ( ; (i<_costs.size()) and _costs[i].isFree() ; i++ ); + _event->setTracksFree ( i ); + } + + + inline RoutingEvent* State::getEvent () { return _event; } + inline RoutingEventQueue& State::getQueue () { return _queue; } + inline RoutingEventHistory& State::getHistory () { return _history; } + inline unsigned int State::getState () { return _state; } + inline DataNegociate* State::getData () { return _data; } + inline Interval& State::getConstraint () { return _constraint; } + inline Interval& State::getOptimal () { return _optimal; } + inline vector& State::getCosts () { return _costs; } + inline TrackCost& State::getCost ( size_t i ) { return _costs[i]; } + inline Track* State::getTrack ( size_t i ) { return _costs[i].getTrack(); } + inline size_t State::getBegin ( size_t i ) { return _costs[i].getBegin(); } + inline size_t State::getEnd ( size_t i ) { return _costs[i].getEnd(); } + inline vector& State::getActions () { return _actions; } + inline void State::setState ( unsigned int state ) { _state = state; } + inline void State::clearActions () { _actions.clear(); } + + + void State::addAction ( TrackElement* segment + , unsigned int type + , DbU::Unit axisHint + , unsigned int toState ) + { + if ( not segment->isFixed() ) { + _actions.push_back ( SegmentAction(segment,type,axisHint,toState) ); + ltrace(200) << "State::addAction(): " << segment << endl; + } + } + + + bool State::doActions () + { + ltrace(200) << "State::doActions() - " << _actions.size() << endl; + + bool ripupOthersParallel = false; + for ( size_t i=0 ; i<_actions.size() ; i++ ) { + if ( _actions[i].getType() & SegmentAction::OtherRipup ) { + ripupOthersParallel = true; + } + } + + for ( size_t i=0 ; i<_actions.size() ; i++ ) { + if ( (_actions[i].getType() & SegmentAction::SelfInsert) and ripupOthersParallel ) + _actions[i].setFlag ( SegmentAction::EventLevel3 ); + + if ( not _actions[i].doAction(_queue) ) { + cinfo << "[INFO] Failed action on " << _actions[i].getSegment() << endl; + } + } + + _actions.clear (); + return true; + } + + + bool State::insertInTrack ( size_t i ) + { + ltrace(200) << "State::insertInTrack() istate:" << _event->getInsertState() + << " track:" << i << endl; + + _event->incInsertState(); + switch ( _event->getInsertState() ) { + case 1: + if ( Manipulator(_event->getSegment(),*this).insertInTrack(i) ) return true; + _event->incInsertState(); + case 2: + if ( Manipulator(_event->getSegment(),*this).shrinkToTrack(i) ) return true; + _event->incInsertState(); + case 3: + if ( Manipulator(_event->getSegment(),*this).forceToTrack(i) ) return true; + _event->incInsertState(); + } + return false; + } + + + bool State::conflictSolve2 () + { + bool success = false; + RipupHistory ripupHistory ( _event ); + RoutingEvent* event; + TrackElement* segment = _event->getSegment(); + + ltrace(200) << "State::conflictSolve2()" << endl; + + size_t maxDepth = min ( getHistory().size(), (size_t)300 ); + size_t depth = 0; + while ( (ripupHistory.getDislodgersCount() < 3) and (depth < maxDepth) ) { + event = getHistory().getRNth(depth++); + if ( !event ) continue; + if ( (event->getSegment() != segment) and ripupHistory.isDislodger(event) ) + ripupHistory.addDislodger ( event ); + } + + //ripupHistory.print ( cout ); + + UnionIntervals* intervals = ripupHistory.getUnionIntervals ( segment->getAxis() ); + if ( intervals && !intervals->empty() ) { + + DbU::Unit minConflict = intervals->getVMin(); + DbU::Unit maxConflict = intervals->getVMax(); + Interval canonical = segment->getCanonicalInterval(); + bool sourceDogLeg = canonical.contains(minConflict); + bool targetDogLeg = canonical.contains(maxConflict); + + if ( sourceDogLeg || targetDogLeg ) { + Point breakPoint; + if ( segment->isHorizontal() ) + breakPoint = Point ( (sourceDogLeg)?minConflict:maxConflict ,segment->getAxis() ); + else + breakPoint = Point ( segment->getAxis(), (sourceDogLeg)?minConflict:maxConflict ); + + GCell* dogLegGCell = Session::getGCellUnder ( breakPoint.getX(), breakPoint.getY() ); + if ( dogLegGCell ) { + if ( segment->canDogLegAt(dogLegGCell) ) { + if ( segment->makeDogLeg(dogLegGCell) ) + success = true; + } + } else { + cerr << Bug("No GCell under %s.",getString(breakPoint).c_str()) << endl; + } + + if ( !success ) { + if ( segment->isHorizontal() ) + breakPoint = Point ( (targetDogLeg)?maxConflict:minConflict ,segment->getAxis() ); + else + breakPoint = Point ( segment->getAxis(), (targetDogLeg)?maxConflict:minConflict ); + + GCell* dogLegGCell = Session::getGCellUnder ( breakPoint.getX(), breakPoint.getY() ); + if ( dogLegGCell ) { + if ( segment->canDogLegAt(dogLegGCell) ) { + if ( segment->makeDogLeg(dogLegGCell) ) + success = true; + } + } else { + cerr << Bug("No GCell under %s.",getString(breakPoint).c_str()) << endl; + } + } + } + } else { + ltrace(200) << "No disloggers found @" << DbU::getValueString(segment->getAxis()) << endl; + + Interval freeSpan = Session::getKiteEngine()-> + getTrackByPosition(segment->getLayer(),segment->getAxis())-> + getFreeInterval(segment->getSourceU(),segment->getNet()); + + if ( freeSpan.contains(segment->getCanonicalInterval()) ) { + ltrace(200) << "Disloggers vanished, Segment can be re-inserted." << endl; + success = true; + } + } + + return success; + } + + + bool State::conflictSolve1 () + { + bool success = false; + bool constraintByPerpandiculars = false; + Interval constraints; + vector candidates; + TrackElement* segment = _event->getSegment(); + bool canMoveUp = (segment->isLocal()) ? segment->canPivotUp() : segment->canMoveUp(); + unsigned int relaxFlags + = (_data and (_data->getStateCount() < 2)) ? Manipulator::AllowExpand : Manipulator::NoExpand; + + ltrace(200) << "State::conflictSolve1()" << endl; + ltrace(200) << "| Candidates Tracks: " << endl; + + segment->base()->getConstraints ( constraints ); + Interval overlap = segment->getCanonicalInterval(); + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer()); + Track* track = plane->getTrackByPosition(constraints.getVMin(),Constant::Superior); + + for ( ; track->getAxis() <= constraints.getVMax() ; track = track->getNext() ) { + ltrace(200) << "* " << track << endl; + candidates.push_back ( Cs1Candidate(track) ); + + size_t begin; + size_t end; + TrackElement* other; + Net* otherNet = NULL; + Interval otherOverlap; + + track->getOverlapBounds ( overlap, begin, end ); + candidates.back().setBegin ( begin ); + candidates.back().setEnd ( end ); + + for ( ; (begin < end) ; begin++ ) { + other = track->getSegment(begin); + + if ( other->getNet() == segment->getNet() ) continue; + if ( !other->getCanonicalInterval().intersect(overlap) ) continue; + ltrace(200) << " | Conflict: " << begin << " " << other << endl; + + if ( otherNet != other->getNet() ) { + if ( otherNet != NULL ) { + candidates.back().addConflict ( otherOverlap ); + } + otherNet = other->getNet(); + otherOverlap = other->getCanonicalInterval(); + } else { + otherOverlap.merge(other->getCanonicalInterval()); + } + } + if ( not otherOverlap.isEmpty() ) + candidates.back().addConflict ( otherOverlap ); + } + + sort ( candidates.begin(), candidates.end() ); + + for ( size_t icandidate=0 ; icandidate 2 ) break; + + Interval overlap0 = candidates[icandidate].getConflict(0); + if ( candidates[icandidate].getLength() == 1 ) { + ltrace(200) << "conflictSolve1() - One conflict, relaxing self" << endl; + + if ( Manipulator(segment,*this).relax(overlap0,relaxFlags) ) { + success = true; + break; + } else { + if ( not canMoveUp + and (relaxFlags != Manipulator::NoExpand) + and Manipulator(segment,*this).relax(overlap0,Manipulator::NoExpand) ) { + ltrace(200) << "Cannot move up but successful narrow breaking." << endl; + success = true; + break; + } + } + } + + if ( candidates[icandidate].getLength() == 2 ) { + ltrace(200) << "conflictSolve1() - Two conflict, relaxing self" << endl; + + Interval overlap1 = candidates[icandidate].getConflict(1); + // Ugly: hard-coded half GCell side. + if ( overlap1.getVMin() - overlap0.getVMax() < DbU::lambda(5.0) ) { + ltrace(200) << "conflictSolve1() - Too narrow spacing: " + << DbU::getValueString(overlap1.getVMin() - overlap0.getVMax()) << endl; + continue; + } + + if ( Manipulator(segment,*this).relax(overlap0,relaxFlags) ) { + success = true; + break; + } else { + if ( not canMoveUp + and (relaxFlags != Manipulator::NoExpand) + and Manipulator(segment,*this).relax(overlap0,Manipulator::NoExpand) ) { + ltrace(200) << "Cannot move up but successful narrow breaking." << endl; + success = true; + break; + } + } + } + } + + //if ( track && (track->getAxis() < constraints.getVMin()) ) track = track->getNext(); + //for ( ; !success && track && (track->getAxis() <= constraints.getVMax()) ; track = track->getNext() ) + + if ( !success && constraintByPerpandiculars ) { + ltrace(200) << "Overconstrained perpandiculars, rip them up. On track:" << endl; + ltrace(200) << " " << track << endl; + Manipulator(segment,*this).ripupPerpandiculars (); + success = true; + } + + return success; + } + + + bool State::localVsGlobal () + { + ltrace(200) << "State::localVsGlobal()" << endl; + ltracein(200); + + bool success = false; + Interval constraint = _event->getConstraints(); + TrackElement* segment = _event->getSegment(); + Interval overlap = segment->getCanonicalInterval(); + vector candidates; + //Interval uside = segment->getGCell()->getUSide(segment->getDirection(),true); + Interval uside = overlap; + + // Ugly: Hard-wired pitch usage. + uside.inflate ( DbU::lambda(10.0) ); + ltrace(200) << "uside: " << uside << endl; + + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer()); + forEach ( Track*, itrack, Tracks_Range::get(plane,constraint)) { + ltrace(200) << "| " << (*itrack) << " - " << endl; + + size_t begin; + size_t end; + TrackElement* candidate = NULL; + Net* otherNet = NULL; + Interval otherOverlap; + unsigned int weight = 0; + size_t terminals = 0; + + itrack->getOverlapBounds ( overlap, begin, end ); + for ( ; (begin < end) ; begin++ ) { + TrackElement* other = itrack->getSegment(begin); + + if ( other->getNet() == segment->getNet() ) continue; + if ( not other->getCanonicalInterval().intersect(overlap) ) continue; + if ( not other->isGlobal() ) { candidate = NULL; break; } + ltrace(200) << "| Conflict: " << begin << " " << other << endl; + + if ( otherNet == NULL ) { + otherNet = other->getNet(); + otherOverlap = other->getCanonicalInterval(); + candidate = other; + + itrack->getTerminalWeight ( uside, otherNet, terminals, weight ); + + // if ( (other->base()->getAutoSource()->getAnchor() != NULL) + // and (overlap.contains(otherOverlap.getVMin())) ) + // ++terminals; + + // if ( (other->base()->getAutoTarget()->getAnchor() != NULL) + // and (overlap.contains(otherOverlap.getVMax())) ) + // ++terminals; + + ltrace(200) << "> Candidate " << candidate << endl; + } else { + if ( other->getNet() == otherNet ) { + Interval otherCanonical = other->getCanonicalInterval(); + if ( otherOverlap.intersect(otherCanonical) ) { + otherOverlap.merge(otherCanonical); + + // if ( (other->base()->getAutoSource()->getAnchor() != NULL) + // and (overlap.contains(otherCanonical.getVMin())) ) + // ++terminals; + + // if ( (other->base()->getAutoTarget()->getAnchor() != NULL) + // and (overlap.contains(otherCanonical.getVMax())) ) + // ++terminals; + + continue; + } + } else { + ltrace(200) << "> Reject candidate " << candidate << endl; + candidate = NULL; + break; + } + } + } + + if ( candidate ) + candidates.push_back ( LvGCandidate(candidate,otherOverlap,terminals) ); + } + + if ( candidates.empty() ) { + ltraceout(200); + return false; + } + + sort ( candidates.begin(), candidates.end(), LvGCandidate::Compare() ); + for ( size_t i=0 ; igetDataNegociate (); + unsigned int nextState = 0; + + ltrace(200) << "Slacken Topology for " << segment->getNet() + << " " << segment << endl; + ltracein(200); + + if ( (not segment) or (not data) ) { ltraceout(200); return false; } + if ( segment == _event->getSegment() ) _event->resetInsertState(); + + if ( not (data->isBorder() or data->isRing()) ) { + data->resetRipupCount (); + } else { + if ( not Manipulator(segment,*this).canRipup() ) { + cerr << "[UNSOLVED] " << segment << " slacken topology not allowed for border/ring." << endl; + ltraceout(200); + return false; + } + } + + // Ring cases. + if ( data->isBorder() ) { + ltrace(200) << "Segment is Ripup only (border), bypass to Unimplemented." << endl; + if ( not Manipulator(segment,*this).canRipup () ) { + ltrace(200) << "Cannot ripup, bypass to Unimplemented." << endl; + data->setState ( DataNegociate::Unimplemented ); + } else { + ltrace(200) << "Refusing to slacken border segment." << endl; + ltraceout(200); + return false; + } + } + + if ( data->isRing() ) { + ltrace(200) << "Segment is Ripup only (ring), back-propagate to perpandiculars." << endl; + // Do not change the state. + //data->setState ( DataNegociate::Unimplemented ); + success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit + |Manipulator::PerpandicularsFirst + |Manipulator::ToMoveUp); + repush = false; + if ( not success ) { + data->setState ( DataNegociate::Unimplemented ); + } + } + + // Normal cases. + if ( not blocked and not success ) { + if ( segment->isStrap() ) { + switch ( data->getState() ) { + case DataNegociate::RipupPerpandiculars: + nextState = DataNegociate::Desalignate; + success = Manipulator(segment,*this).ripupPerpandiculars(); + if ( success ) break; + case DataNegociate::Desalignate: + case DataNegociate::Minimize: + nextState = DataNegociate::LocalVsGlobal; + success = Manipulator(segment,*this).minimize(); + if ( success ) break; + case DataNegociate::DogLeg: + case DataNegociate::Slacken: + case DataNegociate::ConflictSolve1: + case DataNegociate::ConflictSolve2: + case DataNegociate::MoveUp: + case DataNegociate::LocalVsGlobal: + if ( not (flags & NoRecursive) ) { + if ( (success = localVsGlobal()) ) { + nextState = DataNegociate::LocalVsGlobal; + if ( data->getStateCount() >= 1 ) + nextState = DataNegociate::MaximumSlack; + break; + } + } + case DataNegociate::MaximumSlack: + case DataNegociate::Unimplemented: + nextState = DataNegociate::Unimplemented; + break; + } + + if ( not success and (nextState != DataNegociate::Unimplemented) ) { + // if ( segment->canRipple() ) + // success = Manipulator(segment,*this).ripple(); + // else + success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit); + } + } else if ( segment->isLocal() ) { + // Local TrackElement State Machine. + switch ( data->getState() ) { + case DataNegociate::RipupPerpandiculars: + nextState = DataNegociate::Desalignate; + success = Manipulator(segment,*this).ripupPerpandiculars(); + if ( success ) break; + case DataNegociate::Desalignate: + nextState = DataNegociate::Minimize; + success = Manipulator(segment,*this).desalignate(); + break; + case DataNegociate::Minimize: + nextState = DataNegociate::DogLeg; + success = Manipulator(segment,*this).minimize(); + if ( success ) break; + case DataNegociate::DogLeg: + nextState = DataNegociate::Slacken; + success = Manipulator(segment,*this).makeDogLeg(); + if ( success ) break; + case DataNegociate::Slacken: + nextState = DataNegociate::ConflictSolve2; + success = Manipulator(segment,*this).slacken(); + if ( success ) break; + case DataNegociate::ConflictSolve1: + case DataNegociate::ConflictSolve2: + if ( not (flags & NoRecursive) ) { + nextState = DataNegociate::MoveUp; + success = conflictSolve2 (); + break; + } + case DataNegociate::MoveUp: + nextState = DataNegociate::LocalVsGlobal; + success = Manipulator(segment,*this).moveUp(); + if ( success ) break; + case DataNegociate::LocalVsGlobal: + if ( not (flags & NoRecursive) ) { + if ( (success = localVsGlobal()) ) { + nextState = DataNegociate::LocalVsGlobal; + if ( data->getStateCount() >= 1 ) + nextState = DataNegociate::MaximumSlack; + break; + } + } + case DataNegociate::MaximumSlack: + if ( segment->isSlackenStrap() ) { + if ( nextState < DataNegociate::MaximumSlack ) { + nextState = DataNegociate::MaximumSlack; + success = conflictSolve1 (); + if ( success ) break; + } + } + case DataNegociate::Unimplemented: + nextState = DataNegociate::Unimplemented; + break; + } + + if ( not success and (nextState != DataNegociate::Unimplemented) ) { + // if ( segment->canRipple() ) + // success = Manipulator(segment,*this).ripple(); + // else + success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit); + } + + // Special case: all tracks are overlaping a blockage. + if ( not success + and (nextState == DataNegociate::Unimplemented) + and segment->isSlackened() ) { + blocked = (getCosts().size() > 0); + for ( size_t itrack=0 ; itrackgetSegment()->base()->getConstraints ( nativeConstraints ); + + //if ( nativeConstraints.getSize() < DbU::lambda(5.0) ) { + // blocked = true; + success = Manipulator(segment,*this).pivotUp(); + if ( not success ) { + cerr << "[ERROR] Tighly constrained segment overlapping a blockage." << endl; + ltrace(200) << "Segment is hard blocked, bypass to Unimplemented." << endl; + nextState = DataNegociate::Unimplemented; + } + //} + } + } + + // LOOPING. + // if ( not success + // and (nextState == DataNegociate::Unimplemented) + // and segment->isSlackened() ) { + // ltrace(200) << "Last chance on slackened" << endl; + // segment->base()->setSlackened ( false ); + // success = Manipulator(segment,*this).makeDogLeg(); + // nextState = DataNegociate::MaximumSlack; + // } + } else { + // Global TrackElement State Machine. + switch ( data->getState() ) { + case DataNegociate::RipupPerpandiculars: + ltrace(200) << "Global, State: RipupPerpandiculars." << endl; + nextState = DataNegociate::Desalignate; + break; + case DataNegociate::Minimize: + case DataNegociate::DogLeg: + case DataNegociate::Desalignate: + ltrace(200) << "Global, State: Minimize, DogLeg or Desalignate." << endl; + if ( (success = Manipulator(segment,*this).desalignate()) ) { + nextState = DataNegociate::Slacken; + break; + } + case DataNegociate::Slacken: + ltrace(200) << "Global, State: Slacken." << endl; + if ( (success = Manipulator(segment,*this).slacken()) ) { + nextState = DataNegociate::ConflictSolve1; + break; + } + case DataNegociate::ConflictSolve1: + case DataNegociate::ConflictSolve2: + ltrace(200) << "Global, State: ConflictSolve1 or ConflictSolve2." << endl; + if ( not (flags & NoRecursive) ) { + if ( (success = conflictSolve1 ()) ) { + nextState = DataNegociate::ConflictSolve1; + if ( data->getStateCount() > 3 ) + nextState = DataNegociate::MoveUp; + break; + } + } + case DataNegociate::MoveUp: + ltrace(200) << "Global, State: MoveUp." << endl; + if ( (success = Manipulator(segment,*this).moveUp()) ) { + nextState = DataNegociate::ConflictSolve1; + break; + } + case DataNegociate::MaximumSlack: + case DataNegociate::Unimplemented: + ltrace(200) << "Global, State: MaximumSlack or Unimplemented." << endl; + nextState = DataNegociate::Unimplemented; + break; + } + + if ( not success and (nextState != DataNegociate::Unimplemented) ) { + success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit); + } + } + } + + if ( not (flags&NoTransition) ) data->setState ( nextState ); + + if ( success ) { + if ( repush ) { + unsigned int flags = SegmentAction::SelfInsert|SegmentAction::EventLevel5; + if ( not (data->isRing() or data->isBorder()) ) + flags |= SegmentAction::ResetRipup; + + addAction ( segment, flags ); + } + } else { + clearActions (); + if ( data->getState() == DataNegociate::Unimplemented ) { + cerr << "[UNSOLVED] " << segment << " unable to slacken topology." << endl; + } + } + + ltraceout(200); + + return success; + } + + +// ------------------------------------------------------------------- +// Class Definition : "::Manipulator". + + + inline TrackElement* Manipulator::getSegment () const { return _segment; } + inline DataNegociate* Manipulator::getData () const { return _data; } + inline RoutingEvent* Manipulator::getEvent () const { return _event; } + + + Manipulator::Manipulator ( TrackElement* segment, State& S ) + : _segment(segment) + , _data (NULL) + , _event (NULL) + , _S (S) + { + if ( !_segment ) + throw Error("Manipulator::Manipulator(): cannot build upon a NULL TrackElement."); + + DebugSession::open ( _segment->getNet() ); + + _data = _segment->getDataNegociate(); + if ( _data ) + _event = _data->getRoutingEvent(); + } + + + Manipulator::~Manipulator () + { + DebugSession::close (); + } + + + bool Manipulator::canRipup () const + { + if ( _data ) { + unsigned int limit = Session::getKiteEngine()->getRipupLimit(_segment); + return (_data->getRipupCount() < limit) and _event and not _event->isUnimplemented(); + } + + return false; + } + + + bool Manipulator::isCaged ( DbU::Unit axis ) const + { + Track* track = _segment->getTrack(); + if ( not track ) return false; + + TrackElement* neighbor = _segment->getPrevious(); + if ( neighbor and (neighbor->isFixed() or neighbor->isBlockage()) ) { + if ( abs(axis - neighbor->getTargetU()) < DbU::lambda(10.0) ) + return true; + } + + neighbor = _segment->getNext(); + if ( neighbor and (neighbor->isFixed() or neighbor->isBlockage()) ) { + if ( abs(axis - neighbor->getSourceU()) < DbU::lambda(10.0) ) + return true; + } + + return false; + } + + + bool Manipulator::ripup ( DbU::Unit point , unsigned int type, DbU::Unit axisHint ) + { + ltrace(200) << "Manipulator::ripup(DbU::Unit) " << DbU::getValueString(point) << endl; + + Interval overlap = Interval(point); + overlap.inflate ( Session::getExtensionCap() ); // Ugly. + + return ripup ( overlap, type, axisHint ); + } + + + bool Manipulator::ripup ( Interval overlap , unsigned int type, DbU::Unit axisHint, unsigned int toState ) + { + ltrace(200) << "Manipulator::ripup(Interval) " << overlap << endl; + ltrace(200) << "TrackElement:" << _data->getGCellOrder() + << " < Session:" << Session::getOrder() << endl; + + if ( _segment->isFixed() ) return false; + if ( !_data ) return true; + + if ( _segment->getTrack() ) { + if ( _data->getGCellOrder() < Session::getOrder() ) { + return relax(overlap); + } + } + + _S.addAction ( _segment, type, axisHint, toState ); + return true; + } + + + bool Manipulator::ripupPerpandiculars ( unsigned int flags ) + { + ltrace(200) << "Manipulator::ripupPerpandiculars() - " << flags << endl; + + bool success = true; + bool cagedPerpandiculars = false; + Interval constraints ( _event->getConstraints() ); + Interval perpandicularConstraints ( constraints ); + size_t placedPerpandiculars = 0; + unsigned int parallelActionFlags = SegmentAction::SelfRipup|SegmentAction::EventLevel4; + unsigned int perpandicularActionFlags = SegmentAction::SelfRipupPerpand; + + if ( flags & Manipulator::PerpandicularsFirst ) { + parallelActionFlags &= ~SegmentAction::EventLevel4; + perpandicularActionFlags |= SegmentAction::EventLevel4; + if ( flags & Manipulator::ToRipupLimit ) + perpandicularActionFlags |= SegmentAction::ToRipupLimit; + } else { + if ( flags & Manipulator::ToRipupLimit ) + parallelActionFlags |= SegmentAction::ToRipupLimit; + } + + ltrace(200) << "Pure constraints: " << constraints << endl; + + Track* track = NULL; + const vector& perpandiculars = _event->getPerpandiculars(); + + for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) { + track = perpandiculars[i]->getTrack(); + if ( not track ) continue; + + if ( Manipulator(perpandiculars[i],_S).isCaged(_event->getSegment()->getAxis()) ) { + cagedPerpandiculars = true; + break; + } + + placedPerpandiculars++; + DataNegociate* data2 = perpandiculars[i]->getDataNegociate(); + if ( data2->getGCellOrder() == Session::getOrder() ) { + ltrace(200) << "| " << perpandiculars[i] << endl; + + if ( (flags & Manipulator::ToMoveUp) + and (data2->getState() < DataNegociate::MoveUp) ) + data2->setState ( DataNegociate::MoveUp ); + + Manipulator(perpandiculars[i],_S).ripup ( _event->getSegment()->getAxis(), perpandicularActionFlags ); + continue; + } + + size_t begin; + size_t end; + track->getOverlapBounds ( constraints, begin, end ); + + for ( ; (begin < end) ; begin++ ) { + TrackElement* other = track->getSegment(begin); + + if ( other->getNet() == _event->getSegment()->getNet() ) continue; + + Interval otherCanonical ( other->getCanonicalInterval() ); + if ( not otherCanonical.intersect(constraints) ) continue; + if ( other->getDataNegociate() + and (other->getDataNegociate()->getGCellOrder() < Session::getOrder()) ) { + if ( otherCanonical.getVMin() < constraints.getVMin() ) + constraints.shrinkVMin ( otherCanonical.getVMax() ); + else + constraints.shrinkVMax ( otherCanonical.getVMin() ); + continue; + } + + ltrace(200) << " | Ripup: " << begin << " " << other << endl; + _S.addAction ( other, SegmentAction::OtherRipup ); + } + } + + if ( cagedPerpandiculars ) { + ltrace(200) << "Aborted ripup of perpandiculars, constraints are due to fixed/blockage." << endl; + _S.addAction ( _segment, SegmentAction::SelfRipup ); + return true; + } + + if ( _segment->isLocal() and not placedPerpandiculars ) { + ltrace(200) << "No placed perpandiculars, tight native constraints." << endl; + for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) { + _S.addAction ( perpandiculars[i], perpandicularActionFlags|SegmentAction::EventLevel4 ); + } + _S.addAction ( _segment, parallelActionFlags ); + return true; + } + + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_segment->getLayer()); + size_t tracksNb = 0; + + track = plane->getTrackByPosition(constraints.getVMin()); + + if ( track && (track->getAxis() < constraints.getVMin()) ) track = track->getNext(); + for ( ; track && (track->getAxis() <= constraints.getVMax()) + ; track = track->getNext(), tracksNb++ ); + + if ( _segment->isLocal() and (tracksNb < 2) ) success = ripple(); + + _S.addAction ( _segment, parallelActionFlags ); + return success; + } + + + bool Manipulator::relax ( Interval interval, unsigned int flags ) + { + interval.inflate ( - Session::getExtensionCap() /*+ DbU::lambda(5.0)*/ ); // Ugly. + ltrace(200) << "Manipulator::relax() of: " << _segment << " " << interval << endl; + + if ( _segment->isFixed() ) return false; + if ( !interval.intersect(_segment->getCanonicalInterval()) ) return false; + if ( !_data ) return false; + + if ( _segment->isTerminal() + and (_segment->getLayer() == Session::getRoutingGauge()->getRoutingLayer(1)) ) { + if ( interval.contains(_segment->base()->getAutoSource()->getX()) ) return false; + if ( interval.contains(_segment->base()->getAutoTarget()->getX()) ) return false; + } + + bool success = true; + unsigned int currentOrder = Session::getOrder (); + + ltracein(200); + ltrace(200) << "Current o:" << currentOrder << " vs. Segment o:" << _data->getGCellOrder() << endl; + + //bool expand = (_data->getGCellOrder() < currentOrder); + bool expand = _segment->isGlobal() and (flags&AllowExpand); + ltrace(200) << "Expand:" << expand << endl; + + // Temp: <= replace < equal order can be relaxeds. + if ( _data->getGCellOrder() <= currentOrder ) { + vector gcells; + _segment->getGCells ( gcells ); + if ( gcells.size() < 2 ) { + cerr << Bug("relax() Cannot break %p:%s,\n" + " only in %s (current order %d)." + ,_segment->base()->base() + ,getString(_segment).c_str() + ,getString(gcells[0]).c_str() + ,currentOrder + ) << endl; + ltraceout(200); + return false; + } + + unsigned int depth = Session::getRoutingGauge()->getLayerDepth(_segment->getLayer()); + Interval uside; + size_t dogLegCount = 0; + size_t iminconflict = gcells.size(); + size_t imaxconflict = gcells.size(); + size_t igcell; + + // Look for closest enclosing min & max GCells indexes. + for ( igcell=0 ; igcellgetUSide(_segment->getDirection(),true); + ltrace(200) << "| " << gcells[igcell] << " uside: " << uside << endl; + + if ( uside.contains(interval.getVMin()) ) { + iminconflict = igcell; + ltrace(200) << "> Min conflict: " << iminconflict << endl; + } + if ( uside.contains(interval.getVMax()) ) { + imaxconflict = igcell; + ltrace(200) << "> Max conflict: " << imaxconflict << endl; + } + } + + // Expand min & max to enclose GCells of greatest or equal order + // (i.e. less saturateds) + bool minExpanded = false; + bool maxExpanded = false; + if ( expand ) { + size_t iexpand = iminconflict; + if ( iminconflict < gcells.size() ) { + for ( igcell=iminconflict ; true ; igcell-- ) { + if ( gcells[igcell]->getOrder() >= currentOrder ) iexpand = igcell; + else break; + + if ( igcell == 0 ) break; + } + + if ( iexpand > 0 ) { + size_t imindepth = iexpand; + for ( ; iexpand < iminconflict ; iexpand++ ) { + if ( not _segment->canDogLegAt(gcells[iexpand],true) ) continue; + + ltrace(200) << "Density " << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() + << " " << gcells[iexpand]->getDensity(depth) << endl; + + if ( gcells[imindepth]->getDensity(depth) > gcells[iexpand]->getDensity(depth) ) + imindepth = iexpand; + } + iexpand = imindepth; + } + if ( iminconflict != iexpand ) minExpanded = true; + iminconflict = (iexpand>0) ? iexpand : gcells.size(); + } + + iexpand = imaxconflict; + for ( igcell=imaxconflict ; igcell < gcells.size() ; igcell++ ) { + if ( gcells[igcell]->getOrder() >= currentOrder ) iexpand = igcell; + else break; + } + if ( iexpand < gcells.size()-1 ) { + size_t imindepth = iexpand; + for ( ; iexpand > imaxconflict ; iexpand-- ) { + if ( not _segment->canDogLegAt(gcells[iexpand],true) ) continue; + + ltrace(200) << "Density " << Session::getRoutingGauge()->getRoutingLayer(depth)->getName() + << " " << gcells[iexpand]->getDensity(depth) << endl; + + if ( gcells[imindepth]->getDensity(depth) > gcells[iexpand]->getDensity(depth) ) + imindepth = iexpand; + } + iexpand = imindepth; + } + if ( imaxconflict != iexpand ) maxExpanded = true; + imaxconflict = (iexpand < gcells.size()) ? iexpand : gcells.size(); + } + ltrace(200) << "minExpanded:" << minExpanded << " (" << iminconflict + << ") maxExpanded:" << maxExpanded << " (" << imaxconflict << ")" << endl; + + // Check for full enclosure. + if ( ( (iminconflict == gcells.size()) and (imaxconflict == gcells.size() ) ) + or ( (iminconflict == 0) and (imaxconflict == gcells.size()-1) )) { + cinfo << "[INFO] Manipulator::relax(): Segment fully enclosed in interval." << endl; + ltraceout(200); + return false; + } + + // Check order validity under the relaxed interval. + // Should be implicitely satisfied. + + // Suppress min/max if it's the first/last. + if ( (iminconflict < gcells.size()) and (imaxconflict == gcells.size()-1) ) imaxconflict = gcells.size(); + if ( (imaxconflict < gcells.size()) and (iminconflict == 0) ) iminconflict = gcells.size(); + + // Compute number of doglegs and nature of the *first* dogleg. + // (first can be min or max, second can only be max) + bool firstDogLegIsMin = false; + if ( iminconflict < gcells.size() ) { dogLegCount++; firstDogLegIsMin = true; } + if ( imaxconflict < gcells.size() ) dogLegCount++; + + switch ( dogLegCount ) { + case 2: + // Compact only if the double dogleg is at beginning or end. + if ( iminconflict == imaxconflict ) { + if ( iminconflict == 0 ) { + // First dogleg is max. + dogLegCount--; + } else if ( iminconflict == gcells.size()-1 ) { + dogLegCount--; + firstDogLegIsMin = true; + } + } + break; + case 1: break; + case 0: + cerr << Bug("Manipulator::relax() Can't find a GCell suitable for making dogleg.\n" + " Cannot move either left or right of %s. Current order %d." + ,getString(interval).c_str() + ,currentOrder + ) << endl; + ltraceout(200); + return false; + } + + ltrace(200) << "| Has to do " << dogLegCount << " doglegs." << endl; + + // Check for conflict occuring outside the current RoutingSet. + // Ugly: 2 track pitch. +#ifdef DISABLE_NARROW_DOGLEG + if ( (iminconflict != gcells.size()) + and ( (gcells[iminconflict]->getOrder() > currentOrder) + or (_data->getGCellOrder() < currentOrder) ) ) { + uside = gcells[iminconflict]->getUSide(_segment->getDirection(),true); + if ( interval.getVMin() - uside.getVMin() < DbU::lambda(10.0) ) { + ltrace(200) << "Min conflict dogleg space is too narrow (<2 tracks)." << endl; + ltraceout(200); + return false; + } else { + ltrace(200) << "Min conflict has sufficent slack min:" + << DbU::getValueString(interval.getVMin()) << " uside:" + << DbU::getValueString(uside.getVMin()) + << endl; + } + } +#endif + +#ifdef DISABLE_NARROW_DOGLEG + if ( (imaxconflict != gcells.size()) + and ( (gcells[imaxconflict]->getOrder() > currentOrder) + or (_data->getGCellOrder() < currentOrder) ) ) { + uside = gcells[imaxconflict]->getUSide(_segment->getDirection(),true); + if ( uside.getVMax() - interval.getVMax() < DbU::lambda(10.0) ) { + ltrace(200) << "Max conflict dogleg space is too narrow (<2 tracks)." << endl; + ltraceout(200); + return false; + } else { + ltrace(200) << "Max conflict has sufficent slack max:" + << DbU::getValueString(interval.getVMax()) << " uside:" + << DbU::getValueString(uside.getVMax()) + << endl; + } + } +#endif + + // Check of "min is less than one track close the edge" (while not expanded). + // AND we are on the first GCell AND there's one dogleg only. + if ( not minExpanded and (iminconflict == 0) and (imaxconflict == gcells.size()) ) { + ltrace(200) << "Cannot break in first GCell only." << endl; + ltraceout(200); + return false; + } + + // Check of "min is less than one track close the edge" (while not expanded). + if ( /*not minExpanded and*/ (iminconflict > 0) and (iminconflict < gcells.size()) ) { + uside = gcells[iminconflict-1]->getUSide(_segment->getDirection(),true); + ltrace(200) << "GCell Edge Comparison (min): " << uside + << " vs. " << DbU::getValueString(interval.getVMin()) << endl; + // Ugly: One lambda shrink. + if ( interval.getVMin()-DbU::lambda(1.0) <= uside.getVMax() ) { + if ( gcells[iminconflict-1]->getOrder() >= currentOrder ) { + ltrace(200) << "Using previous GCell." << endl; + iminconflict--; + } else { + ltrace(200) << "Cannot break in previous GCell." << endl; + ltraceout(200); + return false; + } + } + } + + // Check if there is only one dogleg AND it's the last one. + if ( not maxExpanded and (iminconflict == gcells.size()) and (imaxconflict == gcells.size()-1) ) { + ltrace(200) << "Cannot break in last GCell only." << endl; + ltraceout(200); + return false; + } + + // Check of "max is less than one track close the edge" (while not expanded). + // AND we are on the last GCell AND there's one dogleg only. + // if ( not maxExpanded and (iminconflict == gcells.size()) and (imaxconflict == gcells.size()-1) ) { + // uside = gcells[imaxconflict]->getUSide(_segment->getDirection(),true); + // ltrace(200) << "GCell Edge Comparison (max): " << uside + // << " vs. " << DbU::getValueString(interval.getVMax()) << endl; + // // Ugly: Direct uses of routing pitch. + // if ( interval.getVMax()+DbU::lambda(10.0) >= uside.getVMax() ) { + // ltrace(200) << "Cannot break in last GCell only, less than 2 pitches." << endl; + // ltraceout(200); + // return false; + // } + // } + + // Check of "max is less than one track close the edge" (while not expanded). + if ( /*not maxExpanded and*/ (imaxconflict < gcells.size()-1) ) { + uside = gcells[imaxconflict+1]->getUSide(_segment->getDirection(),true); + ltrace(200) << "GCell Edge Comparison (max): " << uside + << " vs. " << DbU::getValueString(interval.getVMax()) << endl; + // Ugly: Direct uses of routing pitch. + if ( interval.getVMax()+DbU::lambda(5.0) >= uside.getVMin() ) { + if ( gcells[imaxconflict+1]->getOrder() >= currentOrder ) { + ltrace(200) << "Using next GCell." << endl; + imaxconflict++; + } else { + ltrace(200) << "Cannot break in next GCell." << endl; + ltraceout(200); + return false; + } + } + } + + size_t ifirstDogleg = gcells.size(); + size_t isecondDogleg = gcells.size(); + if ( not firstDogLegIsMin ) { + ifirstDogleg = imaxconflict; + } else { + ifirstDogleg = iminconflict; + isecondDogleg = imaxconflict; + } + + // Making first dogleg. + ltrace(200) << "Making FIRST dogleg at " << ifirstDogleg << endl; + TrackElement* segment = _segment; + Track* track = _segment->getTrack(); + GCell* dogLegGCell = gcells[ifirstDogleg]; + TrackElement* dogleg = NULL; + DbU::Unit doglegAxis; + bool doglegReuse = false; + + // Try to reuse existing dogleg if broken at either end. + if ( ifirstDogleg == 0 ) dogleg = segment->getSourceDogLeg(); + if ( ifirstDogleg == gcells.size()-1 ) dogleg = segment->getTargetDogLeg(); + if ( dogleg ) { + ltrace(200) << "Reusing dogleg." << endl; + doglegReuse = true; + } else { + // Try to create a new dogleg. + if ( not segment->canDogLegAt(dogLegGCell) ) { + ltrace(200) << "Cannot create FIRST dogleg." << endl; + ltraceout(200); + return false; + } + dogleg = segment->makeDogLeg ( dogLegGCell ); + } + + if ( firstDogLegIsMin ) { + if ( minExpanded ) { + //doglegAxis = dogLegGCell->getUSide(segment->getDirection(),false).getVMax() - DbU::lambda(1.0); + doglegAxis = dogLegGCell->getUSide(segment->getDirection(),false).getCenter(); + } else { + // Ugly: hardcoded pitch. + doglegAxis = interval.getVMin() - DbU::lambda(5.0); + } + } else { + if ( maxExpanded ) { + doglegAxis = dogLegGCell->getUSide(segment->getDirection(),false).getVMin(); + } else { + // Ugly: hardcoded pitch (5.0 - 1.0). + doglegAxis = interval.getVMax() + DbU::lambda(4.0); + } + } + if ( doglegReuse ) _S.addAction ( dogleg, SegmentAction::OtherRipup ); + else dogleg->setAxis ( doglegAxis ); + + // If event is present, the dogleg is in the current RoutingSet. + RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent(); + if ( event ) { + ltrace(200) << "Set Axis Hint: @" << DbU::getValueString(doglegAxis) << " " << dogleg << endl; + event->setAxisHint ( doglegAxis ); + } else { + ltrace(200) << "Dogleg has no RoutingEvent yet." << endl; + } + + if ( (dogLegCount == 2) + and not segment->getTrack() + and (segment->getGCell()->getOrder() < Session::getOrder()) ) { + Session::addInsertEvent ( segment, track ); + } + + // Making second dogleg. + if ( dogLegCount > 1 ) { + ltrace(200) << "Making SECOND dogleg at " << isecondDogleg + << " on " << Session::getDogLegs()[2] << endl; + + dogleg = NULL; + segment = Session::lookup ( Session::getDogLegs()[2] ); + dogLegGCell = gcells[isecondDogleg]; + + if ( ifirstDogleg == isecondDogleg ) { + ltrace(200) << "Double break in same GCell." << endl; + segment->setSourceDogLeg(false); + } + + doglegReuse = false; + if ( isecondDogleg == gcells.size()-1 ) dogleg = segment->getTargetDogLeg(); + if ( dogleg ) { + ltrace(200) << "Reusing dogleg." << endl; + doglegReuse = true; + } else { + // Try to create a new dogleg. + if ( not segment->canDogLegAt(dogLegGCell) ) { + ltrace(200) << "Cannot create SECOND dogleg." << endl; + ltraceout(200); + return false; + } + dogleg = segment->makeDogLeg ( dogLegGCell ); + } + + if ( maxExpanded ) { + //doglegAxis = dogLegGCell->getUSide(segment->getDirection(),false).getVMin(); + doglegAxis = dogLegGCell->getUSide(segment->getDirection(),false).getCenter(); + } else { + // Ugly: hardcoded pitch. + doglegAxis = interval.getVMax() + DbU::lambda(5.0); + } + if ( doglegReuse ) _S.addAction ( dogleg, SegmentAction::OtherRipup ); + else dogleg->setAxis ( doglegAxis ); + + // If event is present, the dogleg is in the current RoutingSet. + RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent(); + if ( event ) { + ltrace(200) << "Set Axis Hint: @" << DbU::getValueString(doglegAxis) << " " << dogleg << endl; + event->setAxisHint ( doglegAxis ); + } else { + ltrace(200) << "Dogleg has no RoutingEvent yet." << endl; + } + + const vector& doglegs = Session::getDogLegs(); + for ( size_t i=0 ; igetGCell()->getOrder() < Session::getOrder() ) and not segment->getTrack() ) { + Session::addInsertEvent ( segment, track ); + } + } + } + } else if ( _data->getGCellOrder() > currentOrder ) { + cerr << Bug("relax() Routing order problem for %s." + ,getString(_segment).c_str()) << endl; + success = false; + } else { + // The TrackElement has an order equal to the Session, it's in the + // RoutingSet. + if ( !Manipulator(_segment,_S).makeDogLeg(interval) ) success = false; + } + + ltraceout(200); + return success; + } + + + bool Manipulator::insertInTrack ( size_t itrack ) + { + Track* track = _S.getTrack(itrack); + size_t begin = _S.getBegin(itrack); + size_t end = _S.getEnd (itrack); + Net* ownerNet = _segment->getNet(); + Interval toFree (_segment->getCanonicalInterval()); + Net* ripupNet = NULL; + set canonicals; + DbU::Unit rightAxisHint = 0; + DbU::Unit leftAxisHint = 0; + bool leftIntrication = false; + bool rightIntrication = false; + bool success = true; + unsigned long maxId = AutoSegment::getMaxId(); + + ltrace(200) << "Manipulator::insertInTrack() - " << toFree << endl; + + for ( size_t i = begin ; success && (i < end) ; i++ ) { + TrackElement* segment2 = track->getSegment(i); + + ltrace(200) << "* Looking // " << segment2 << endl; + + if ( segment2->getNet() == ownerNet ) continue; + if ( not toFree.intersect(segment2->getCanonicalInterval()) ) continue; + if ( segment2->getId() >= maxId ) continue; + if ( segment2->isBlockage() or segment2->base()->isFixed() ) { + success = false; + continue; + } + //if ( (segment2->getNet() != ripupNet ) + // && !toFree.intersect(segment2->getCanonicalInterval()) ) continue; + ripupNet = segment2->getNet(); + + DataNegociate* data2 = segment2->getDataNegociate(); + if ( !data2 ) { + ltrace(200) << "No DataNegociate, ignoring." << endl; + continue; + } + + if ( data2->getGCellOrder() < Session::getOrder() ) { + // Interval relax. + success = Manipulator(segment2,_S).relax ( toFree ); + } else { + if ( data2->getState() == DataNegociate::MaximumSlack ) { + ltrace(200) << "At " << DataNegociate::getStateString(data2) + << " for " << segment2 << endl; + success = false; + continue; + } + + bool shrinkLeft = false; + bool shrinkRight = false; + + if ( data2->getCost().getRightMinExtend() < toFree.getVMin() ) { + ltrace(200) << "- Shrink right edge (push left) " << segment2 << endl; + shrinkRight = true; + TrackElement* rightNeighbor2 = track->getSegment(i+1); + if ( rightNeighbor2 && (rightNeighbor2->getNet() == segment2->getNet()) ) { + Interval interval1 = segment2->getCanonicalInterval(); + Interval interval2 = rightNeighbor2->getCanonicalInterval(); + + if ( interval1.intersect(interval2) && (interval2.getVMax() > interval1.getVMax()) ) + shrinkLeft = true; + } + } + + if ( data2->getCost().getLeftMinExtend() > toFree.getVMax() ) { + ltrace(200) << "- Shrink left edge (push right) " << segment2 << endl; + shrinkLeft = true; + if ( i > 0 ) { + TrackElement* leftNeighbor2 = track->getSegment(i-1); + if ( leftNeighbor2 && (leftNeighbor2->getNet() == segment2->getNet()) ) { + Interval interval1 = segment2->getCanonicalInterval(); + Interval interval2 = leftNeighbor2->getCanonicalInterval(); + + if ( interval1.intersect(interval2) && (interval2.getVMin() < interval1.getVMin()) ) + shrinkRight = true; + } + } + } + + if ( not (shrinkLeft xor shrinkRight) ) { + ltrace(200) << "- Hard overlap/enclosure/shrink " << segment2 << endl; + Manipulator(segment2,_S).ripup ( toFree, SegmentAction::OtherRipup ); + } + + canonicals.clear (); + forEach ( TrackElement*, isegment3 + , segment2->getCollapsedPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) { + DataNegociate* data3 = isegment3->getDataNegociate(); + if ( not data3 ) continue; + + RoutingEvent* event3 = data3->getRoutingEvent(); + if ( not event3 ) continue; + + if ( not toFree.intersect(event3->getConstraints()) ) { + ltrace(200) << " . " << *isegment3 << endl; + continue; + } + + ltrace(200) << " | " << *isegment3 << endl; + + if ( shrinkRight xor shrinkLeft ) { + if ( shrinkRight ) { + Manipulator(*isegment3,_S).ripup ( track->getAxis() + , SegmentAction::OtherPushAside + | SegmentAction::AxisHint + , toFree.getVMin() - DbU::lambda(1.0) + ); + if ( event3->getTracksFree() == 1 ) { + ltrace(200) << "Potential left intrication with other perpandicular." << endl; + if ( isegment3->getAxis() == segment2->getTargetU() - Session::getExtensionCap() ) { + leftIntrication = true; + leftAxisHint = isegment3->getAxis(); + } + } + } + if ( shrinkLeft ) { + Manipulator(*isegment3,_S).ripup ( track->getAxis() + , SegmentAction::OtherPushAside + | SegmentAction::AxisHint + , toFree.getVMax() + DbU::lambda(1.0) + ); + if ( event3->getTracksFree() == 1 ) { + ltrace(200) << "Potential right intrication with other perpandicular." << endl; + if ( isegment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap() ) { + rightIntrication = true; + rightAxisHint = isegment3->getAxis(); + } + } + } + } else { + // DbU::Unit axisHint + // = (event3->getAxisHint() - toFree.getVMin() < toFree.getVMax() - event3->getAxisHint()) + // ? (toFree.getVMin() - DbU::lambda(1.0)) : (toFree.getVMax() + DbU::lambda(1.0)); + Manipulator(*isegment3,_S).ripup + ( track->getAxis() + , SegmentAction::OtherRipup + | SegmentAction::EventLevel3 + //| SegmentAction::AxisHint, axisHint + ); + } + } + } + } + + if ( success ) { + _S.setState ( State::OtherRipup ); + _S.addAction ( _segment, SegmentAction::SelfInsert /*| SegmentAction::EventLevel3*/ ); + _segment->setAxis ( _S.getCost(itrack).getTrack()->getAxis() ); + + unsigned int flags = 0; + if ( rightIntrication ) flags |= RightAxisHint; + if ( leftIntrication ) flags |= LeftAxisHint; + if ( flags ) + Manipulator(_segment,_S).shrinkToTrack(itrack,flags,leftAxisHint,rightAxisHint); + } else + _S.clearActions (); + + return success; + } + + + bool Manipulator::forceToTrack ( size_t itrack ) + { + Track* track = _S.getTrack(itrack); + size_t begin = _S.getBegin(itrack); + size_t end = _S.getEnd (itrack); + Net* ownerNet = _segment->getNet(); + Interval toFree (_segment->getCanonicalInterval()); + Net* ripupNet = NULL; + set canonicals; + bool success = true; + + ltrace(200) << "Manipulator::forceToTrack() - " << toFree << endl; + + for ( size_t i = begin ; success && (i < end) ; i++ ) { + TrackElement* segment2 = track->getSegment(i); + + ltrace(200) << "* Looking // " << segment2 << endl; + + if ( segment2->getNet() == ownerNet ) continue; + if ( !toFree.intersect(segment2->getCanonicalInterval()) ) continue; + if ( segment2->base()->isFixed() ) { + success = false; + continue; + } + //if ( (segment2->getNet() != ripupNet ) + // && !toFree.intersect(segment2->getCanonicalInterval()) ) continue; + ripupNet = segment2->getNet(); + + DataNegociate* data2 = segment2->getDataNegociate(); + if ( !data2 ) { + ltrace(200) << "No DataNegociate, ignoring." << endl; + continue; + } + + if ( data2->getGCellOrder() < Session::getOrder() ) { + // Interval relax. + success = Manipulator(segment2,_S).relax ( toFree ); + } else { + ltrace(200) << "- Forced ripup " << segment2 << endl; + Manipulator(segment2,_S).ripup ( toFree, SegmentAction::OtherRipup ); + + canonicals.clear (); + forEach ( TrackElement*, isegment3 + , segment2->getCollapsedPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) { + DataNegociate* data3 = isegment3->getDataNegociate(); + if ( !data3 ) continue; + + RoutingEvent* event3 = data3->getRoutingEvent(); + if ( !event3 ) continue; + + _S.addAction ( *isegment3, SegmentAction::OtherRipup ); + } + } + } + + if ( success ) { + _S.setState ( State::OtherRipup ); + _S.addAction ( _segment, SegmentAction::SelfInsert ); + _segment->setAxis ( _S.getCost(itrack).getTrack()->getAxis() ); + } + + return true; + } + + + bool Manipulator::shrinkToTrack ( size_t i, unsigned int flags, DbU::Unit leftAxisHint, DbU::Unit rightAxisHint ) + { + Track* track = _S.getTrack(i); + size_t begin = _S.getBegin(i); + size_t end = _S.getEnd (i); + Net* ownerNet = _segment->getNet(); + set canonicals; + bool success = true; + DbU::Unit leftExtend = _segment->getSourceU() + Session::getExtensionCap(); + DbU::Unit rightExtend = _segment->getSourceU() - Session::getExtensionCap(); + + ltrace(200) << "Manipulator::shrinkToTrack()" << endl; + + if ( _segment->isLocal() ) return false; + //Interval shrunkFree ( _segment->getSourceConstraints().getVMax() + // , _segment->getTargetConstraints().getVMin() ); + Interval shrunkFree = _segment->base()->getMinSpanU(); + + ltrace(200) << "* " << shrunkFree << endl; + + for ( size_t i = begin ; success && (i < end) ; i++ ) { + TrackElement* segment2 = track->getSegment(i); + + ltrace(200) << "* Looking // " << segment2 << endl; + + if ( segment2->getNet() == ownerNet ) continue; + if ( segment2->isFixed() ) { success = false; continue; } + if ( !shrunkFree.intersect(segment2->getCanonicalInterval()) ) continue; + + success = false; + } + + if ( success ) { + set perpandiculars; + set::iterator iperpand; + + DbU::Unit axisHint; + if ( not (flags & LeftAxisHint ) ) leftAxisHint = shrunkFree.getCenter(); + if ( not (flags & RightAxisHint) ) rightAxisHint = shrunkFree.getCenter(); + + _segment->getPerpandicularsBound ( perpandiculars ); + for ( iperpand = perpandiculars.begin() ; iperpand != perpandiculars.end() ; iperpand++ ) { + DataNegociate* data2 = (*iperpand)->getDataNegociate(); + if ( data2 && (data2->getGCellOrder() >= Session::getOrder()) ) { + + ltrace(200) << "| perpandicular bound:" << *iperpand << endl; + success = Manipulator(*iperpand,_S).ripup ( track->getAxis(), SegmentAction::SelfRipupAndAxisHint ); + if ( success ) { + if ( (*iperpand)->getAxis() == leftExtend ) axisHint = leftAxisHint; + else if ( (*iperpand)->getAxis() == rightExtend ) axisHint = rightAxisHint; + else { + cinfo << "[INFO] Bound Axis is neither left nor right\n " + << (*iperpand) << endl; + axisHint = shrunkFree.getCenter(); + } + + _S.getActions()[_S.getActions().size()-1].setAxisHint ( axisHint ); + } + } + } + + _S.addAction ( _segment, SegmentAction::SelfInsert ); + _S.setState ( State::OtherRipup ); + + ltrace(200) << "Successful shrinkToTrack." << endl; + return true; + } + + return false; + } + + + bool Manipulator::desalignate () + { + ltrace(200) << "Manipulator::desalignate() " << _segment << endl; + + if ( _segment->isFixed () ) return false; + if ( !_segment->canDesalignate() ) return false; + + _segment->desalignate (); + return true; + } + + + bool Manipulator::slacken () + { + ltrace(200) << "Manipulator::slacken() " << _segment << endl; + + if ( _segment->isFixed () ) return false; + if ( !_segment->canSlacken() ) return false; + + _segment->slacken (); + return true; + } + + + bool Manipulator::goOutsideGCell () + { + ltrace(200) << "Manipulator::goOutsideGCell() " << _segment << endl; + return false; + +#if 0 + if ( _segment->isFixed () ) return false; + if ( !_segment->canGoOutsideGCell() ) return false; + + GCell* sourceGCell = _segment->getGCell(); + GCell* leftGCell = NULL; + GCell* rightGCell = NULL; + Interval uside; + bool goLeft = false; + bool goRight = false; + + if ( _segment->isHorizontal() ) { + uside = sourceGCell->getUSide ( Constant::Vertical, false ); + leftGCell = sourceGCell->getDown(); + rightGCell = sourceGCell->getUp (); + } else { + uside = sourceGCell->getUSide ( Constant::Horizontal, false ); + leftGCell = sourceGCell->getLeft (); + rightGCell = sourceGCell->getRight(); + } + + Interval constraints; + _segment->base()->getConstraints ( constraints ); + + // Ugly: Must use the right compensator for VMax. + if ( rightGCell and (uside.getVMax() <= constraints.getVMax())+DbU::lambda(1.0) ) goRight = true; + if ( leftGCell and (uside.getVMin() >= constraints.getVMin()) ) goLeft = true; + + if ( goRight and goLeft ) { + DbU::Unit distanceToLeft = _segment->getAxis() - uside.getVMin(); + DbU::Unit distanceToRight = uside.getVMax() - _segment->getAxis(); + if ( distanceToLeft < distanceToRight ) goRight = false; + else goLeft = false; + } + + _segment->moveAside ( goLeft ); + + return true; +#endif + } + + + bool Manipulator::ripple () + { + ltrace(200) << "Manipulator::ripple() from " << _segment << endl; + + //if ( not _segment->canRipple() ) return false; + if ( not _segment->isLocal() ) return false; + + Net* net = _segment->getNet(); + Interval uside = _segment->getGCell()->getUSide + ( Constant::perpandicular(_segment->getDirection()), false ); + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_segment->getLayer()); + + ltracein(200); + forEach ( Track*, itrack, Tracks_Range::get(plane,uside)) { + size_t begin; + size_t end; + + itrack->getOverlapBounds ( _segment->getCanonicalInterval(), begin, end ); + for ( ; begin < end ; begin++ ) { + TrackElement* other = itrack->getSegment(begin); + ltrace(200) << "| " << other << endl; + + if ( other->getNet() == net ) continue; + if ( not other->canRipple() ) continue; + + DataNegociate* otherData = other->getDataNegociate(); + if ( not otherData ) continue; + if ( otherData->getGCellOrder() < Session::getOrder() ) continue; + + DbU::Unit shiftedAxisHint; + RoutingEvent* otherEvent = otherData->getRoutingEvent(); + + if ( other->getAxis() < _segment->getAxis() ) { + // Ugly: routing pitch. + shiftedAxisHint = otherEvent->getAxisHint() - DbU::lambda(5.0); + if ( shiftedAxisHint < uside.getVMin() ) + shiftedAxisHint = uside.getVMin(); + } else { + // Ugly: routing pitch. + shiftedAxisHint = otherEvent->getAxisHint() + DbU::lambda(5.0); + if ( shiftedAxisHint > uside.getVMax() ) + shiftedAxisHint = uside.getVMax(); + } + + otherEvent->setAxisHint ( shiftedAxisHint ); + _S.addAction ( other, SegmentAction::OtherRipup ); + } + } + ltraceout(200); + + return true; + } + + + bool Manipulator::pivotUp () + { + ltrace(200) << "Manipulator::pivotUp() " << _segment << endl; + + if ( _segment->isFixed () ) return false; + if ( not _segment->canMoveUp() ) return false; + + _segment->moveUp (); + return true; + } + + + bool Manipulator::moveUp () + { + ltrace(200) << "Manipulator::moveUp() " << _segment << endl; + + if ( _segment->isFixed () ) return false; + if ( _segment->isLocal() and not _segment->canPivotUp() ) return false; + if ( not _segment->canMoveUp() ) return false; + +#if DISABLED + ltrace(200) << "| Repack Tracks: " << endl; + + Interval constraints; + Interval overlap = _segment->getCanonicalInterval(); + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_segment->getLayer()); + size_t begin; + size_t end; + TrackElement* other; + + constraints = _segment->getGCell()->getUSide(Constant::perpandicular(_segment->getDirection()),true); + forEach ( Track*, itrack, Tracks_Range::get(plane,constraints)) { + itrack->getOverlapBounds ( overlap, begin, end ); + for ( ; (begin < end) ; begin++ ) { + other = itrack->getSegment(begin); + + if ( other->isGlobal() ) continue; + if ( other->getDataNegociate() + and (other->getDataNegociate()->getGCellOrder() != Session::getOrder()) ) continue; + + ltrace(200) << " | Ripup for repack: " << begin << " " << other << endl; + _S.addAction ( other, SegmentAction::OtherRipup ); + } + } +#endif + + _segment->moveUp (); + return true; + } + + + bool Manipulator::makeDogLeg () + { + ltrace(200) << "Manipulator::makeDogLeg() " << _segment << endl; + + if ( _segment->isFixed() ) return false; + if ( !_segment->isLocal() ) return false; + + if ( _S.getCosts().size() ) { + Track* track = _S.getTrack(0); + size_t begin = _S.getBegin(0); + size_t end = _S.getEnd (0); + Net* ownerNet = _segment->getNet(); + Interval toFree (_segment->getCanonicalInterval()); + Interval overlap; + + for ( size_t i = begin ; i < end ; i++ ) { + TrackElement* segment2 = track->getSegment(i); + + ltrace(200) << "* Looking // " << segment2 << endl; + + if ( segment2->getNet() == ownerNet ) continue; + if ( !toFree.intersect(segment2->getCanonicalInterval()) ) continue; + + if ( overlap.isEmpty() ) + overlap = segment2->getCanonicalInterval(); + else + overlap.merge ( segment2->getCanonicalInterval() ); + } + + if ( !overlap.isEmpty() && makeDogLeg(overlap) ) return true; + } + + if ( !_segment->canDogLeg() ) return false; + _segment->makeDogLeg (); + + return true; + } + + + bool Manipulator::makeDogLeg ( Interval overlap ) + { + ltrace(200) << "Manipulator::makeDogLeg(Interval) " << _segment << endl; + ltrace(200) << overlap << endl; + + //if ( !_segment->isLocal() || !_segment->canDogLeg() ) return false; + + if ( _segment->isFixed () ) return false; + if ( !_segment->canDogLeg(overlap) ) return false; + + bool pushLeft; + bool isTerminal = _segment->isTerminal(); + TrackElement* dogleg = _segment->makeDogLeg(overlap,pushLeft); + if ( dogleg ) { + ltrace(200) << "Manipulator::makeDogLeg(Interval) - Push dogleg to the " + << ((pushLeft)?"left":"right") << endl; + if ( isTerminal ) { + AutoContact* contact = (pushLeft) ? _segment->base()->getAutoSource() + : _segment->base()->getAutoTarget(); + DbU::Unit axisHint = (_segment->isHorizontal()) ? contact->getX() : contact->getY(); + RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent(); + if ( event ) { + event->setAxisHint ( axisHint ); + event->setForcedToHint ( true ); + ltrace(200) << "Forced to axis hint @" << DbU::getValueString(axisHint) << endl; + } + } + return true; + } + + return false; + } + + + bool Manipulator::minimize () + { + ltrace(200) << "Manipulator::minimize() " << _segment << endl; + + if ( _segment->isFixed() ) return false; + if ( !_event->canMinimize() ) return false; + + DbU::Unit minSpan = DbU::Max; + DbU::Unit maxSpan = DbU::Min; + Interval punctualSpan ( false ); + + if ( _segment->base()->getAutoSource()->getAnchor() ) { + ltrace(200) << " | " << _segment->base()->getAutoSource() << endl; + Interval constraints ( _segment->base()->getAutoSource()->getUConstraints + (Constant::perpandicular(_segment->getDirection())) ); + ltrace(200) << " | Constraints: " << constraints << endl; + + minSpan = min ( minSpan, constraints.getVMax() ); + maxSpan = max ( maxSpan, constraints.getVMin() ); + punctualSpan.intersection ( constraints ); + } + + if ( _segment->base()->getAutoTarget()->getAnchor() ) { + ltrace(200) << " | " << _segment->base()->getAutoTarget() << endl; + Interval constraints ( _segment->base()->getAutoTarget()->getUConstraints + (Constant::perpandicular(_segment->getDirection())) ); + ltrace(200) << " | Constraints: " << constraints << endl; + + minSpan = min ( minSpan, constraints.getVMax() ); + maxSpan = max ( maxSpan, constraints.getVMin() ); + punctualSpan.intersection ( constraints ); + } + + const vector& perpandiculars = _event->getPerpandiculars(); + for ( size_t i=0 ; igetDataNegociate(); + if ( !data2 ) continue; + + ltrace(200) << " | " << perpandiculars[i] << endl; + if ( data2->getGCellOrder() < Session::getOrder() ) { + ltrace(200) << "Reject: bad order." << endl; + continue; + } + + RoutingEvent* event2 = data2->getRoutingEvent(); + if ( !event2 ) continue; + + ltrace(200) << " | Constraints: " << event2->getConstraints() << endl; + + minSpan = min ( minSpan, event2->getConstraints().getVMax() ); + maxSpan = max ( maxSpan, event2->getConstraints().getVMin() ); + punctualSpan.intersection ( event2->getConstraints() ); + } + if ( minSpan > maxSpan ) swap ( minSpan, maxSpan ); + + ltrace(200) << "punctualSpan: " << punctualSpan + << " min/max span: [" << DbU::getValueString(minSpan) + << ":" << DbU::getValueString(minSpan) << "]" << endl; + + vector holes; + for ( size_t itrack=0 ; itrack<_S.getCosts().size() ; itrack++ ) { + size_t begin = _S.getBegin(itrack); + size_t end = _S.getEnd (itrack); + Track* track = _S.getTrack(itrack); + + if ( end < track->getSize() ) end++; + + ltrace(200) << "Looking for holes in " << _S.getCost(itrack) << endl; + + TrackElement* otherPrevious = NULL; + // ToDo: Manage disjoint but subsequent segment of a Net. + // (currently, that hole will not be found). + for ( ; begin < end ; begin++ ) { + TrackElement* otherSegment = track->getSegment(begin); + if ( otherSegment->getNet() == _segment->getNet() ) continue; + if ( !otherPrevious ) { + holes.push_back ( Interval(track->getMin() + ,otherSegment->getSourceU()) ); + ltrace(200) << "| First hole: " << holes.back() << " " << otherSegment << endl; + } else { + if ( otherSegment->getNet() == otherPrevious->getNet() ) continue; + + holes.push_back ( Interval(otherPrevious->getTargetU() + ,otherSegment ->getSourceU()) ); + ltrace(200) << "| Found hole: " << holes.back() + << " " << otherPrevious << " <-> " << " " << otherSegment << endl; + } + otherPrevious = otherSegment; + } + } + + if ( holes.empty() ) { + ltrace(200) << "No holes found to minimize into." << endl; + return false; + } + + Interval currentSpan = _segment->getCanonicalInterval(); + Interval biggestHole; + for ( size_t i=0 ; i currentSpan.getIntersection(biggestHole).getSize() ) + biggestHole = holes[i]; + } + + if ( !punctualSpan.isEmpty() ) { + bool success = false; + + if ( biggestHole.intersect(punctualSpan) ) { + ltrace(200) << "Go as punctual into biggest hole: " << biggestHole << endl; + success = true; + } else { + for ( size_t i=0 ; igetDataNegociate(); + if ( !data2 ) continue; + + ltrace(200) << " | " << perpandiculars[i] << endl; + if ( data2->getGCellOrder() < Session::getOrder() ) continue; + + RoutingEvent* event2 = data2->getRoutingEvent(); + if ( !event2 ) continue; + + _S.addAction ( perpandiculars[i], SegmentAction::SelfRipupAndAxisHint, axisHint ); + } + + _event->setMinimized (); + + return true; + } + + + bool Manipulator::relax ( size_t i ) + { + ltrace(200) << "Manipulator::relax() " << _segment << endl; + + if ( /* _segment->base()->isGlobal() + ||*/ _segment->isFixed() + || ( _segment->getDogLegLevel() > 0 ) + || ( _segment->getLength() < DbU::lambda(10.0) ) + || !_segment->canDogLegAt(_segment->getGCell()) ) + return false; + + TrackElement* perpandicular + = _segment->makeDogLeg ( Session::lookup(_segment->base()->getAutoSource()->getGCell()) ); + + if ( perpandicular ) { + RoutingEvent* event = perpandicular->getDataNegociate()->getRoutingEvent(); + if ( event ) { + TrackCost& cost = _S.getCost(i); + Interval optimal = cost.getInterval(); + event->setOptimalAxis ( optimal.inflate( - Session::getExtensionCap() ) ); + } else { + cerr << Bug("New dog leg without active RoutingEvent.\n " + "%s",getString(perpandicular).c_str()) << endl; + } + } + + return true; + } + + + void Manipulator::reprocessPerpandiculars () + { + if ( _event->getAxisHistory() == _event->getAxisHint() ) return; + + bool moveLeft = (_event->getAxisHistory() > _event->getAxisHint()); + + const vector& perpandiculars = _event->getPerpandiculars(); + for ( size_t iperpand=0 ; iperpandgetDataNegociate(); + + if ( perpandicular->isFixed() ) continue; + if ( not data or (data->getGCellOrder() != Session::getOrder()) ) continue; + if ( not perpandicular->getTrack() ) continue; + if ( not Manipulator(perpandicular,_S).canRipup() + or (data->getState() >= DataNegociate::MaximumSlack) ) continue; + + // Ugly: ExtensionCap usage. + if ( moveLeft ) { + if ( perpandicular->getTargetU()-Session::getExtensionCap() == _event->getAxisHistory() ) + _S.addAction ( perpandicular, SegmentAction::OtherPacking ); + } else { + if ( perpandicular->getSourceU()+Session::getExtensionCap() == _event->getAxisHistory() ) + _S.addAction ( perpandicular, SegmentAction::OtherPacking ); + } + } + } + + +// ------------------------------------------------------------------- +// Local Functions. + + +} // End of anonymous namespace. + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::setw; + using std::min; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::DebugSession; + using Hurricane::Bug; + using Hurricane::ForEachIterator; + using Hurricane::Net; + using Hurricane::Layer; + + +// ------------------------------------------------------------------- +// Class : "RoutingEvent::Compare". + + + bool RoutingEvent::Compare::operator() ( const RoutingEvent* lhs, const RoutingEvent* rhs ) const + { + //if ( !lhs->isValid() ) const_cast(lhs)->revalidate (); + //if ( !rhs->isValid() ) const_cast(rhs)->revalidate (); + + //unsigned int lhsDepth = Session::getRoutingGauge()->getLayerDepth(lhs->getSegment()->getLayer()); + //unsigned int rhsDepth = Session::getRoutingGauge()->getLayerDepth(rhs->getSegment()->getLayer()); + + //if ( lhsDepth > rhsDepth ) return true; + //if ( lhsDepth < rhsDepth ) return false; + + if ( lhs == rhs ) return false; + + return RoutingEvent::Key::Compare() ( lhs->getKey(), rhs->getKey() ); + + // if ( lhs->getEventLevel() < rhs->getEventLevel() ) return true; + // if ( lhs->getEventLevel() > rhs->getEventLevel() ) return false; + + // // Uses static ordering. + // if ( lhs->getTracksNb() < rhs->getTracksNb() ) return false; + // if ( lhs->getTracksNb() > rhs->getTracksNb() ) return true; + + // if ( lhs->getPriority() < rhs->getPriority() ) return false; + // if ( lhs->getPriority() > rhs->getPriority() ) return true; + + // //return false; + // // For debugging purpose only: ensure a reproductible sort. Could be removed. + // //bool segmentCompare = TrackElement::CompareByPosition() ( lhs->getSegment(), rhs->getSegment() ); + + // //return (segmentCompare or ((void*)lhs < (void*)rhs)); + // return ((void*)lhs < (void*)rhs); + } + + +// ------------------------------------------------------------------- +// Class : "RoutingEvent::Key". + + + bool RoutingEvent::Key::Compare::operator() ( const RoutingEvent::Key& lhs, const RoutingEvent::Key& rhs ) const + { + //if ( lhs._ring xor rhs._ring ) return lhs._ring; + + if ( lhs._eventLevel < rhs._eventLevel ) return true; + if ( lhs._eventLevel > rhs._eventLevel ) return false; + + if ( lhs._canRipple xor rhs._canRipple ) return rhs._canRipple; + //if ( lhs._slackenStrap xor rhs._slackenStrap ) return lhs._slackenStrap; + + // Uses static ordering. + //if ( lhs._tracksNb < rhs._tracksNb ) return false; + //if ( lhs._tracksNb > rhs._tracksNb ) return true; + + if ( lhs._priority < rhs._priority ) return false; + if ( lhs._priority > rhs._priority ) return true; + + if ( lhs._length < rhs._length ) return true; + if ( lhs._length > rhs._length ) return false; + + if ( lhs._isHorizontal xor rhs._isHorizontal ) return rhs._isHorizontal; + + if ( lhs._axis > rhs._axis ) return true; + if ( lhs._axis < rhs._axis ) return false; + + if ( lhs._sourceU > rhs._sourceU ) return true; + if ( lhs._sourceU < rhs._sourceU ) return false; + + if ( lhs._net->getName() != rhs._net->getName() ) + return lhs._net->getName() < rhs._net->getName(); + + return lhs._id < rhs._id; + } + + + RoutingEvent::Key::Key ( const RoutingEvent* event ) + : _slackenStrap(event->getSegment()->isSlackenStrap()) + , _isHorizontal(event->getSegment()->isHorizontal()) + , _canRipple (event->getSegment()->canRipple()) + , _tracksNb (event->getTracksNb()) + , _priority (event->getPriority()) + , _eventLevel (event->getEventLevel()) + , _length (event->getSegment()->getLength()) + , _axis (event->getSegment()->getAxis()) + , _sourceU (event->getSegment()->getSourceU()) + , _net (event->getSegment()->getNet()) + , _id (event->getSegment()->getId()) + { } + + + void RoutingEvent::Key::update ( const RoutingEvent* event ) + { + if ( !event ) return; + + _slackenStrap = event->getSegment()->isSlackenStrap(); + _canRipple = event->getSegment()->canRipple(); + _tracksNb = event->getTracksNb(); + _priority = event->getPriority(); + _eventLevel = event->getEventLevel(); + _length = event->getSegment()->getLength(); + _axis = event->getSegment()->getAxis(); + _sourceU = event->getSegment()->getSourceU(); + _id = event->getSegment()->getId(); + } + + +// ------------------------------------------------------------------- +// Class : "RoutingEvent". + + + size_t RoutingEvent::_allocateds = 0; + size_t RoutingEvent::_processeds = 0; + size_t RoutingEvent::_cloneds = 0; + + + size_t RoutingEvent::getAllocateds () { return _allocateds; } + size_t RoutingEvent::getProcesseds () { return _processeds; } + size_t RoutingEvent::getCloneds () { return _cloneds; } + void RoutingEvent::resetProcesseds () { _processeds = 0; } + + + RoutingEvent::RoutingEvent ( TrackElement* segment, unsigned int mode ) + : _cloned (false) + , _processed (false) + , _disabled (false) + , _valid (false) + , _validConstraints (false) + , _validPerpandiculars (false) + , _canHandleConstraints(false) + , _minimized (false) + , _forceToHint (false) + , _segment (segment) + , _axisHistory (segment->getAxis()) + , _axisHint (segment->getAxis()) + , _optimalAxis (false) + , _constraints () + , _optimal () + , _perpandicular (false) + , _shearGCell (NULL) + , _tracksNb (0) + , _tracksFree (0) + , _insertState (0) + , _mode (mode) + , _rippleState (0) + , _eventLevel (0) + , _priority (0.0) + , _perpandiculars () + , _key (this) + { + DataNegociate* data = _segment->getDataNegociate(); + if ( data ) + data->setRoutingEvent ( this ); + + // Interval optimal; + // _segment->base()->getOptimal ( optimal ); + // _axisHint = optimal.getCenter(); + + invalidate ( true ); + + ltrace(180) << "create: " << (void*)this << ":" << this << endl; + ltrace(200) << "Initial setAxisHint @" << DbU::getValueString(_axisHint) << endl; + + if ( _segment->getTrack() ) { + cerr << Bug("RoutingEvent::create() - TrackElement is already inserted in a Track." + "\n %s." + ,getString(_segment).c_str() + ) << endl; + } + } + + + RoutingEvent* RoutingEvent::create ( TrackElement* segment, unsigned int mode ) + { + RoutingEvent* event = new RoutingEvent ( segment, mode ); + ++_allocateds; + + return event; + } + + + RoutingEvent* RoutingEvent::clone () const + { + _cloned = true; + + RoutingEvent* clone = new RoutingEvent ( *this ); + ++_allocateds; + ++_cloneds; + + clone->_cloned = false; + clone->_disabled = false; + clone->_eventLevel = 0; + + ltrace(200) << "RoutingEvent::clone() " << (void*)clone << ":" << clone + << " (from: " << (void*)this << ")" << endl; + + return clone; + } + + + RoutingEvent::~RoutingEvent () + { + ltrace(180) << "~RoutingEvent() " << (void*)this << endl; + + DataNegociate* data = _segment->getDataNegociate(); + if ( data and ( data->getRoutingEvent() == this ) ) + data->setRoutingEvent ( NULL ); + } + + + void RoutingEvent::destroy () + { + ltrace(180) << "RoutingEvent::destroy() " << (void*)this << ":" << this << endl; + if ( _allocateds > 0 ) --_allocateds; + + delete this; + } + + + bool RoutingEvent::isUnimplemented () const + { return getState() == DataNegociate::Unimplemented; } + + + unsigned int RoutingEvent::getState () const + { + DataNegociate* data = _segment->getDataNegociate(); + if ( not data ) return 0; + + return data->getState(); + } + + + void RoutingEvent::setState ( unsigned int state ) + { + DataNegociate* data = _segment->getDataNegociate(); + if ( not data ) return; + + data->setState ( state ); + } + + + void RoutingEvent::setEventLevel ( unsigned int level ) + { _eventLevel = level; } + + + void RoutingEvent::setAxisHint ( DbU::Unit axis ) + { + ltrace(200) << "setAxisHint @" << DbU::getValueString(axis) << " " << _segment << endl; + _axisHint = axis; + } + + + long RoutingEvent::getAxisWeight ( DbU::Unit axis ) const + { return abs(axis - _axisHint); } + + + RoutingEvent* RoutingEvent::reschedule ( RoutingEventQueue& queue, unsigned int eventLevel ) + { + RoutingEvent* active = _segment->getDataNegociate()->getRoutingEvent(); + if ( active != this ) + return active->reschedule ( queue, eventLevel ); + + RoutingEvent* fork = NULL; + + if ( isUnimplemented() ) { + ltrace(200) << "Reschedule: cancelled (Unimplemented) " + << (void*)this << " -> " << (void*)fork << ":" << fork << endl; + return NULL; + } + + if ( not isProcessed() ) { + fork = this; + ltrace(200) << "Reschedule/Self: " + << (void*)this << " -> " << (void*)fork << ":" << fork << endl; + } else { + fork = clone(); + fork->_processed = false; + + _segment->getDataNegociate()->setRoutingEvent ( fork ); + + ltrace(200) << "Reschedule/Fork: " + << (void*)this << " -> " << (void*)fork << ":" << fork << endl; + } + if ( fork->_eventLevel < eventLevel ) + fork->_eventLevel = eventLevel; + queue.repush ( fork ); + + return fork; + } + + + void RoutingEvent::setSegment ( TrackElement* segment ) + { + if ( _segment ) + _segment->getDataNegociate()->setRoutingEvent ( NULL ); + _segment = segment; + _segment->getDataNegociate()->setRoutingEvent ( this ); + + invalidate ( true, true ); + } + + + void RoutingEvent::process ( RoutingEventQueue& queue, RoutingEventHistory& history ) + { + DebugSession::open ( _segment->getNet(), 200 ); + +#if defined(CHECK_DETERMINISM) + cerr << "Order: " + << getProcesseds() + << "," << getEventLevel() + << "," << setw(6) << getPriority() + << " " << setw(6) << DbU::getValueString(_segment->getLength()) + << " " << _segment->isHorizontal() + << " " << setw(6) << DbU::getValueString(_segment->getAxis()) + << " " << setw(6) << DbU::getValueString(_segment->getSourceU()) + << ": " << _segment << endl; +#endif + _processeds++; + + ltrace(210) << "Event:" << _processeds << " " << this << endl; + ltracein(200); + ltrace(200) << "State: *before* " + << DataNegociate::getStateString(_segment->getDataNegociate()) + << " ripup:" << _segment->getDataNegociate()->getRipupCount() + << endl; + ltrace(149) << "Level: " << getEventLevel() + << ", area: " << _segment->getArea() << endl; + + _preCheck(_segment); + _eventLevel = 0; + + if ( _mode < PostPack ) history.push ( this ); + + if ( isProcessed() || isDisabled() ) { + ltrace(200) << "Already processed or disabled." << endl; + } else { + setProcessed (); + + switch ( _mode ) { + case Negociate: _processNegociate ( queue, history ); break; + case Pack: + case PostPack: _processPacking ( queue, history ); break; + default: + cerr << Bug("RoutingEvent::process() - Unknown mode value:%d.",_mode) << endl; + break; + } + } + +#if defined(CHECK_DATABASE) + Session::getKiteEngine()->_check ( _segment->getNet() ); +#endif + ltraceout(200); + + queue.repushInvalidateds (); + Session::revalidate (); + queue.commit (); + + _postCheck(_segment); + DebugSession::close (); + + if ( Session::getKiteEngine()->getPostEventCb() != NULL ) + Session::getKiteEngine()->getPostEventCb() (); + } + + + void RoutingEvent::_processNegociate ( RoutingEventQueue& queue, RoutingEventHistory& history ) + { + ltrace(200) << "* Mode:Negociation." << endl; + + State S ( this, queue, history ); + + if ( S.getHistory().looping() ) { + cerr << Error("RoutingEvent::process() - Simple Loop detection triggered.") << endl; + + setState ( DataNegociate::Unimplemented ); + S.getHistory().dump ( cerr, 40 ); + return; + } + + if ( S.getState() == State::MissingData ) { + cerr << Error("RoutingEvent::process() - Missing datas.") << endl; + return; + } + + ltracein(200); + + S.getData()->incRipupCount (); + + size_t itrack = 0; + for ( itrack = 0 ; itrack < S.getCosts().size() ; itrack++ ) + ltrace(200) << "| " << S.getCost(itrack) << endl; + + itrack = 0; + if ( isForcedToHint() ) { + // Try to honor the forced axis hint. + bool hintFound = false; + for ( ; itrack < S.getCosts().size() ; itrack++ ) { + if ( S.getCost(itrack).getTrack()->getAxis() == _axisHint ) { + hintFound = true; + break; + } + } + if ( !hintFound ) itrack = 0; + ltrace(200) << "Forcing to hint Track: " << itrack << endl; + } + + if ( Manipulator(_segment,S).canRipup() ) { + if ( S.getCosts().size() and S.getCost(itrack).isFree() ) { + // Track is free: insertion. + ltrace(200) << "Insert in free space " << this << endl; + resetInsertState (); + + _axisHistory = _segment->getAxis(); + _eventLevel = 0; + Session::addInsertEvent ( _segment, S.getCost(itrack).getTrack() ); + Manipulator(_segment,S).reprocessPerpandiculars (); + S.setState ( State::SelfInserted ); + } else { + // Do ripup. + if ( S.getState() == State::EmptyTrackList ) { + Manipulator(_segment,S).ripupPerpandiculars (); + } else { + for ( itrack=0 ; itrackgetAxis()) + << " " << (void*)this << ":" << this << endl; + } + + ltraceout(200); + } + + + void RoutingEvent::_processPacking ( RoutingEventQueue& queue, RoutingEventHistory& history ) + { + ltrace(200) << "* Mode:Packing." << endl; + + if ( _segment->getTrack() != NULL ) { + ltrace(200) << "* Cancel: already in Track." << endl; + return; + } + // if ( !_canHandleConstraints ) { + // ltrace(200) << "* Cancel: cannot handle constraints." << endl; + // return; + // } + + State S ( this, queue, history ); + if ( S.getState() == State::MissingData ) return; + if ( S.getState() == State::EmptyTrackList ) return; + + ltracein(200); + for ( size_t i = 0 ; i < S.getCosts().size() ; i++ ) + ltrace(200) << "| " << S.getCost(i) << endl; + ltraceout(200); + + if ( S.getCosts().size() and S.getCost(0).isFree() ) { + ltrace(200) << "Insert in free space." << endl; + Session::addInsertEvent ( _segment, S.getCost(0).getTrack() ); + S.setState ( State::SelfInserted ); + } else { + ltrace(200) << "Packing failed." << endl; + if ( _mode == Pack ) { + _mode = Negociate; + S.addAction ( _segment, SegmentAction::SelfInsert ); + S.doActions (); + } + } + } + + + void RoutingEvent::revalidate ( bool force ) + { + if ( _valid and not force ) return; + + DebugSession::open ( _segment->getNet(), 200 ); + + ltrace(200) << "RoutingEvent::revalidate() - " << (void*)this << ":" << this << endl; + ltracein(200); + ltrace(200) << "axisHint:" << DbU::getValueString(_axisHint) << endl; + + _canHandleConstraints = true; + if ( /*!_validConstraints*/ true ) { + _segment->base()->getConstraints ( _constraints ); + _segment->base()->getOptimal ( _optimal ); + + ltrace(200) << "| Raw Track Constraint: " << _constraints << endl; + + _validConstraints = true; + } + + if ( !_validPerpandiculars ) { + TrackElement* perpandicular; + Interval canonical; + + _perpandiculars.clear (); + forEach ( AutoSegment*, isegment, _segment->base()->getCollapsedPerpandiculars() ) { + ltrace(200) << "| perpandicular " << *isegment << endl; + perpandicular = Session::lookup ( isegment->getCanonical(canonical)->base() ); + if ( !perpandicular ) continue; + + _perpandiculars.push_back ( perpandicular ); + } + _validPerpandiculars = true; + + if ( not _segment->isTerminal() and (_perpandiculars.size() < 2) ) + cerr << Bug("Less than two perpandiculars on %s.",getString(_segment).c_str()) << endl; + } + + ltrace(200) << "| Track Constraint: " << _constraints << endl; + + _perpandicular = _constraints; + DataNegociate* dataPerpandicular; + + for ( size_t i=0 ; i<_perpandiculars.size() ; i++ ) { + dataPerpandicular = _perpandiculars[i]->getDataNegociate(); + if ( !dataPerpandicular ) { + ltrace(200) << "| No data " << _perpandiculars[i] << endl; + continue; + } + + if ( _perpandiculars[i]->getTrack() ) { + Interval trackFree = _perpandiculars[i]->getFreeInterval( false ); + ltrace(200) << "| From " << _perpandiculars[i] << endl; + ltrace(200) << "| Track Perpandicular Free: " << trackFree << endl; + + _perpandicular.intersection ( trackFree ); + if ( dataPerpandicular->getGCellOrder() < Session::getOrder() ) + _constraints.intersection ( trackFree ); + } else { + ltrace(200) << "| Not in any track " << _perpandiculars[i] << endl; + } + } + _tracksNb = 0; + + ltrace(200) << "| Perpandicular Free: " << _perpandicular << endl; + if ( !_perpandicular.isEmpty() ) { + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_segment->getLayer()); + Track* track = plane->getTrackByPosition(_perpandicular.getVMin()); + + if ( track && (track->getAxis() < _perpandicular.getVMin()) ) track = track->getNext(); + for ( ; track && (track->getAxis() <= _perpandicular.getVMax()) + ; track = track->getNext(), _tracksNb++ ); + } + if ( not _tracksNb ) { + ltrace(200) << "| Reverting to pure constraints." << endl; + RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_segment->getLayer()); + Track* track = plane->getTrackByPosition(_constraints.getVMin()); + + if ( track && (track->getAxis() < _constraints.getVMin()) ) track = track->getNext(); + for ( ; track && (track->getAxis() <= _constraints.getVMax()) + ; track = track->getNext(), _tracksNb++ ); + + _canHandleConstraints = false; + } + if ( not _tracksNb ) { + ltrace(200) << "| Pure constraints are too tight." << endl; + //_segment->base()->getConstraints ( _constraints ); + _canHandleConstraints = false; + } + + _priority + = (DbU::getLambda(_segment->getLength()) + 1.0) + * (DbU::getLambda(_segment->base()->getSlack()) + 1.0); + //_priority = (DbU::getLambda(_segment->getLength()) + 1.0) * (float)(_tracksNb+1); + //_priority = (float)_segment->getArea(); + _valid = true; + + ltrace(200) << _segment << " has " << _tracksNb << " choices " << _perpandicular << endl; + ltraceout(200); + + DebugSession::close(); + } + + + string RoutingEvent::_getTypeName () const + { return "RoutingEvent"; } + + + string RoutingEvent::_getString () const + { + string s = "<" + _getTypeName(); + + s += " " + getString(_eventLevel); + s += "," + getString((long)getPriority()); + s += " @" + DbU::getValueString(getAxisHistory()); + s += ":" + getString(_segment); + s += " " + getString(_segment->getDataNegociate()->getRipupCount()); + s += " "; + s += (isCloned ()?"C":"-"); + s += (isDisabled ()?"d":"-"); + s += (isUnimplemented()?"u":"-"); + s += ">"; + + return s; + } + + + Record* RoutingEvent::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_segment" , _segment ) ); + record->add ( getSlot ( "_processed" , _processed ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/RoutingEventHistory.cpp b/kite/src/RoutingEventHistory.cpp new file mode 100644 index 00000000..0b6851d8 --- /dev/null +++ b/kite/src/RoutingEventHistory.cpp @@ -0,0 +1,130 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./RoutingEventHistory.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include + +#include "hurricane/Error.h" +#include "kite/RoutingEvent.h" +#include "kite/RoutingEventHistory.h" + + +namespace Kite { + + + using std::cerr; + using std::setw; + using std::setfill; + using std::endl; + using Hurricane::Error; + + +// ------------------------------------------------------------------- +// Class : "RoutingEventHistory". + + + RoutingEventHistory::RoutingEventHistory () + : _events () + , _identicals(0) + { } + + + RoutingEventHistory::~RoutingEventHistory () + { clear (); } + + + RoutingEvent* RoutingEventHistory::getNth ( size_t index ) const + { + if ( index < size() ) return _events[index]; + return NULL; + } + + + RoutingEvent* RoutingEventHistory::getRNth ( size_t index ) const + { + if ( index < size() ) return _events[size()-index-1]; + return NULL; + } + + + void RoutingEventHistory::dump ( ostream& o, size_t depth ) const + { + o << " o Event History top stack:" << endl; + if ( _events.empty() ) return; + + size_t stop = (_events.size() > depth) ? (_events.size()-depth-1) : 0; + size_t i = _events.size()-1; + do { + o << " - [" << setfill('0') << setw(3) << i << "]: " << _events[i] << endl; + o << setfill(' '); + } while ( i && (i-- >= stop) ); + } + + + void RoutingEventHistory::push ( RoutingEvent* event ) + { + if ( _events.size() && (event->getSegment() == _events.back()->getSegment()) ) + _identicals++; + else + _identicals = 0; + + _events.push_back(event); + +// if ( _identicals > 30 ) { +// dump ( cerr, 40 ); +// throw Error("RoutingEventHistory::push(): More than 30 identicals events, we are looping."); +// } + } + + + void RoutingEventHistory::clear () + { + for ( size_t i=0 ; i < _events.size() ; i++ ) + _events[i]->destroy(); + _events.clear (); + _identicals = 0; + } + + + string RoutingEventHistory::_getString () const + { + string s = "<" + _getTypeName(); + + s += ":" + getString(size()); + s += ">"; + + return s; + } + + + Record* RoutingEventHistory::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_events", &_events ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/RoutingEventQueue.cpp b/kite/src/RoutingEventQueue.cpp new file mode 100644 index 00000000..0edbd2e9 --- /dev/null +++ b/kite/src/RoutingEventQueue.cpp @@ -0,0 +1,321 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./RoutingEvent.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include +#include +#include +#include + +#include "hurricane/Bug.h" +#include "kite/DataNegociate.h" +#include "kite/TrackElement.h" +#include "kite/RoutingEventQueue.h" +#include "kite/Session.h" + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::setw; + using std::max; + using std::make_heap; + using std::push_heap; + using std::pop_heap; + + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::Bug; + + + +// ------------------------------------------------------------------- +// Class : "RoutingEventQueue". + + + RoutingEventQueue::RoutingEventQueue () + : _topEventLevel (0) + , _pushRequests () + , _events () + { } + + + RoutingEventQueue::~RoutingEventQueue () + { clear (); } + + + void RoutingEventQueue::load ( const vector& segments ) + { + for ( size_t i=0 ; igetDataNegociate()->getGCellOrder() >= Session::getOrder() ) { + if ( segments[i]->getDataNegociate()->getRoutingEvent() ) { + cinfo << "[INFO] Already have a RoutingEvent - " << segments[i] << endl; + continue; + } + if ( segments[i]->getTrack() ) { + cinfo << "[INFO] Already in Track - " << segments[i] << endl; + continue; + } + RoutingEvent* event = RoutingEvent::create(segments[i]); + event->updateKey (); + _events.insert ( event ); + } + } + } + + + void RoutingEventQueue::add ( TrackElement* segment, unsigned int level ) + { + if ( segment->getTrack() ) { + cinfo << "[INFO] Already in Track " << (void*)segment->base()->base() + << ":" << segment << endl; + return; + } + + RoutingEvent* event = RoutingEvent::create(segment); + event->setEventLevel ( level ); + push ( event ); + } + + + void RoutingEventQueue::push ( RoutingEvent* event ) + { _pushRequests.insert ( event ); } + + + void RoutingEventQueue::commit () + { + ltrace(200) << "RoutingEventQueue::commit()" << endl; + ltracein(200); + + size_t addeds = _pushRequests.size(); + size_t before = _events.size(); + + set::iterator ipushEvent = _pushRequests.begin(); + for ( ; ipushEvent != _pushRequests.end() ; ipushEvent++ ) { + (*ipushEvent)->updateKey (); + + _topEventLevel = max ( _topEventLevel, (*ipushEvent)->getEventLevel() ); + _events.insert ( (*ipushEvent) ); + + ltrace(200) << "| " << (*ipushEvent) << endl; + } + _pushRequests.clear (); +#if defined(CHECK_ROUTINGEVENT_QUEUE) + _keyCheck (); +#endif + size_t after = _events.size(); + if ( after-before != addeds ) { + cerr << Bug("RoutingEventQueue::commit(): less than %d events pusheds (%d)." + ,addeds,(after-before)) << endl; + } + + // if ( (RoutingEvent::getProcesseds() > 61246) + // and (RoutingEvent::getProcesseds() < 61256) ) { + // cerr << "RoutingEventQueue::commit()" << endl; + // dump (); + // } + + ltraceout(200); + } + + + RoutingEvent* RoutingEventQueue::pop () + { + multiset::iterator ievent; + RoutingEvent* event = NULL; + +#if defined(CHECK_ROUTINGEVENT_QUEUE) + _keyCheck (); +#endif + + if ( !_events.empty() ) { + size_t beforeSize = _events.size(); + + ievent = _events.end(); + ievent--; + event = (*ievent); + _events.erase ( ievent ); + + // if ( (RoutingEvent::getProcesseds() > 61246) + // and (RoutingEvent::getProcesseds() < 61256) ) { + // cerr << "Popped: " << event << endl; + // dump (); + // } + + size_t afterSize = _events.size(); + + if ( afterSize+1 != beforeSize ) { + cerr << Bug("RoutingEventQueue::pop(): more than one event popped: %d." + ,(beforeSize-afterSize)) << endl; + } +// size_t erased = _events.erase ( event ); +// if ( erased != 1 ) { +// cerr << Bug("RoutingEventQueue::pop(): %d events matches key %p.",erased,event) << endl; +// #if defined(CHECK_ROUTINGEVENT_QUEUE) +// _keyCheck (); +// #endif +// } + } + + return event; + } + + + void RoutingEventQueue::repush ( RoutingEvent* event ) + { +#if defined(CHECK_ROUTINGEVENT_QUEUE) + _keyCheck (); +#endif + + multiset::iterator ievent = _events.find(event); + size_t count = _events.count(event); + if ( count > 1 ) { + cerr << Bug("RoutingEventQueue::repush(): %d events matches key %p.",count,event) << endl; +#if defined(CHECK_ROUTINGEVENT_QUEUE) + _keyCheck (); +#endif + } + + if ( ievent != _events.end() ) { + // if ( (RoutingEvent::getProcesseds() > 61246) + // and (RoutingEvent::getProcesseds() < 61256) ) { + // cerr << "Erasing: " << *ievent << endl; + // } + _events.erase ( ievent ); + } + push ( event ); + + // if ( (RoutingEvent::getProcesseds() > 61246) + // and (RoutingEvent::getProcesseds() < 61256) ) { + // cerr << "After repush: " << event << endl; + // dump(); + // } + } + + + void RoutingEventQueue::repushInvalidateds () + { + const vector& invalidateds0 = Session::getInvalidateds(); + set invalidateds1; + for ( size_t i=0 ; i::iterator isegment = invalidateds1.begin(); + for ( ; isegment != invalidateds1.end() ; isegment++ ) { + RoutingEvent* event = (*isegment)->getDataNegociate()->getRoutingEvent(); + if ( event + and not event->isUnimplemented() + and not event->isDisabled () + and not event->isProcessed () ) { + repush ( event ); + } else { + // if ( (RoutingEvent::getProcesseds() > 61246) + // and (RoutingEvent::getProcesseds() < 61256) ) { + // cerr << "NOT repushed: " << event << endl; + // } + } + } + } + + + void RoutingEventQueue::clear () + { + if ( not _events.empty() ) { + cerr << Bug("RoutingEvent queue is not empty, %d events remains." + ,_events.size()) << endl; + } + _events.clear (); + } + + + void RoutingEventQueue::dump () const + { + multiset::const_iterator ievent = _events.begin (); + for ( ; ievent != _events.end(); ievent++ ) { + cerr << "Order: Queue:" + << (*ievent)->getEventLevel() + << "," << setw(6) << (*ievent)->getPriority() + << " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getLength()) + << " " << (*ievent)->getSegment()->isHorizontal() + << " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getAxis()) + << " " << setw(6) << DbU::getValueString((*ievent)->getSegment()->getSourceU()) + << ": " << (*ievent)->getSegment() << endl; + } + } + + + void RoutingEventQueue::_keyCheck () const + { + multiset::const_iterator ievent = _events.begin (); + for ( ; ievent != _events.end(); ievent++ ) { + multiset::const_iterator ieventByKey + = _events.find ( *ievent ); + + if ( ieventByKey != ievent ) { + if ( ieventByKey == _events.end() ) { + cerr << Bug("Key mismatch in RoutingEvent Queue:\n" + " %p:%s wasn't found by key." + ,*ievent,getString(*ievent).c_str() + ) << endl; + } else { + cerr << Bug("Key mismatch in RoutingEvent Queue:\n" + " %p:%s has same key of\n" + " %p:%s" + ,*ievent,getString(*ievent).c_str() + ,*ieventByKey,getString(*ieventByKey).c_str() + ) << endl; + } + } + } + } + + + string RoutingEventQueue::_getString () const + { + string s = "<" + _getTypeName(); + + s += ":" + getString(size()); + s += ">"; + + return s; + } + + + Record* RoutingEventQueue::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_events", &_events ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/RoutingPlane.cpp b/kite/src/RoutingPlane.cpp new file mode 100644 index 00000000..9dcf8a6e --- /dev/null +++ b/kite/src/RoutingPlane.cpp @@ -0,0 +1,196 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./RoutingPlane.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "hurricane/Error.h" +#include "hurricane/Box.h" +#include "hurricane/Cell.h" + +#include "crlcore/RoutingLayerGauge.h" + +#include "kite/HorizontalTrack.h" +#include "kite/VerticalTrack.h" +#include "kite/RoutingPlane.h" +#include "kite/KiteEngine.h" + + +namespace { + + + const char* badLayerGauge = + "RoutingPlane::create() :\n\n" + " No plane at depth %u in %s."; + + +} // End of local namespace. + + +namespace Kite { + + + using std::cerr; + using std::endl; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::Error; + using Hurricane::Box; + using Hurricane::Cell; + + +// ------------------------------------------------------------------- +// Class : "RoutingPlane". + + + RoutingPlane::RoutingPlane ( KiteEngine* kite, size_t depth ) + : _kite (kite) + , _layerGauge(kite->getLayerGauge(depth)) + , _depth (depth) + , _tracks () + { } + + + RoutingPlane::~RoutingPlane () + { } + + + void RoutingPlane::destroy () + { + ltrace(90) << "RoutingPlane::destroy() - " + << (void*)this << " " << this << endl; + ltracein(90); + + for ( size_t index = 0 ; index < _tracks.size() ; index++ ) + _tracks[index]->destroy (); + + delete this; + + ltraceout(90); + } + + + RoutingPlane* RoutingPlane::create ( KiteEngine* kite, size_t depth ) + { + RoutingPlane* plane = new RoutingPlane ( kite, depth ); + + if ( !plane->_layerGauge ) + throw Error ( badLayerGauge, depth, getString(kite->getRoutingGauge()).c_str() ); + + size_t trackNumber; + Box abutmentBox = kite->getCell()->getAbutmentBox(); + if ( plane->getLayerGauge()->getDirection() & Constant::Horizontal ) { + plane->_trackMin = abutmentBox.getXMin () - DbU::lambda (2.0); + plane->_trackMax = abutmentBox.getXMax () + DbU::lambda (2.0); + plane->_axisMin = abutmentBox.getYMin (); + plane->_axisMax = abutmentBox.getYMax (); + trackNumber = plane->computeTracksSize (); + } else { + plane->_trackMin = abutmentBox.getYMin () - DbU::lambda (2.0); + plane->_trackMax = abutmentBox.getYMax () + DbU::lambda (2.0); + plane->_axisMin = abutmentBox.getXMin (); + plane->_axisMax = abutmentBox.getXMax (); + trackNumber = plane->computeTracksSize (); + } + + plane->_tracks.reserve ( trackNumber ); + for ( size_t index = 0 ; index < trackNumber ; index++ ) { + if ( plane->getLayerGauge()->getDirection() & Constant::Horizontal ) { + plane->_tracks.push_back ( HorizontalTrack::create ( plane, index ) ); + } else { + plane->_tracks.push_back ( VerticalTrack::create ( plane, index ) ); + } + } + + return plane; + } + + + RoutingPlane* RoutingPlane::getTop () const + { return getKiteEngine()->getRoutingPlaneByIndex ( getDepth()+1 ); } + + + RoutingPlane* RoutingPlane::getBottom () const + { + if ( !getDepth() ) return NULL; + return getKiteEngine()->getRoutingPlaneByIndex ( getDepth()-1 ); + } + + + Track* RoutingPlane::getTrackByIndex ( size_t index ) const + { + if ( index >= getTracksSize() ) return NULL; + return _tracks[index]; + } + + + Track* RoutingPlane::getTrackByPosition ( DbU::Unit axis, unsigned int mode ) const + { + return getTrackByIndex ( getLayerGauge()->getTrackIndex ( getAxisMin() + , getAxisMax() + , axis + , mode + ) ); + } + + + bool RoutingPlane::_check ( unsigned int& overlaps ) const + { + bool coherency = true; + + for ( size_t i=0 ; i<_tracks.size() ; i++ ) { + coherency = _tracks[i]->_check(overlaps) && coherency; + } + + return coherency; + } + + + string RoutingPlane::_getString () const + { + return "<" + _getTypeName() + " @" + + getString(_depth) + " [" + + getString(_tracks.size()) + "/" + + getString(_tracks.capacity()) + + "]>"; + } + + + Record* RoutingPlane::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_kite" , _kite ) ); + record->add ( getSlot ( "_layerGauge" , _layerGauge ) ); + record->add ( getSlot ( "_depth" , &_depth ) ); + record->add ( DbU::getValueSlot ( "_axisMin" , &_axisMin ) ); + record->add ( DbU::getValueSlot ( "_axisMax" , &_axisMax ) ); + record->add ( DbU::getValueSlot ( "_trackMin" , &_trackMin ) ); + record->add ( DbU::getValueSlot ( "_trackMax" , &_trackMax ) ); + record->add ( getSlot ( "_tracks" , &_tracks ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/Session.cpp b/kite/src/Session.cpp new file mode 100644 index 00000000..65c5cc63 --- /dev/null +++ b/kite/src/Session.cpp @@ -0,0 +1,364 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Session.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "hurricane/Bug.h" +#include "hurricane/Error.h" +#include "kite/Session.h" +#include "kite/Track.h" +#include "kite/TrackElement.h" +#include "kite/GCellGrid.h" +#include "kite/KiteEngine.h" + + +namespace { + + + using namespace Kite; + + + const char* reopenSession = + "Kite::Session::open() :\n\n" + " Session already open for %s (internal error)."; + + +} // End of local namespace. + + +namespace Kite { + + + using std::cerr; + using std::endl; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::Error; + using Hurricane::Bug; + + +// ------------------------------------------------------------------- +// Class : "Session". + + + Session::Session ( KiteEngine* kite ) + : Katabatic::Session(kite) + , _order (0) + , _insertEvents() + , _removeEvents() + , _sortEvents () + { } + + + void Session::_postCreate () + { + Katabatic::Session::_postCreate (); + } + + + Session::~Session () + { } + + + size_t Session::_preDestroy () + { + _isEmpty (); + + size_t count = Katabatic::Session::_preDestroy (); + + return count; + } + + + Session* Session::open ( KiteEngine* kite ) + { + ltrace(110) << "Kite::Session::open()" << endl; + + Session* session = Session::get (); + if ( session ) { + if ( session->_getKiteEngine() != kite ) + throw Error ( reopenSession, getString(session->getKiteEngine()).c_str() ); + + return session; + } + + session = new Session ( kite ); + session->_postCreate (); + + return session; + } + + + Session* Session::get ( const char* message ) + { return dynamic_cast( Katabatic::Session::get(message) ); } + + + Configuration* Session::getConfiguration () + { return Session::getKiteEngine()->getConfiguration(); } + + + void Session::link ( TrackElement* trackSegment ) + { Session::get("link(TrackElement*)")->_getKiteEngine()->_link(trackSegment); } + + + void Session::unlink ( TrackElement* trackSegment ) + { Session::get("unlink(TrackElement*)")->_getKiteEngine()->_unlink(trackSegment); } + + + TrackElement* Session::lookup ( Segment* segment ) + { return Session::get("Session::lookup(Segment*)")->_getKiteEngine()->_lookup(segment); } + + + TrackElement* Session::lookup ( AutoSegment* segment ) + { return Session::get("lookup(AutoSegment*)")->_getKiteEngine()->_lookup ( segment ); } + + + GCell* Session::lookup ( Katabatic::GCell* gcell ) + { return Session::get("lookup(Katabatic::GCell*)")->_getKiteEngine()->getGCellGrid()->getGCell(gcell->getIndex()); } + + + void Session::setInterrupt ( bool state ) + { Session::get("setInterrupt()")->_getKiteEngine()->setInterrupt(state); } + + + KiteEngine* Session::_getKiteEngine () + { return static_cast(_katabatic); } + + + Net* Session::_getBlockageNet () + { return _getKiteEngine()->getBlockageNet(); }; + + + NegociateWindow* Session::_getNegociateWindow () + { return _getKiteEngine()->getNegociateWindow(); }; + + + unsigned int Session::_getRipupCost () + { return _getKiteEngine()->getRipupCost(); }; + + + GCell* Session::_getGCellUnder ( DbU::Unit x, DbU::Unit y ) + { return _getKiteEngine()->getGCellGrid()->getGCell(Point(x,y)); }; + + + unsigned int Session::_getOrder () const + { return _order; } + + + void Session::_setOrder ( unsigned int order ) + { _order = order; } + + + size_t Session::_revalidate () + { + set packTracks; + + for ( size_t i=0 ; i < _removeEvents.size() ; i++ ) { + if ( !_removeEvents[i]._segment->getTrack() ) continue; + + packTracks.insert ( _removeEvents[i]._segment->getTrack() ); + _removeEvents[i]._segment->detach (); + } + _removeEvents.clear (); + + for ( set::iterator it=packTracks.begin() ; it != packTracks.end() ; it++ ) + (*it)->pack (); + + for ( size_t i=0 ; i < _insertEvents.size() ; i++ ) { + if ( _insertEvents[i]._segment ) { + _insertEvents[i]._track->insert ( _insertEvents[i]._segment ); + } + if ( _insertEvents[i]._marker ) _insertEvents[i]._track->insert ( _insertEvents[i]._marker ); + } + _insertEvents.clear (); + + // Check if to be destroyeds are not associateds with TrackSegments. + const set& destroyeds = getDestroyeds(); + set::const_iterator idestroyed = destroyeds.begin(); + for ( ; idestroyed != destroyeds.end() ; idestroyed++ ) { + if ( lookup(*idestroyed) ) { + cerr << Error("Destroyed AutoSegment is associated with a TrackSegment\n" + " (%s)" + ,getString(*idestroyed).c_str()) << endl; + } + } + + size_t count = Katabatic::Session::_revalidate (); + + Interval span; + vector processeds; + const vector& revalidateds = getRevalidateds (); + const set& netsModificateds = getNetsModificateds (); + + for ( size_t i=0 ; ibase() ); + + if ( trackSegment && !trackSegment->isRevalidated() ) { + if ( trackSegment->getNet() != currentNet ) { + currentNet = trackSegment->getNet(); + invalidEvent = (netsModificateds.find(currentNet) != netsModificateds.end()); + } + trackSegment->revalidate ( invalidEvent ); + processeds.push_back ( trackSegment ); + + Track* track = trackSegment->getTrack(); + if ( track ) { + track->forceSort (); + _sortEvents.insert ( track ); + } + } + } + for ( size_t i=0 ; isetRevalidated ( false ); + +# if defined(CHECK_DATABASE) + unsigned int overlaps = 0; +# endif + for ( set::iterator it=_sortEvents.begin() + ; it != _sortEvents.end() + ; it++ + ) { + (*it)->sort (); +# if defined(CHECK_DATABASE) + (*it)->_check ( overlaps, "Session::_revalidate() - track sorting." ); +# endif + } + + for ( set::iterator inet=netsModificateds.begin() ; inet != netsModificateds.end() ; inet++ ) { + _getKiteEngine()->_computeCagedConstraints ( *inet ); + } + +# if defined(CHECK_DATABASE) + for ( set::iterator it=packTracks.begin() ; it != packTracks.end() ; it++ ) + (*it)->_check ( overlaps, "Session::_revalidate() - on packed track." ); + + //_getKiteEngine()->_showOverlap (); +# endif + + _sortEvents.clear (); + + return count; + } + + + bool Session::_isEmpty () const + { + if ( !_insertEvents.empty() || !_removeEvents.empty() || !_sortEvents.empty() ) { + cerr << Bug(" Session::checkEmpty() failed :\n" + " %u inserts, %u removes and %u sort events remains." + , _insertEvents.size() + , _removeEvents.size() + , _sortEvents .size() ) << endl; + return false; + } + + return true; + } + + + void Session::_addInsertEvent ( TrackMarker* marker, Track* track ) + { + _insertEvents.push_back ( Event(marker,track) ); + _addSortEvent ( track, true ); + } + + + void Session::_addInsertEvent ( TrackElement* segment, Track* track ) + { +#if defined(CHECK_DETERMINISM) + cerr << "Order: Insert in @" << DbU::getValueString(track->getAxis()) + << " " << segment << endl; +#endif + ltrace(200) << "addInsertEvent() " << segment << endl; + + if ( segment->getTrack() != NULL ) { + cerr << Bug("Session::addInsertEvent(): Segment already in Track." + "\n %s." + "\n to %s." + ,getString(segment).c_str() + ,getString(track).c_str() + ) << endl; + return; + } + + _insertEvents.push_back ( Event(segment,track) ); + _addSortEvent ( track, true ); + } + + + void Session::_addRemoveEvent ( TrackElement* segment ) + { + if ( not segment->getTrack() ) { + cerr << Bug(" Kite::Session::addRemoveEvent() : %s is not in any Track." + ,getString(segment).c_str()) << endl; + return; + } + + ltrace(200) << "Ripup: @" << DbU::getValueString(segment->getAxis()) << " " << segment << endl; + _removeEvents.push_back ( Event(segment,segment->getTrack()) ); + _addSortEvent ( segment->getTrack(), true ); + } + + + void Session::_addMoveEvent ( TrackElement* segment, Track* track ) + { + if ( !segment->getTrack() ) { + cerr << Bug(" Kite::Session::addMoveEvent() : %s has no target Track." + ,getString(segment).c_str()) << endl; + return; + } + + _addRemoveEvent ( segment ); + _addInsertEvent ( segment, track ); + } + + + void Session::_addSortEvent ( Track* track, bool forced ) + { + if ( !track ) { + cerr << Bug(" Kite::Session::addSortEvent() : no Track to sort.") << endl; + return; + } + if ( forced ) track->forceSort (); + _sortEvents.insert ( track ); + } + + + string Session::_getTypeName () const + { return "Kite::Session"; } + + + Record* Session::_getRecord () const + { + Record* record = Session::_getRecord (); + record->add ( getSlot ( "_sortEvents" , &_sortEvents ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/Track.cpp b/kite/src/Track.cpp new file mode 100644 index 00000000..eb753f06 --- /dev/null +++ b/kite/src/Track.cpp @@ -0,0 +1,774 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Track.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include +#include +#include + +#include "hurricane/Warning.h" +#include "hurricane/Bug.h" +#include "hurricane/Layer.h" +#include "hurricane/Net.h" +#include "kite/RoutingPlane.h" +#include "kite/Track.h" +#include "kite/TrackMarker.h" +#include "kite/DataNegociate.h" + + +namespace { + + + using namespace std; + using namespace CRL; + using namespace Kite; + + + struct isDetachedSegment { + bool operator() ( const TrackElement* s ) { return !s->getTrack(); }; + }; + + + DbU::Unit getPositionByIterator ( const vector& v, size_t i ) + { return (*(v.begin()+i))->getSourceU(); } + + +} // End of local namespace. + + +namespace Kite { + + + using std::lower_bound; + using std::remove_if; + using std::sort; + using Hurricane::dbo_ptr; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::Warning; + using Hurricane::Bug; + using Hurricane::Layer; + using Hurricane::Net; + + +// ------------------------------------------------------------------- +// Class : "Track". + + + const size_t Track::NPOS = (size_t)-1; + + + Track::Track ( RoutingPlane* routingPlane, unsigned int index ) + : _routingPlane (routingPlane) + , _index (index) + , _axis (routingPlane->getTrackPosition(index)) + , _min (routingPlane->getTrackMin()) + , _max (routingPlane->getTrackMax()) + , _segments () + , _markers () + , _segmentsValid(false) + , _markersValid (false) + { } + + + void Track::_postCreate () + { } + + + Track::~Track () + { + ltrace(90) << "Track::~Track() - " << (void*)this << endl; + } + + + void Track::_preDestroy () + { + ltrace(90) << "Track::_preDestroy() - " << (void*)this << " " << this << endl; + ltracein(90); + + for ( size_t i=0 ; i<_segments.size() ; i++ ) + if ( _segments[i] ) _segments[i]->detach(); + + for ( size_t i=0 ; i<_markers.size() ; i++ ) + if ( _markers[i] ) _markers[i]->destroy(); + + ltraceout(90); + } + + + void Track::destroy () + { + ltrace(90) << "Track::destroy() - " << (void*)this << " " << this << endl; + + Track::_preDestroy (); + delete this; + } + + + KiteEngine* Track::getKiteEngine () const + { return _routingPlane->getKiteEngine(); } + + + unsigned int Track::getDepth () const + { return _routingPlane->getDepth(); } + + + const Layer* Track::getLayer () const + { return _routingPlane->getLayer(); } + + + const Layer* Track::getBlockageLayer () const + { return _routingPlane->getBlockageLayer(); } + + + TrackElement* Track::getSegment ( size_t index ) const + { + if ( (index == NPOS) || (index >= getSize()) ) return NULL; + return _segments[index]; + } + + + TrackElement* Track::getSegment ( DbU::Unit position ) const + { + unsigned int state; + size_t begin; + size_t end; + + getIBounds ( position, begin, end, state ); + + if ( state & (MinTrackMin|MaxTrackMax) ) return NULL; + + return getSegment(begin); + } + + + TrackElement* Track::getNext ( size_t& index, Net* net, bool useOrder ) const + { + for ( index++ ; index < _segments.size() ; index++ ) { + if ( _segments[index]->getNet() == net ) continue; + if ( useOrder + and _segments[index]->getDataNegociate() + and (_segments[index]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) + continue; + return _segments[index]; + } + index = NPOS; + + return NULL; + } + + + TrackElement* Track::getPrevious ( size_t& index, Net* net, bool useOrder ) const + { + for ( index-- ; index != NPOS ; index-- ) { + if ( inltrace(148) ) { + cerr << tab << index << ":"; cerr.flush(); + cerr << _segments[index] << endl; + } + if ( _segments[index]->getNet() == net ) continue; + if ( useOrder + and _segments[index]->getDataNegociate() + and (_segments[index]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) + continue; + return _segments[index]; + } + index = NPOS; + + return NULL; + } + + + TrackElement* Track::getNextFixed ( size_t& index ) const + { + TrackElement* nextFixed = getNext ( index, NULL ); + for ( ; nextFixed ; nextFixed = getNext(index,NULL) ) { + if ( nextFixed->base()->isFixed() ) return nextFixed; + } + + return nextFixed; + } + + + void Track::getIBounds ( DbU::Unit position, size_t& begin, size_t& end, unsigned int& state ) const + { + if ( _segments.empty() ) { + state = EmptyTrack; + begin = end = 0; + return; + } + + if ( position < _min ) { + cerr << Warning ( " Position %s inferior to the lower bound of %s. Returning NPOS." + , DbU::getValueString(position).c_str() + , getString(this).c_str() ) << endl; + state = BeforeFirst; + begin = end = 0; + return; + } + + if ( position > _max ) { + cerr << Warning ( " Position %s superior to the upper bound of %s. Returning NPOS." + , DbU::getValueString(position).c_str() + , getString(this).c_str() ) << endl; + state = AfterLast; + begin = end = _segments.size() - 1; + return; + } + + vector::const_iterator lowerBound + = lower_bound ( _segments.begin(), _segments.end(), position, SourceCompare() ); + begin = end = lowerBound - _segments.begin(); + + if ( begin < _segments.size() ) + for ( ; (begin > 0) && (_segments[begin-1]->getNet() == _segments[begin]->getNet()) ; --begin ); + + state = 0; + if ( (begin == 0) && (position < _segments[0]->getSourceU()) ) { + state = BeforeFirst; + } else { + if ( begin ) end = begin -= 1; + + size_t usedBegin = begin; + size_t usedEnd = begin; + Interval usedInterval = expandUsedInterval ( usedBegin, usedEnd ); + + if ( position < usedInterval.getVMax() ) + state = Inside; + else + if ( begin+1 == _segments.size() ) + state = AfterLast; + else + state = Outside; + } + } + + + void Track::getOverlapBounds ( Interval interval, size_t& begin, size_t& end ) const + { + unsigned int iState; + size_t iBegin; + size_t iEnd; + + if ( _segments.empty() + || (interval.getVMax() <= _min) + || (interval.getVMin() >= _max)) { + begin = end = NPOS; + return; + } + + getIBounds ( interval.getVMin(), begin, iEnd, iState ); + expandUsedInterval ( begin, iEnd ); + + getIBounds ( interval.getVMax(), iBegin, end, iState ); + while ( end < _segments.size() ) { + if ( _segments[end++]->getSourceU() >= interval.getVMax() ) break; + } + } + + + TrackCost Track::getOverlapCost ( Interval interval, Net* net, size_t begin, size_t end ) const + { + TrackCost cost ( const_cast(this), interval, begin, end ); + + ltrace(148) << "getOverlapCost() @" << DbU::getValueString(_axis) + << " [" << interval.getVMin() << " " << interval.getVMax() << "]" << endl; + + ltracein(148); + + vector::const_iterator lowerBound + = lower_bound ( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() ); + size_t mbegin = lowerBound - _markers.begin(); + + for ( ; (mbegin < _markers.size()) + && (_markers[mbegin]->getSourceU() <= interval.getVMax()) ; mbegin++ ) { + ltrace(148) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl; + if ( _markers[mbegin]->getNet() != net ) { + ltrace(148) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl; + cost.incTerminals ( _markers[mbegin]->getWeight(this) ); + } + } + + if ( begin == NPOS ) { + ltrace(148) << " begin == NPOS (after last TrackElement)." << endl; + ltraceout(148); + return cost; + } + + for ( ; begin < end ; begin++ ) { + if ( _segments[begin]->getNet() == net ) { + cost.incDeltaShared ( _segments[begin]->getCanonicalInterval().intersection(interval).getSize() ); + } + ltrace(190) << "| overlap: " << _segments[begin] << endl; + _segments[begin]->incOverlapCost ( net, cost ); + if ( cost.isInfinite() ) break; + } + + ltraceout(148); + + return cost; + } + + + TrackCost Track::getOverlapCost ( Interval interval, Net* net ) const + { + size_t begin; + size_t end; + + getOverlapBounds ( interval, begin, end ); + + return getOverlapCost ( interval, net, begin, end ); + } + + + TrackCost Track::getOverlapCost ( TrackElement* segment ) const + { + return getOverlapCost ( segment->getCanonicalInterval(), segment->getNet() ); + } + + + void Track::getTerminalWeight ( Interval interval, Net* net, size_t& count, unsigned int& weight ) const + { + ltrace(148) << "getTerminalWeight() @" << DbU::getValueString(_axis) + << " [" << interval.getVMin() << " " << interval.getVMax() << "]" << endl; + ltracein(148); + + //count = 0; + //weight = 0; + + vector::const_iterator lowerBound + = lower_bound ( _markers.begin(), _markers.end(), interval.getVMin(), TrackMarker::Compare() ); + size_t mbegin = lowerBound - _markers.begin(); + + for ( ; (mbegin < _markers.size()) + && (_markers[mbegin]->getSourceU() <= interval.getVMax()) ; mbegin++ ) { + ltrace(148) << "| @" << DbU::getValueString(_axis) << _markers[mbegin] << endl; + if ( _markers[mbegin]->getNet() == net ) { + ltrace(200) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl; + weight += _markers[mbegin]->getWeight(this); + ++count; + } + } + ltraceout(148); + } + + + Track* Track::getNext () const + { + return getRoutingPlane()->getTrackByIndex ( getIndex()+1 ); + } + + + Track* Track::getPrevious () const + { + if ( !getIndex() ) return NULL; + + return getRoutingPlane()->getTrackByIndex ( getIndex()-1 ); + } + + + size_t Track::find ( const TrackElement* segment ) const + { + if ( !_segments.size() ) return NPOS; + + vector::const_iterator lowerBound + = lower_bound ( _segments.begin() + , _segments.end() + , segment + , SegmentCompare() + ); + + if ( lowerBound != _segments.end() ) { + while ( segment->getSourceU() == (*lowerBound)->getSourceU() ) { + if ( *lowerBound == segment ) return (size_t)(lowerBound-_segments.begin()); + lowerBound++; + } + } + + return NPOS; + } + + + Interval Track::getFreeInterval ( DbU::Unit position, Net* net ) const + { + unsigned int state; + size_t begin; + size_t end; + + if ( !_segments.size() ) return Interval(_min,_max); + + getIBounds ( position, begin, end, state ); + if ( (state == Inside) && (_segments[begin]->getNet() != net) ) + return Interval(); + + return expandFreeInterval ( begin, end, state, net ); + } + + + Interval Track::expandFreeInterval ( size_t& begin, size_t& end, unsigned int state, Net* net, bool useOrder ) const + { + DbU::Unit minFree = _min; + + if ( !(state & MinTrackMin) ) { + if ( _segments[begin]->getNet() == net ) + getPrevious ( begin, net, useOrder ); + + if ( begin != NPOS ) { + size_t usedEnd; + minFree = expandUsedInterval ( begin, usedEnd, useOrder ).getVMax(); + } + } + + if ( !(state & MaxTrackMax) ) { + if ( _segments[end]->getNet() == net ) { + getNext ( end, net, useOrder ); + + if ( end == NPOS ) { + end = _segments.size() - 1; + setMaximalFlags ( state, MaxTrackMax ); + } else { + setMaximalFlags ( state, MaxSegmentMin ); + } + } + } + + return Interval ( minFree, getMaximalPosition(end,state) ); + } + + + void Track::forceSort () + { + _segmentsValid = false; + } + + + void Track::insert ( TrackMarker* marker ) + { + _markers.push_back ( marker ); + _markersValid = false; + } + + + void Track::insert ( TrackElement* segment ) + { + ltrace(200) << "Track::insert() " << getLayer()->getName() + << " @" << DbU::getValueString(getAxis()) << " " << segment << endl; + + if ( (getLayer()->getMask() != segment->getLayer()->getMask()) + and (getBlockageLayer()->getMask() != segment->getLayer()->getMask()) ) { + cerr << Bug("Track::insert(), segment %s has not the right layer." + ,getString(segment).c_str()) << endl; + } + + segment->setAxis ( getAxis() ); + _segments.push_back ( segment ); + _segmentsValid = false; + + segment->setTrack ( this ); + } + + + void Track::setSegment ( TrackElement* segment, size_t index ) + { + if ( index >= _segments.size() ) return; + + _segments[index] = segment; + } + + + bool Track::_check ( unsigned int& overlaps, const char* message ) const + { + bool coherency = true; + bool holes = false; + + if ( message ) cerr << " o Checking Track - " << message << endl; + ltrace(90) << "[CHECK] " << (void*)this << ":" << this << endl; + + for ( size_t i=0 ; i<_segments.size() ; i++ ) { + if ( _segments[i] ) { + if ( i ) { + if ( _segments[i-1] == _segments[i] ) { + cerr << "[CHECK] incoherency at " << i << " " + << _segments[i] << " is duplicated. " << endl; + coherency = false; + } + } + if ( !_segments[i]->getTrack() ) { + cerr << "[CHECK] incoherency at " << i << " " + << _segments[i] << " is detached." << endl; + coherency = false; + } else { + if ( _segments[i]->getTrack() != this ) { + cerr << "[CHECK] incoherency at " << i << " " + << _segments[i] << " is in track " + << _segments[i]->getTrack() << endl; + coherency = false; + } + if ( _segments[i]->getIndex() != i ) { + cerr << "[CHECK] incoherency at " << i << " " + << _segments[i] << " has bad index " + << _segments[i]->getIndex() << endl; + coherency = false; + } + } + if ( _segments[i]->getAxis() != getAxis() ) { + cerr << "[CHECK] incoherency at " << i << " " + << _segments[i] << " is not on Track axis " + << DbU::getValueString(getAxis()) << "." << endl; + coherency = false; + } + + coherency = coherency && _segments[i]->_check (); + } else { + cerr << "[CHECK] Hole at position " << i << "." << endl; + holes = true; + coherency = false; + } + } + + if ( !holes ) + coherency = coherency && (checkOverlap(overlaps) == 0); + + return coherency; + } + + + DbU::Unit Track::getSourcePosition ( size_t i ) const + { + if ( i == NPOS) return 0; + + return _segments[i]->getSourceU(); + } + + + DbU::Unit Track::getSourcePosition ( vector::iterator isegment ) const + { + if ( isegment == _segments.end() ) return 0; + + return (*isegment)->getSourceU(); + } + + + DbU::Unit Track::getMinimalPosition ( size_t index, unsigned int state ) const + { + Interval canonical; + + switch ( state & MinMask ) { + case MinTrackMin: return _min; + case MinSegmentMin: return _segments[index]->getSourceU (); + case MinSegmentMax: return _segments[index]->getTargetU (); + } + + cerr << Bug ( " Track::getMinimalPosition(size_t,unsigned int) :" + " invalid state value %ud.", state ) << endl; + + return _min; + } + + + DbU::Unit Track::getMaximalPosition ( size_t index, unsigned int state ) const + { + Interval canonical; + + switch ( state & MaxMask ) { + case MaxTrackMax: return _max; + case MaxSegmentMin: return _segments[index ]->getSourceU (); + case MaxNextSegmentMin: return _segments[index+1]->getSourceU (); + case MaxSegmentMax: return _segments[index ]->getTargetU (); + } + + cerr << Bug ( " Track::getMaximalPosition(size_t,unsigned int) :" + " invalid state value %ud.", state ) << endl; + + return _min; + } + + + Interval Track::expandUsedInterval ( size_t& begin, size_t& end, bool useOrder ) const + { + if ( begin == NPOS ) return Interval(); + + size_t seed = begin; + Net* owner = _segments[seed]->getNet(); + + Interval expandInterval; + Interval ownerInterval; + _segments[seed]->getCanonical ( ownerInterval ); + + size_t i = seed; + while ( --i != NPOS ) { + if ( _segments[i]->getNet() != owner ) break; + if ( useOrder + and _segments[i]->getDataNegociate() + and (_segments[i]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) + continue; + + _segments[i]->getCanonical ( expandInterval ); + if ( expandInterval.getVMax() >= ownerInterval.getVMin() ) { + ownerInterval.merge ( expandInterval ); + begin = i; + } + } + + end = i = seed; + while ( ++i < _segments.size() ) { + if ( _segments[i]->getNet() != owner ) break; + if ( useOrder + and _segments[i]->getDataNegociate() + and (_segments[i]->getDataNegociate()->getGCellOrder() >= Session::getOrder()) ) + continue; + + _segments[i]->getCanonical ( expandInterval ); + if ( expandInterval.getVMin() > ownerInterval.getVMax() ) break; + if ( expandInterval.getVMax() > ownerInterval.getVMax() ) end = i; + + ownerInterval.merge ( expandInterval ); + } + + return ownerInterval; + } + + + size_t Track::pack () + { + ltrace(148) << "Track::pack() - " << this << endl; + ltracein(148); + + size_t size = _segments.size(); + + vector::iterator beginRemove + = remove_if ( _segments.begin(), _segments.end(), isDetachedSegment() ); + + _segments.erase ( beginRemove, _segments.end() ); + +# if 0 + size_t first = 0; + size_t last = 0; + bool erase = false; + + while ( last < _segments.size() ) { + if ( _segments[last] ) { + if ( erase ) { + _segments.erase ( _segments.begin()+first, _segments.begin()+last ); + + erase = false; + last = first; + } else { + first = last; + } + } else { + erase = true; + } + } + + if ( erase ) + _segments.erase ( _segments.begin()+first, _segments.end() ); +# endif + + ltrace(148) << "After packing " << this << endl; + ltraceout(148); + + return size - _segments.size(); + } + + + void Track::sort () + { + if ( !_segmentsValid ) { + std::sort ( _segments.begin(), _segments.end(), SegmentCompare() ); + for ( size_t i=0 ; i < _segments.size() ; i++ ) { + _segments[i]->setIndex ( i ); + } + _segmentsValid = true; + } + + if ( !_markersValid ) { + std::sort ( _markers.begin(), _markers.end(), TrackMarker::Compare() ); + _markersValid = true; + } + } + + + unsigned int Track::checkOverlap ( unsigned int& overlaps ) const + { + if ( !_segments.size() ) return 0; + + size_t j = 0; + for ( size_t i=0 ; i<_segments.size()-1 ; i++ ) { + if ( _segments[i]->getNet() == _segments[i+1]->getNet() ) { + if ( _segments[i]->getSourceU() == _segments[i+1]->getSourceU() ) { + if ( _segments[i]->getTargetU() < _segments[i+1]->getTargetU() ) { + cerr << Warning(" Invalid sorting length order:\n%s \n%s " + ,getString(_segments[i ]).c_str() + ,getString(_segments[i+1]).c_str()) << endl; + } + } + for ( j=i+1 ; (j<_segments.size()) && (_segments[i]->getNet() == _segments[j]->getNet()) ; j++ ); + } else { + j = i+1; + } + + if ( (j<_segments.size()) + && (_segments[i]->getTargetU() > _segments[j]->getSourceU()) ) { + cerr << Warning("Overlap between:\n %s\n %s" + ,getString(_segments[i]).c_str() + ,getString(_segments[j]).c_str()) << endl; + overlaps++; + } + } + + return overlaps; + } + + + string Track::_getString () const + { + return "<" + _getTypeName() + " " + + getString(getLayer()) + " @" + + DbU::getValueString(_axis) + " [" + + DbU::getValueString(_min) + ":" + + DbU::getValueString(_max) + "] [" + + getString(_segments.size()) + "/" + + getString(_segments.capacity()) + + "]>"; + } + + + Record* Track::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot ( "_routingPlane", _routingPlane ) ); + record->add ( getSlot ( "_index" , &_index ) ); + record->add ( DbU::getValueSlot ( "_axis" , &_axis ) ); + record->add ( getSlot ( "_segments" , &_segments ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackBlockage.cpp b/kite/src/TrackBlockage.cpp new file mode 100644 index 00000000..c5aa492e --- /dev/null +++ b/kite/src/TrackBlockage.cpp @@ -0,0 +1,204 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackBlockage.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/DataBase.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "katabatic/AutoContact.h" +#include "crlcore/RoutingGauge.h" +#include "kite/GCell.h" +#include "kite/DataNegociate.h" +#include "kite/TrackBlockage.h" +#include "kite/TrackCost.h" +#include "kite/Track.h" +#include "kite/Session.h" +#include "kite/RoutingEvent.h" +#include "kite/NegociateWindow.h" + + +namespace Kite { + + + using namespace std; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::tab; + using Hurricane::ForEachIterator; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Net; + using Hurricane::Name; + using Hurricane::RegularLayer; + using Hurricane::Technology; + using Hurricane::DataBase; + using Hurricane::Horizontal; + using Hurricane::Vertical; + + +// ------------------------------------------------------------------- +// Class : "TrackBlockage". + + + TrackBlockage::TrackBlockage ( Track* track, Box& boundingBox ) + : TrackElement (NULL) + , _segment (NULL) + { + if ( track ) { + Technology* technology = DataBase::getDB()->getTechnology(); + const Layer* layer1 = track->getLayer()->getBlockageLayer(); + RegularLayer* layer2 = dynamic_cast(technology->getLayer(layer1->getMask())); + ltrace(190) << "Blockage layer: " << layer2 << endl; + if ( layer2 ) { + DbU::Unit extention = layer2->getExtentionCap(); + if ( track->getDirection() == Constant::Horizontal ) { + _sourceU = boundingBox.getXMin(); + _targetU = boundingBox.getXMax(); + + _segment = Horizontal::create ( Session::getBlockageNet() + , layer2 + , track->getAxis() + , layer2->getMinimalSize() + , _sourceU + extention + , _targetU - extention + ); + } else { + _sourceU = boundingBox.getYMin(); + _targetU = boundingBox.getYMax(); + + _segment = Vertical::create ( Session::getBlockageNet() + , layer2 + , track->getAxis() + , layer2->getMinimalSize() + , _sourceU + extention + , _targetU - extention + ); + } + } + } + } + + + void TrackBlockage::_postCreate () + { TrackElement::_postCreate (); } + + + TrackBlockage::~TrackBlockage () + { } + + + void TrackBlockage::_preDestroy () + { + ltrace(90) << "TrackBlockage::_preDestroy() - " << (void*)this << endl; + TrackElement::_preDestroy (); + } + + + TrackElement* TrackBlockage::create ( Track* track, Box& boundingBox ) + { + TrackBlockage* trackBlockage = NULL; + if ( track ) { + trackBlockage = new TrackBlockage ( track, boundingBox ); + trackBlockage->_postCreate (); + Session::addInsertEvent ( trackBlockage, track ); + + ltrace(190) << "Adding: " << boundingBox << " on " << track << endl; + + ltrace(200) << "TrackBlockage::create(): " << trackBlockage << endl; + } + return trackBlockage; + } + + + AutoSegment* TrackBlockage::base () const { return NULL; } + bool TrackBlockage::isFixed () const { return true; } + bool TrackBlockage::isBlockage () const { return true; } + DbU::Unit TrackBlockage::getAxis () const { return getTrack()->getAxis(); } + bool TrackBlockage::isHorizontal () const { return getTrack()->isHorizontal(); } + bool TrackBlockage::isVertical () const { return getTrack()->isVertical(); } + unsigned int TrackBlockage::getDirection () const { return getTrack()->getDirection(); } + Net* TrackBlockage::getNet () const { return _segment->getNet(); } + const Layer* TrackBlockage::getLayer () const { return _segment->getLayer(); } + Interval TrackBlockage::getFreeInterval ( bool useOrder ) const { return Interval(); } + + + unsigned long TrackBlockage::getId () const + { + cerr << Error("::getId() called on %s.",_getString().c_str()) << endl; + return 0; + } + + + TrackElement* TrackBlockage::getNext () const + { + size_t dummy = _index; + return _track->getNext ( dummy, getNet() ); + } + + + TrackElement* TrackBlockage::getPrevious () const + { + size_t dummy = _index; + return _track->getPrevious ( dummy, getNet() ); + } + + + string TrackBlockage::_getTypeName () const + { return "TrackBlockage"; } + + + string TrackBlockage::_getString () const + { + string s1 = _segment->_getString(); + string s2 = " [" + DbU::getValueString(_sourceU) + + ":" + DbU::getValueString(_targetU) + "]" + + " " + DbU::getValueString(_targetU-_sourceU) + + " [" + ((_track) ? getString(_index) : "npos") + "]"; + s1.insert ( s1.size()-1, s2 ); + + return s1; + } + + + Record* TrackBlockage::_getRecord () const + { + Record* record = TrackElement::_getRecord (); + record->add ( getSlot ( "_segment", _segment ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackCost.cpp b/kite/src/TrackCost.cpp new file mode 100644 index 00000000..e2e6f821 --- /dev/null +++ b/kite/src/TrackCost.cpp @@ -0,0 +1,191 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackCost.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include +#include + +#include "kite/Track.h" +#include "kite/TrackCost.h" +#include "kite/Session.h" + + + + +namespace Kite { + + + using std::cerr; + using std::endl; + + +// ------------------------------------------------------------------- +// Class : "TrackCost". + + + TrackCost::TrackCost ( Track* track + , const Interval& interval + , size_t begin + , size_t end + ) + : _track (track) + , _begin (begin) + , _end (end) + , _interval (interval) + , _blockage (false) + , _fixed (false) + , _infinite (false) + , _hardOverlap (false) + , _overlap (false) + , _leftOverlap (false) + , _rightOverlap (false) + , _terminals (0) + , _delta (-interval.getSize()) + , _deltaShared (0) + , _deltaPerpand (0) + , _axisWeight (0) + , _distanceToFixed(DbU::Max) + , _dataState (0) + , _ripupCount (0) + { + TrackElement* neighbor; + if ( _begin != Track::NPOS ) { + neighbor = _track->getSegment(_begin); + if ( neighbor && neighbor->isFixed() ) { + if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0; + _distanceToFixed += interval.getVMin() - neighbor->getTargetU(); + } + } + if ( _end != Track::NPOS ) { + neighbor = _track->getSegment(_end); + if ( neighbor && neighbor->isFixed() ) { + if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0; + _distanceToFixed += neighbor->getSourceU() - interval.getVMax(); + } + } + } + + + TrackCost::~TrackCost () + { } + + + bool TrackCost::isFree () const + { + return /*(_terminals == 0) &&*/ (!_overlap) && (!_infinite); + } + + + bool operator< ( const TrackCost& lhs, const TrackCost& rhs ) + { + if ( lhs._infinite xor rhs._infinite ) return rhs._infinite; + if ( lhs._hardOverlap xor rhs._hardOverlap ) return rhs._hardOverlap; + + if ( lhs._ripupCount + (int)Session::getRipupCost() < rhs._ripupCount ) return true; + if ( lhs._ripupCount > rhs._ripupCount + (int)Session::getRipupCost() ) return false; + + if ( lhs._overlap xor rhs._overlap ) return rhs._overlap; + + //std::cerr << "lhs:" << lhs._ripupCount + // << " rhs:" << rhs._ripupCount + // << " " << rhs._ripupCount - lhs._ripupCount << " > " << Session::getRipupCost() + // << std::endl; + //if ( lhs._ripupCount - rhs._ripupCount > (int)Session::getRipupCost() ) return false; + + if ( lhs._terminals < rhs._terminals ) return true; + if ( lhs._terminals > rhs._terminals ) return false; + + if ( lhs._delta < rhs._delta ) return true; + if ( lhs._delta > rhs._delta ) return false; + + if ( lhs._axisWeight < rhs._axisWeight ) return true; + if ( lhs._axisWeight > rhs._axisWeight ) return false; + + if ( lhs._deltaPerpand < rhs._deltaPerpand ) return true; + if ( lhs._deltaPerpand > rhs._deltaPerpand ) return false; + + if ( lhs._distanceToFixed > rhs._distanceToFixed ) return true; + if ( lhs._distanceToFixed < rhs._distanceToFixed ) return false; + + return lhs.getTrack()->getAxis() < rhs.getTrack()->getAxis(); + } + + + bool TrackCost::CompareByDelta::operator() ( const TrackCost& lhs, const TrackCost& rhs ) + { + return lhs.getDelta() < rhs.getDelta(); + } + + + void TrackCost::consolidate () + { + if ( !_infinite && !_hardOverlap ) { + //_deltaPerpand += - (_deltaShared << 1); + _delta += - _deltaShared; + } + } + + + string TrackCost::_getString () const + { + string s = "<" + _getTypeName(); + + s += " " + getString(_track); + s += " " + getString(_ripupCount); + s += " " + getString(_ripupCount); + s += " " + string ( (_blockage )?"b":"-" ); + s += string ( (_hardOverlap)?"h":"-" ); + s += string ( (_overlap )?"o":"-" ); + s += " " + getString(_terminals); + s += "/" + DbU::getValueString(_delta); + s += "/" + DbU::getValueString(_axisWeight); + s += "/" + DbU::getValueString(_deltaPerpand); + s += "/" + DbU::getValueString(_distanceToFixed); + s += " " + getString(_dataState); + s += ">"; + + return s; + } + + + Record* TrackCost::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot ( "_track" , _track ) ); + record->add ( getSlot ( "_begin" , &_begin ) ); + record->add ( getSlot ( "_end" , &_end ) ); + record->add ( getSlot ( "_interval" , &_interval ) ); + record->add ( getSlot ( "_infinite" , _infinite ) ); + record->add ( getSlot ( "_overlap" , _overlap ) ); + record->add ( getSlot ( "_terminals", _terminals ) ); + record->add ( getSlot ( "_delta" , &_delta ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackElement.cpp b/kite/src/TrackElement.cpp new file mode 100644 index 00000000..8dcae766 --- /dev/null +++ b/kite/src/TrackElement.cpp @@ -0,0 +1,305 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackElement.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "katabatic/AutoContact.h" +#include "crlcore/RoutingGauge.h" +#include "kite/GCell.h" +#include "kite/DataNegociate.h" +#include "kite/TrackElement.h" +#include "kite/TrackCost.h" +#include "kite/Track.h" +#include "kite/Session.h" +#include "kite/RoutingEvent.h" +#include "kite/NegociateWindow.h" + + + +namespace { + + + using namespace std; + using namespace Hurricane; + using namespace CRL; + using namespace Kite; + + + // --------------------------------------------------------------- + // Function : "DummyOverlapCost ()". + + + void DummyOverlapCost ( const TrackElement* segment, TrackCost& cost ) + { + cerr << Warning("No overlapCost callback has been set (%s)." + ,getString(segment).c_str()) << endl; + } + + +} // End of local namespace. + + +namespace Kite { + + + using Hurricane::Bug; + using Hurricane::Net; + using Hurricane::Name; + + +// ------------------------------------------------------------------- +// Class : "TrackElement::Compare". + + + bool TrackElement::Compare::operator() ( TrackElement* lhs, TrackElement* rhs ) + { + return lhs->getArea() > rhs->getArea(); + } + + +// ------------------------------------------------------------------- +// Class : "TrackElement::CompareByPosition". +// +// Return: lhs < rhs. + + + bool TrackElement::CompareByPosition::operator() ( const TrackElement* lhs, const TrackElement* rhs ) const + { + if ( lhs == rhs ) return false; + + if ( lhs->isBlockage() xor rhs->isBlockage() ) + return lhs->isBlockage(); + + if ( lhs->getLength() < rhs->getLength() ) return true; + if ( lhs->getLength() > rhs->getLength() ) return false; + + if ( lhs->isHorizontal() xor rhs->isHorizontal() ) + return rhs->isHorizontal(); + + if ( lhs->getAxis() > rhs->getAxis() ) return true; + if ( lhs->getAxis() < rhs->getAxis() ) return false; + + if ( lhs->getSourceU() > rhs->getSourceU() ) return true; + if ( lhs->getSourceU() < rhs->getSourceU() ) return false; + + if ( lhs->isBlockage() and rhs->isBlockage() ) return false; + + //return lhs->getNet()->getName() < rhs->getNet()->getName(); + return lhs->getId() < rhs->getId(); + } + + +// ------------------------------------------------------------------- +// Class : "TrackElement". + + + SegmentOverlapCostCB* TrackElement::_overlapCostCallback = DummyOverlapCost; + + + SegmentOverlapCostCB* TrackElement::setOverlapCostCB ( SegmentOverlapCostCB* cb ) + { + SegmentOverlapCostCB* oldCb = _overlapCostCallback; + + _overlapCostCallback = cb; + + return oldCb; + } + + +// Former inline functions. + AutoSegment* TrackElement::base () const { return NULL; } + bool TrackElement::isCreated () const { return false; } + bool TrackElement::isFixed () const { return false; } + bool TrackElement::isBlockage () const { return false; } + bool TrackElement::isStrap () const { return false; } + bool TrackElement::isSlackenStrap () const { return false; } + bool TrackElement::isLocal () const { return true; } + bool TrackElement::isGlobal () const { return not isLocal(); } + bool TrackElement::isLocked () const { return false; } + bool TrackElement::isTerminal () const { return false; } + bool TrackElement::isRevalidated () const { return false; } + bool TrackElement::isRouted () const { return true; } + bool TrackElement::isSlackened () const { return false; } + bool TrackElement::isSlackenDogLeg () const { return false; } + bool TrackElement::hasSourceDogLeg () const { return false; } + bool TrackElement::hasTargetDogLeg () const { return false; } + bool TrackElement::allowOutsideGCell () const { return false; } + bool TrackElement::canGoOutsideGCell () const { return false; } + bool TrackElement::canRipple () const { return false; } + unsigned long TrackElement::getId () const { return 0; } + GCell* TrackElement::getGCell () const { return NULL; } + unsigned long TrackElement::getArea () const { return 0; } + unsigned int TrackElement::getDogLegLevel () const { return 0; } + unsigned int TrackElement::getDogLegOrder () const { return 0; } + Interval TrackElement::getSourceConstraints () const { return Interval(); } + Interval TrackElement::getTargetConstraints () const { return Interval(); } + DataNegociate* TrackElement::getDataNegociate () const { return NULL; } + TrackElements TrackElement::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(NULL); } + void TrackElement::setAllowOutsideGCell ( bool ) { } + void TrackElement::setLock ( bool ) { } + void TrackElement::setRevalidated ( bool ) { } + void TrackElement::invalidate () { } + void TrackElement::setCanRipple ( bool ) { } + void TrackElement::setSourceDogLeg ( bool ) { } + void TrackElement::setTargetDogLeg ( bool ) { } + TrackElement* TrackElement::getCanonical ( Interval& i ) { i=Interval(getSourceU(),getTargetU()); return this; } + bool TrackElement::canSlacken () const { return false; } + + + bool TrackElement::canDesalignate () const { return false; } + bool TrackElement::canPivotUp () const { return false; }; + bool TrackElement::canMoveUp () const { return false; }; + bool TrackElement::canDogLeg () { return false; }; + bool TrackElement::canDogLeg ( Interval ) { return false; }; + bool TrackElement::canDogLegAt ( GCell*, bool allowReuse ) { return false; }; + TrackElement* TrackElement::getSourceDogLeg () { return NULL; } + TrackElement* TrackElement::getTargetDogLeg () { return NULL; } + void TrackElement::dataInvalidate () { } + void TrackElement::eventInvalidate () { } + void TrackElement::setGCell ( GCell* ) { } + void TrackElement::setArea () { } + void TrackElement::setRouted ( bool ) { } + void TrackElement::setTrack ( Track* track ) { _track = track; } + void TrackElement::setDogLegLevel ( unsigned int ) { } + void TrackElement::setDogLegOrder ( unsigned int ) { } + void TrackElement::updateGCellsStiffness ( unsigned int ) { } + void TrackElement::swapTrack ( TrackElement* ) { } + void TrackElement::reschedule ( unsigned int ) { } + void TrackElement::detach () { } + void TrackElement::revalidate ( bool invalidEvent ) { } + void TrackElement::setAxis ( DbU::Unit, unsigned int flags ) { } + void TrackElement::slacken () { } + bool TrackElement::moveUp () { return false; } + bool TrackElement::moveAside ( bool onLeft ) { return false; } + TrackElement* TrackElement::makeDogLeg () { return NULL; } + TrackElement* TrackElement::makeDogLeg ( Interval, bool& leftDogleg ) { return NULL; } + TrackElement* TrackElement::makeDogLeg ( GCell* ) { return NULL; } + TrackElement* TrackElement::_postDogLeg ( GCell* ) { return NULL; } + void TrackElement::_postModify () { } + void TrackElement::desalignate () { } + bool TrackElement::_check () const { return true; } + + + TrackElement::TrackElement ( Track* track ) + : _track(track) + , _index((size_t)-1) + { } + + + void TrackElement::_postCreate () + { } + + + TrackElement::~TrackElement () + { } + + + void TrackElement::_preDestroy () + { } + + + void TrackElement::destroy () + { + _preDestroy (); + delete this; + } + + + TrackElement* TrackElement::getNext () const + { + size_t dummy = _index; + return _track->getNext ( dummy, getNet() ); + } + + + TrackElement* TrackElement::getPrevious () const + { + size_t dummy = _index; + return _track->getPrevious ( dummy, getNet() ); + } + + + Interval TrackElement::getFreeInterval ( bool useOrder ) const + { + if ( !_track ) return Interval(false); + + size_t begin = _index; + size_t end = _index; + return _track->expandFreeInterval ( begin, end, Track::Inside, getNet(), useOrder ); + } + + + size_t TrackElement::getGCells ( vector& gcells ) const + { + vector().swap ( gcells ); + return gcells.size(); + } + + + size_t TrackElement::getPerpandicularsBound ( set& bounds ) + { + bounds.clear (); + return 0; + } + + + unsigned int TrackElement::getOrder () const + { return numeric_limits::max(); } + + + void TrackElement::incOverlapCost ( Net* net, TrackCost& cost ) const + { + if ( not _track or (getNet() == net) ) return; + + _overlapCostCallback ( this, cost ); + } + + + string TrackElement::_getTypeName () const + { return "TrackElement"; } + + + string TrackElement::_getString () const + { return "<" + _getTypeName() + ">"; } + + + Record* TrackElement::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot ( "_track", _track ) ); + record->add ( getSlot ( "_index", _index ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackElements.cpp b/kite/src/TrackElements.cpp new file mode 100644 index 00000000..7cbfa36f --- /dev/null +++ b/kite/src/TrackElements.cpp @@ -0,0 +1,148 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackElements.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "hurricane/Bug.h" +#include "hurricane/Interval.h" +#include "kite/Session.h" +#include "kite/TrackElement.h" + + +namespace Kite { + + + using namespace std; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::ForEachIterator; + using Hurricane::Interval; + using Hurricane::Bug; + + +// ------------------------------------------------------------------- +// Class : "TrackElements_CollapsedPerpandicular". + + + TrackElements_CollapsedPerpandicular::Locator::Locator ( TrackElement* segment ) + : TrackElementHL () + , _locator (segment->base()) + , _element (NULL) + { + ltrace(80) << "TrackElements_CollapsedPerpandicular::Locator::Locator()" << endl; + ltrace(80) << " " << segment << endl; + + Interval bounds; + if ( _locator.isValid() ) { + _element = Session::lookup ( _locator.getElement()->getCanonical(bounds)->base() ); + if ( !_element ) { + cerr << Bug("Canonical segment whithout TrackElement.") << endl; + progress (); + } + } + } + + + TrackElement* TrackElements_CollapsedPerpandicular::Locator::getElement () const + { return _element; } + + + void TrackElements_CollapsedPerpandicular::Locator::progress () + { + ltrace(80) << "TrackElements_CollapsedPerpandicular::Locator::progress()" << endl; + + Interval bounds; + while ( _locator.isValid() ) { + _locator.progress (); + + if ( _locator.isValid() ) { + _element = Session::lookup ( _locator.getElement()->getCanonical(bounds)->base() ); + if ( !_element ) { + cerr << Bug("Canonical segment whithout TrackElement.") << endl; + continue; + } + + break; + } + } + } + + + TrackElementHL* TrackElements_CollapsedPerpandicular::Locator::getClone () const + { return new Locator(*this); } + + + bool TrackElements_CollapsedPerpandicular::Locator::isValid () const + { return _locator.isValid(); } + + + TrackElementHC* TrackElements_CollapsedPerpandicular::getClone () const + { return new TrackElements_CollapsedPerpandicular(*this); } + + + TrackElementHL* TrackElements_CollapsedPerpandicular::getLocator () const + { return new Locator(_segment); } + + + string TrackElements_CollapsedPerpandicular::Locator::_getString () const + { + string s = ""; + return s; + } + + + string TrackElements_CollapsedPerpandicular::_getString () const + { + string s = ""; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "TrackElements_UniqCanonical". + + + TrackElementHF* TrackElements_UniqCanonical::getClone () const + { return new TrackElements_UniqCanonical(_canonicals); } + + + bool TrackElements_UniqCanonical::accept ( TrackElement* segment ) const + { + if ( _canonicals.find(segment) == _canonicals.end() ) { + _canonicals.insert ( segment ); + return true; + } + + return false; + } + + + string TrackElements_UniqCanonical::_getString () const + { return ""; } + + +} // End of Kite namespace. diff --git a/kite/src/TrackFixedSegment.cpp b/kite/src/TrackFixedSegment.cpp new file mode 100644 index 00000000..3fb98c70 --- /dev/null +++ b/kite/src/TrackFixedSegment.cpp @@ -0,0 +1,220 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackFixedSegment.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "hurricane/RegularLayer.h" +#include "hurricane/Technology.h" +#include "hurricane/DataBase.h" +#include "hurricane/Horizontal.h" +#include "hurricane/Vertical.h" +#include "katabatic/AutoContact.h" +#include "crlcore/RoutingGauge.h" +#include "kite/GCell.h" +#include "kite/DataNegociate.h" +#include "kite/TrackFixedSegment.h" +#include "kite/TrackCost.h" +#include "kite/Track.h" +#include "kite/Session.h" +#include "kite/RoutingEvent.h" +#include "kite/NegociateWindow.h" +#include "kite/GCellGrid.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using namespace std; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::tab; + using Hurricane::Warning; + using Hurricane::ForEachIterator; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Net; + using Hurricane::Name; + using Hurricane::RegularLayer; + using Hurricane::Technology; + using Hurricane::DataBase; + using Hurricane::Horizontal; + using Hurricane::Vertical; + + +// ------------------------------------------------------------------- +// Class : "TrackFixedSegment". + + + TrackFixedSegment::TrackFixedSegment ( Track* track, Segment* segment ) + : TrackElement (NULL) + , _segment (segment) + { + Box boundingBox = segment->getBoundingBox(); + + if ( track ) { + unsigned int depth = track->getDepth(); + Technology* technology = DataBase::getDB()->getTechnology(); + const Layer* layer1 = track->getLayer()->getBlockageLayer(); + RegularLayer* layer2 = dynamic_cast(technology->getLayer(layer1->getMask())); + if ( layer2 ) { + DbU::Unit extention = layer2->getExtentionCap(); + if ( track->getDirection() == Constant::Horizontal ) { + _sourceU = boundingBox.getXMin()-extention; + _targetU = boundingBox.getXMax()+extention; + + GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell ( Point(_sourceU,track->getAxis()) ); + GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell ( Point(_targetU,track->getAxis()) ); + GCell* right = NULL; + if ( gcell ) { + while ( gcell and (gcell != end) ) { + right = gcell->getRight(); + if ( right == NULL ) break; + gcell->addBlockage ( depth, 1.0 ); + gcell = right; + } + if ( end ) end->addBlockage ( depth, 1.0 ); + } else + cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl; + } else { + _sourceU = boundingBox.getYMin()-extention; + _targetU = boundingBox.getYMax()+extention; + + GCell* gcell = track->getKiteEngine()->getGCellGrid()->getGCell ( Point(track->getAxis(),_sourceU) ); + GCell* end = track->getKiteEngine()->getGCellGrid()->getGCell ( Point(track->getAxis(),_targetU) ); + GCell* up = NULL; + if ( gcell ) { + while ( gcell and (gcell != end) ) { + up = gcell->getUp(); + if ( up == NULL ) break; + gcell->addBlockage ( depth, 1.0 ); + gcell = up; + } + if ( end ) end->addBlockage ( depth, 1.0 ); + } else + cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl; + } + } + } + } + + + void TrackFixedSegment::_postCreate () + { TrackElement::_postCreate (); } + + + TrackFixedSegment::~TrackFixedSegment () + { } + + + void TrackFixedSegment::_preDestroy () + { + ltrace(90) << "TrackFixedSegment::_preDestroy() - " << (void*)this << endl; + TrackElement::_preDestroy (); + } + + + TrackElement* TrackFixedSegment::create ( Track* track, Segment* segment ) + { + TrackFixedSegment* trackFixedSegment = NULL; + if ( track ) { + trackFixedSegment = new TrackFixedSegment ( track, segment ); + trackFixedSegment->_postCreate (); + Session::addInsertEvent ( trackFixedSegment, track ); + + ltrace(190) << "Adding: " << segment << " on " << track << endl; + ltrace(200) << "TrackFixedSegment::create(): " << trackFixedSegment << endl; + } + return trackFixedSegment; + } + + + AutoSegment* TrackFixedSegment::base () const { return NULL; } + bool TrackFixedSegment::isFixed () const { return true; } + bool TrackFixedSegment::isBlockage () const { return true; } + DbU::Unit TrackFixedSegment::getAxis () const { return getTrack()->getAxis(); } + bool TrackFixedSegment::isHorizontal () const { return getTrack()->isHorizontal(); } + bool TrackFixedSegment::isVertical () const { return getTrack()->isVertical(); } + unsigned int TrackFixedSegment::getDirection () const { return getTrack()->getDirection(); } + Net* TrackFixedSegment::getNet () const { return _segment->getNet(); } + const Layer* TrackFixedSegment::getLayer () const { return _segment->getLayer(); } + Interval TrackFixedSegment::getFreeInterval ( bool useOrder ) const { return Interval(); } + + + unsigned long TrackFixedSegment::getId () const + { + cerr << Error("::getId() called on %s.",_getString().c_str()) << endl; + return 0; + } + + + TrackElement* TrackFixedSegment::getNext () const + { + size_t dummy = _index; + return _track->getNext ( dummy, getNet() ); + } + + + TrackElement* TrackFixedSegment::getPrevious () const + { + size_t dummy = _index; + return _track->getPrevious ( dummy, getNet() ); + } + + + string TrackFixedSegment::_getTypeName () const + { return "TrackFixedSegment"; } + + + string TrackFixedSegment::_getString () const + { + string s1 = _segment->_getString(); + string s2 = " [" + DbU::getValueString(_sourceU) + + ":" + DbU::getValueString(_targetU) + "]" + + " " + DbU::getValueString(_targetU-_sourceU) + + " [" + ((_track) ? getString(_index) : "npos") + "]"; + s1.insert ( s1.size()-1, s2 ); + + return s1; + } + + + Record* TrackFixedSegment::_getRecord () const + { + Record* record = TrackElement::_getRecord (); + record->add ( getSlot ( "_segment", _segment ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackMarker.cpp b/kite/src/TrackMarker.cpp new file mode 100644 index 00000000..92b58292 --- /dev/null +++ b/kite/src/TrackMarker.cpp @@ -0,0 +1,145 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackMarker.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/RoutingPad.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "crlcore/RoutingGauge.h" +#include "kite/GCell.h" +#include "kite/TrackMarker.h" +#include "kite/Track.h" +#include "kite/RoutingPlane.h" +#include "kite/Session.h" +#include "kite/RoutingEvent.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::ostringstream; + using std::setprecision; + using Hurricane::Bug; + using CRL::RoutingGauge; + + + TrackMarker* TrackMarker::create ( RoutingPad* rp, size_t depth ) + { + TrackMarker* segment = new TrackMarker ( rp, depth ); + return segment; + } + + + void TrackMarker::destroy () + { + if ( !--_refcount ) delete this; + } + + + TrackMarker::TrackMarker ( RoutingPad* pad, size_t depth ) + : _routingPad (pad) + , _sourcePosition(0) + , _targetPosition(0) + , _track (NULL) + , _weight (0) + , _refcount (0) + { + Point sourcePoint = pad->getSourcePosition(); + Point targetPoint = pad->getTargetPosition(); + RoutingGauge* rg = Session::getKiteEngine()->getRoutingGauge(); + RoutingPlane* rp = Session::getKiteEngine()->getRoutingPlaneByIndex(depth); + unsigned int rpDirection = rg->getLayerDirection(depth); + Interval trackSpan; + + if ( rpDirection == Constant::Horizontal ) { + _sourcePosition = sourcePoint.getX(); + _targetPosition = targetPoint.getX(); + trackSpan = Interval ( sourcePoint.getY(), targetPoint.getY() ); + } else { + _sourcePosition = sourcePoint.getY(); + _targetPosition = targetPoint.getY(); + trackSpan = Interval ( sourcePoint.getX(), targetPoint.getX() ); + } + + if ( rpDirection xor rg->getLayerDirection(rg->getLayerDepth(pad->getLayer())) ) { + _weight = (unsigned int)(( 5.0 / (5.0+DbU::getLambda(trackSpan.getSize())) ) * 100.0) ; + } else { + _weight = (unsigned int)( (5.0 + DbU::getLambda(trackSpan.getSize())) * 20.0 ); + } + + Track* track = rp->getTrackByPosition ( trackSpan.getVMin() ); + while ( track && (track->getAxis() <= trackSpan.getVMax()) ) { + Session::addInsertEvent ( this, track ); + track = track->getNext (); + _refcount++; + } + } + + + Net* TrackMarker::getNet () const + { return _routingPad->getNet(); } + + + string TrackMarker::_getTypeName () const + { return "TrackMarker"; } + + + string TrackMarker::_getString () const + { + ostringstream s; + s << "<" << _getTypeName() + << " " << getNet()->getName() + << " [" << DbU::getValueString(_sourcePosition) + << ":" << DbU::getValueString(_targetPosition) + << " " << setprecision(3) << ((double)_weight)/100.0 + << ">"; + return s.str(); + } + + + Record* TrackMarker::_getRecord () const + { + Record* record = new Record ( _getString() ); + record->add ( getSlot ( "_routingPad" , _routingPad ) ); + record->add ( getSlot ( "_sourcePosition", _sourcePosition ) ); + record->add ( getSlot ( "_targetPosition", _targetPosition ) ); + record->add ( getSlot ( "_track" , _track ) ); + record->add ( getSlot ( "_weight" , _weight ) ); + + return record; + } + + + +} // End of Kite namespace. diff --git a/kite/src/TrackSegment.cpp b/kite/src/TrackSegment.cpp new file mode 100644 index 00000000..f89c30e7 --- /dev/null +++ b/kite/src/TrackSegment.cpp @@ -0,0 +1,1192 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackSegment.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include + +#include "hurricane/Bug.h" +#include "hurricane/Warning.h" +#include "hurricane/Net.h" +#include "hurricane/Name.h" +#include "katabatic/AutoContact.h" +#include "crlcore/RoutingGauge.h" +#include "kite/GCell.h" +#include "kite/DataNegociate.h" +#include "kite/TrackSegment.h" +#include "kite/TrackCost.h" +#include "kite/Track.h" +#include "kite/Session.h" +#include "kite/RoutingEvent.h" +#include "kite/NegociateWindow.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using namespace std; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::tab; + using Hurricane::ForEachIterator; + using Hurricane::Bug; + using Hurricane::Error; + using Hurricane::Net; + using Hurricane::Name; + + +// ------------------------------------------------------------------- +// Class : "TrackSegment". + + + TrackSegment::TrackSegment ( AutoSegment* segment, Track* track ) + : TrackElement (track) + , _base (segment) + , _gcell (NULL) + , _created (true) + , _lock (true) + , _revalidated (false) + , _sourceDogLeg (false) + , _targetDogLeg (false) + , _canRipple (false) + , _routed (false) + , _area (0) + , _data (NULL) + , _dogLegLevel (0) + , _dogLegOrder (0) + { + if (segment) { + _data = new DataNegociate ( this ); + _base->getCanonical ( _sourceU, _targetU ); + setArea (); + //update (); + } + } + + + void TrackSegment::_postCreate () + { + TrackElement::_postCreate (); + Session::link ( this ); + + vector gcells; + getGCells ( gcells ); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + } + + + TrackSegment::~TrackSegment () + { + if ( _data ) delete _data; + } + + + void TrackSegment::_preDestroy () + { + ltrace(90) << "TrackSegment::_preDestroy() - " << (void*)this + << " [" << (void*)_base << ", " + << (void*)(_base?_base->base():NULL) << "]" << endl; + + Session::unlink ( this ); + + TrackElement::_preDestroy (); + } + + + TrackElement* TrackSegment::create ( AutoSegment* segment, Track* track, bool& created ) + { + created = false; + + TrackElement* trackElement = Session::lookup ( segment->base() ); + if ( !trackElement ) { + TrackSegment* trackSegment = new TrackSegment ( segment, track ); + trackSegment->_postCreate (); + created = true; + + trackSegment->invalidate (); + + ltrace(200) << "TrackSegment::create(): " << trackSegment << endl; + trackElement = trackSegment; + } + + return trackElement; + } + + +// Formerly Inline Functions. + AutoSegment* TrackSegment::base () const { return _base; } + bool TrackSegment::isCreated () const { return _created; } + bool TrackSegment::isFixed () const { return _base->isFixed(); } + bool TrackSegment::isStrap () const { return _base->isCanonicalStrap(); } + bool TrackSegment::isSlackenStrap () const { return _base->isSlackenStrap(); } + bool TrackSegment::isLocal () const { return _base->isCanonicalLocal(); } + bool TrackSegment::isGlobal () const { return !isLocal(); } + bool TrackSegment::isLocked () const { return _lock; } + bool TrackSegment::isTerminal () const { return _base->isTerminal(); } + bool TrackSegment::isRevalidated () const { return _revalidated; } + bool TrackSegment::isRouted () const { return _routed; } + bool TrackSegment::isSlackened () const { return _base->isSlackened(); } + bool TrackSegment::isSlackenDogLeg () const { return isSlackened() and (_dogLegLevel > 0); } + bool TrackSegment::hasSourceDogLeg () const { return _sourceDogLeg; } + bool TrackSegment::hasTargetDogLeg () const { return _targetDogLeg; } + bool TrackSegment::allowOutsideGCell () const { return _base->allowOutsideGCell(); } + bool TrackSegment::canGoOutsideGCell () const { return _base->canGoOutsideGCell(); } + bool TrackSegment::canRipple () const { return _canRipple; } + unsigned long TrackSegment::getId () const { return _base->getId(); } + GCell* TrackSegment::getGCell () const { return _gcell; } + DbU::Unit TrackSegment::getAxis () const { return _base->getAxis(); } + unsigned long TrackSegment::getArea () const { return _area; } + unsigned int TrackSegment::getDogLegLevel () const { return _dogLegLevel; } + unsigned int TrackSegment::getDogLegOrder () const { return _dogLegOrder; } + Interval TrackSegment::getSourceConstraints () const { return _base->getSourceConstraints(); } + Interval TrackSegment::getTargetConstraints () const { return _base->getTargetConstraints(); } + DataNegociate* TrackSegment::getDataNegociate () const { return _data; } + TrackElements TrackSegment::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(this); } + void TrackSegment::setAllowOutsideGCell ( bool state ) { _base->setAllowOutsideGCell(state,true); } + void TrackSegment::setLock ( bool state ) { _lock = state; } + void TrackSegment::setRevalidated ( bool state ) { _revalidated = state; } + void TrackSegment::invalidate () { _base->invalidate(); } + void TrackSegment::setCanRipple ( bool state ) { _canRipple = state; } + void TrackSegment::setSourceDogLeg ( bool state ) { _sourceDogLeg = state; } + void TrackSegment::setTargetDogLeg ( bool state ) { _targetDogLeg = state; } + + + TrackElement* TrackSegment::getCanonical ( Interval& i ) + { return Session::lookup ( _base->getCanonical(i)->base() ); } + + + bool TrackSegment::canSlacken () const + { return (not isSlackened())?(_base->canSlacken(true)):false; } + + + bool TrackSegment::isHorizontal () const + { return _base->isHorizontal(); } + + + bool TrackSegment::isVertical () const + { return _base->isVertical(); } + + + unsigned int TrackSegment::getDirection () const + { return _base->getDirection(); } + + + Net* TrackSegment::getNet () const + { return _base->getNet(); } + + + const Layer* TrackSegment::getLayer () const + { return _base->getLayer(); } + + + // DbU::Unit TrackSegment::getSourceU () const + // { return _base->getSourceU(); } + + + // DbU::Unit TrackSegment::getTargetU () const + // { return _base->getTargetU(); } + + + TrackElement* TrackSegment::getNext () const + { + size_t dummy = _index; + + return _track->getNext ( dummy, getNet() ); + } + + + TrackElement* TrackSegment::getPrevious () const + { + size_t dummy = _index; + + return _track->getPrevious ( dummy, getNet() ); + } + + + Interval TrackSegment::getFreeInterval ( bool useOrder ) const + { + if ( !_track ) return Interval(false); + + size_t begin = _index; + size_t end = _index; + + return _track->expandFreeInterval ( begin, end, Track::Inside, getNet(), useOrder ); + } + + + size_t TrackSegment::getGCells ( vector& gcells ) const + { + vector().swap ( gcells ); + + GCell* sourceGCell = Session::lookup(base()->getAutoSource()->getGCell()); + GCell* targetGCell = Session::lookup(base()->getAutoTarget()->getGCell()); + + ltrace(148) << "getGCells(): sourceGCell: " << sourceGCell << endl; + ltrace(148) << "getGCells(): targetGCell: " << targetGCell << endl; + + forEach ( AutoSegment*, isegment, base()->getCollapseds() ) { + GCell* gcell = Session::lookup(isegment->getAutoSource()->getGCell()); + if ( gcell->getIndex() < sourceGCell->getIndex() ) { + sourceGCell = gcell; + ltrace(148) << "getGCells(): new sourceGCell: " << sourceGCell << endl; + } + + gcell = Session::lookup(isegment->getAutoTarget()->getGCell()); + if ( gcell->getIndex() > targetGCell->getIndex() ) { + targetGCell = gcell; + ltrace(148) << "getGCells(): new targetGCell: " << targetGCell << endl; + } + } + + if ( not sourceGCell or not targetGCell ) return 0; + if ( not sourceGCell ) { gcells.push_back ( targetGCell ); return 1; } + if ( not targetGCell ) { gcells.push_back ( sourceGCell ); return 1; } + + if ( isHorizontal() ) { + gcells.push_back ( sourceGCell ); + while ( sourceGCell != targetGCell ) { + sourceGCell = sourceGCell->getRight(); + if ( not sourceGCell ) break; + + //cerr << " Pushing: " << sourceGCell << endl; + gcells.push_back ( sourceGCell ); + } + } else { + gcells.push_back ( sourceGCell ); + while ( sourceGCell != targetGCell ) { + sourceGCell = sourceGCell->getUp(); + if ( not sourceGCell ) break; + + gcells.push_back ( sourceGCell ); + } + } + + return gcells.size(); + } + + + void TrackSegment::setGCell ( GCell* gcell ) + { + _gcell = gcell; + if (_data and not (_data->isBorder() or _data->isRing())) + _data->setGCellOrder( (_gcell) ? _gcell->getOrder() : (unsigned int)-1 ); + } + + + size_t TrackSegment::getPerpandicularsBound ( set& bounds ) + { + bounds.clear (); + + set baseBounds; + set::iterator ibase; + _base->getPerpandicularsBound ( baseBounds ); + + for ( ibase = baseBounds.begin() ; ibase != baseBounds.end() ; ibase++ ) { + TrackElement* segment = Session::lookup ( *ibase ); + if ( segment ) + bounds.insert ( segment ); + } + + return bounds.size(); + } + + + unsigned int TrackSegment::getOrder () const + { + if ( _data == NULL ) return numeric_limits::max(); + return _data->getGCellOrder (); + } + + + void TrackSegment::setDogLegLevel ( unsigned int level ) + { + if ( level > 15 ) { + cerr << Bug("%s has reached maximum dog leg count (15)." + ,_getString().c_str()) << endl; + level = 15; + } + + _dogLegLevel = level; + } + + + void TrackSegment::setDogLegOrder ( unsigned int order ) + { + ltrace(200) << "setDogLegOrder(): " << order << " " << this << endl; + + if ( order > 32768 ) { + cerr << Bug("%s has reached maximum dog leg order (32768)." + ,_getString().c_str()) << endl; + order = 32768; + } + + _dogLegOrder = order; + } + + + void TrackSegment::dataInvalidate () + { if (_data) _data->invalidate(); } + + + void TrackSegment::eventInvalidate () + { + if ( !_data ) return; + + RoutingEvent* event = _data->getRoutingEvent(); + if ( event ) event->invalidate ( true ); + } + + + void TrackSegment::setArea () + { + //float length = getValue ( getTargetU() - getSourceU() ); + //float height = getValue ( getSlack() ); + //_area = (unsigned long)( length * height ); + _area = _base->getSlack(); + } + + + void TrackSegment::setRouted ( bool state ) + { _routed = state; } + + + void TrackSegment::setTrack ( Track* track ) + { + TrackElement::setTrack ( track ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( ((track != NULL) ? TrackElement::Routed : TrackElement::UnRouted ) ); +#endif + } + + + void TrackSegment::detach () + { + ltrace(200) << "TrackSegment::detach() - " << endl; + + setTrack ( NULL ); + setIndex ( (size_t)-1 ); + setLock ( true ); + //updateGCellsStiffness ( TrackElement::UnRouted ); + } + + + void TrackSegment::revalidate ( bool invalidEvent ) + { + _created = false; + ltrace(148) << "revalidate() - " << this << endl; + + _base->getCanonical ( _sourceU, _targetU ); + _data->update (); + if ( invalidEvent ) + _data->invalidate ( true, true ); + + if ( _track ) Session::addSortEvent ( _track ); + + _revalidated = true; + } + + + void TrackSegment::setAxis ( DbU::Unit axis, unsigned int flags ) + { + _base->setAxis ( axis, flags ); + invalidate (); + } + + + void TrackSegment::updateGCellsStiffness ( unsigned int flags ) + { + if ( Session::getKiteEngine()->getState() > Katabatic::StateDriving ) return; + + vector gcells; + getGCells ( gcells ); + + int count = 0; + if ( flags & TrackElement::AddToGCells ) { + if ( getTrack() ) { flags |= TrackSegment::Routed; _routed = false; } + //cerr << "INC:"; + count = +1; + } + if ( flags & TrackElement::RemoveFromGCells ) { + if ( getTrack() ) { flags |= TrackSegment::UnRouted; _routed = true; } + //cerr << "DEC:"; + count = -1; + } + if ( count ) { + //cerr << count << " SegmentCount() for " << this << endl; + for ( size_t i=0 ; iincSegmentCount ( count ); + //cerr << "| " << gcells[i] << endl; + } + } + + count = 0; + if ( not _routed and (flags & TrackElement::Routed ) ) { count = +1; _routed = true; } + if ( _routed and (flags & TrackElement::UnRouted) ) { count = -1; _routed = false; } + + if ( count ) { + for ( size_t i=0 ; iincRoutedCount ( count ); + //cerr << "Update (" << count << ") " << gcells[i] << " for: " << this << endl; + } + } + } + + + void TrackSegment::swapTrack ( TrackElement* other ) + { + if ( !other ) return; + + ltrace(200) << "TrackSegment::swapTrack()" << endl; + + size_t thisIndex = getIndex (); + Track* thisTrack = getTrack (); + size_t otherIndex = other->getIndex (); + Track* otherTrack = other->getTrack (); + + if ( _track and otherTrack and (_track != otherTrack) ) { + cerr << Error("TrackSegment::swapTrack() - swapping TrackSement from different tracks.") << endl; + } + + // detach (); + // other->detach (); + // if ( thisTrack ) thisTrack ->insert ( other ); + // if ( otherTrack ) otherTrack->insert ( this ); + + setTrack ( NULL ); + other->setTrack ( NULL ); + // if ( _track ) updateGCellsStiffness ( TrackElement::UnRouted ); + // if ( otherTrack ) other->updateGCellsStiffness ( TrackElement::UnRouted ); + + //other->setRouted ( thisRouted ); + other->setTrack ( thisTrack ); + other->setIndex ( thisIndex ); + if ( thisTrack ) thisTrack->setSegment ( other, thisIndex ); + + //setRouted ( otherRouted ); + setTrack ( otherTrack ); + setIndex ( otherIndex ); + if ( _track ) _track->setSegment ( this, _index ); + +#if defined(CHECK_DATABASE_DISABLED) + if ( _track ) + _track->_check(); + else if ( other->getTrack() ) + other->getTrack()->_check(); +#endif + + RoutingEvent* thisEvent = getDataNegociate()->getRoutingEvent(); + RoutingEvent* otherEvent = other->getDataNegociate()->getRoutingEvent(); + + if ( thisEvent ) thisEvent ->setSegment ( other ); + if ( otherEvent ) otherEvent->setSegment ( this ); + + ltrace(200) << "| this: " << this << endl; + ltrace(200) << "| other: " << other << endl; + } + + + void TrackSegment::reschedule ( unsigned int level ) + { + ltrace(200) << "TrackSegment::reschedule() - " << this << endl; + ltracein(200); + ltrace(200) << "GCell: " << _gcell << endl; + ltrace(200) << "GCell::order:" << _gcell->getOrder() + << " Data::order:" << getOrder() + << " Session::order:" << Session::getOrder() << endl; + + if ( getOrder() == Session::getOrder() ) { + if ( not _data or not _data->hasRoutingEvent() ) + Session::getNegociateWindow()->addInsertEvent ( this, level ); + else { + if ( _track != NULL ) + Session::addRemoveEvent ( this ); + Session::getNegociateWindow()->rescheduleEvent ( _data->getRoutingEvent(), level ); + } + } else { + if ( _data and _data->hasRoutingEvent() ) + _data->getRoutingEvent()->setDisabled(); + } + ltraceout(200); + } + + + void TrackSegment::slacken () + { + if ( not isSlackened() ) { + ltrace(200) << "TrackSegment::slacken()" << endl; + ltracein(200); + + // set collapseds; + + // collapseds.insert ( _base ); + // forEach ( AutoSegment*, isegment, _base->getCollapseds() ) { + // collapseds.insert ( *isegment ); + // } + + //unsigned int direction = Constant::perpandicular ( getDirection() ); + //unsigned int doglegLevel = getDogLegLevel() + 1; + + //setSlackened ( true ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + base()->slacken ( true ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + _postModify (); + + // const vector& invalidateds = Session::getInvalidateds(); + // if ( not invalidateds.empty() ) { + // vector segments; + // for ( size_t i=0 ; ibase()->isTerminal() or (collapseds.find(segment->base()) != collapseds.end()) ) + // // segment->setSlackened ( true ); + + // if ( segment->isCreated() ) { + // //segment->setSlackened ( true ); + // if ( segment->getDirection() == direction ) { + // ltrace(200) << "Increasing dogleg level to: " << doglegLevel << endl; + // segment->setDogLegLevel ( doglegLevel ); + + // if ( segment->getOrder() > Session::getOrder() ) { + // ltrace(200) << "Adding to ring: " << segment << endl; + // Session::getNegociateWindow()->addToRing ( segment ); + // } + // } + // } + + // segment->reschedule ( 0 ); + // } + + // for ( size_t i=0 ; icanPivotUp(); + } + + + bool TrackSegment::canMoveUp () const + { + // if ( isLocal() /*and (hasSourceDogLeg() or hasTargetDogLeg())*/ ) { + // return _base->canPivotUp(); + // } + + return _base->canMoveUp ( true ); + } + + + bool TrackSegment::moveUp () + { + bool success = false; + + ltrace(160) << "TrackSegment::moveUp()" << endl; + ltracein(200); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + success = base()->moveUp ( true ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + const vector& invalidateds = Session::getInvalidateds(); + if ( not invalidateds.empty() ) { + vector segments; + for ( size_t i=0 ; ireschedule ( 0 ); + } + + for ( size_t i=0 ; isetState ( DataNegociate::ConflictSolve1, true ); + } + + ltraceout(200); + + return success; + } + + + bool TrackSegment::moveAside ( bool onLeft ) + { + bool success = true; + + ltrace(200) << "TrackSegment::moveAside() - " << (onLeft?"left":"right") << endl; + ltracein(200); + + unsigned int order = _data->getGCellOrder(); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + if ( onLeft ) base()->moveULeft (); + else base()->moveURight (); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + const vector& invalidateds = Session::getInvalidateds(); + if ( not invalidateds.empty() ) { + vector segments; + for ( size_t i=0 ; ireschedule ( 0 ); + } + + if ( _data->getGCellOrder() < order ) { + cinfo << "[INFO] Putting TrackSegment of order " << order + << " into GCell " << getGCell() << endl; + _data->setGCellOrder ( order ); + } + + for ( size_t i=0 ; igetAutoSource()->getSlaveComponents().getSubSet() ) { + dogleg = Session::lookup ( *isegment ); + if ( dogleg and (dogleg->getDirection() == direction) ) { + ltrace(200) << "Source dogleg: " << dogleg << endl; + return dogleg; + } + } + return NULL; + } + + + TrackElement* TrackSegment::getTargetDogLeg () + { + if ( !hasSourceDogLeg() ) return NULL; + + unsigned int direction = Constant::perpandicular ( getDirection() ); + TrackElement* dogleg = NULL; + forEach ( Segment*, isegment, base()->getAutoTarget()->getSlaveComponents().getSubSet() ) { + dogleg = Session::lookup ( *isegment ); + if ( dogleg and (dogleg->getDirection() == direction) ) { + ltrace(200) << "Target dogleg: " << dogleg << endl; + return dogleg; + } + } + return NULL; + } + + + bool TrackSegment::canDogLeg ( Interval interval ) + { + ltrace(200) << "TrackSegment::canDogLeg(Interval) " << interval << endl; + + if ( isFixed() ) { + ltrace(200) << "Failed: is fixed" << endl; + return false; + } + + if ( not isLocal() ) { + ltrace(200) << "Failed: is not local" << endl; + return false; + } + + if ( getDogLegOrder() < Session::getOrder() ) { + ltrace(200) << "No dogleg in current order " << Session::getOrder() + << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; + setDogLegOrder ( Session::getOrder() ); + setSourceDogLeg ( false ); + setTargetDogLeg ( false ); + } + if ( hasSourceDogLeg() or hasTargetDogLeg() or isSlackened() ) { + ltrace(200) << "Failed: already has source and/or target dogleg or slackened." << endl; + return false; + } + + return _base->canDogLeg(interval); + } + + + TrackElement* TrackSegment::makeDogLeg ( Interval interval, bool& leftDogleg ) + { + ltrace(200) << "TrackSegment::makeDogLeg(Interval)" << endl; + + bool upLayer = (Session::getRoutingGauge()->getLayerDepth(getLayer()) < 2); + + GCell* originalGCell = getGCell (); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + base()->makeDogLeg ( interval, upLayer, leftDogleg ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + return _postDogLeg ( originalGCell ); + } + + + bool TrackSegment::canDogLeg () + { + ltrace(200) << "TrackSegment::canDogLeg()" << endl; + + if ( not isLocal() ) { + ltrace(200) << "Failed: is not local." << endl; + return false; + } + + if ( isFixed() ) { + ltrace(200) << "Failed: is fixed." << endl; + return false; + } + + if ( isSlackened() ) { + ltrace(200) << "Failed: is local & slackened." << endl; + return false; + } + + if ( getDogLegOrder() < Session::getOrder() ) { + ltrace(200) << "No dogleg in current order " << Session::getOrder() + << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; + setDogLegOrder ( Session::getOrder() ); + setSourceDogLeg ( false ); + setTargetDogLeg ( false ); + } + if ( hasSourceDogLeg() || hasTargetDogLeg() ) return false; + + return true; + } + + + TrackElement* TrackSegment::makeDogLeg () + { + AutoContact* source = _base->getAutoSource(); + AutoContact* target = _base->getAutoTarget(); + GCell* gcell = Session::lookup ( _base->getAutoSource()->getGCell() ); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + TrackElement* dogleg = makeDogLeg ( gcell ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + if ( dogleg ) { + if ( source->isTerminal() xor target->isTerminal() ) { + if ( target->isTerminal() ) + source = target; + + DbU::Unit axis = (_base->isHorizontal()) ? source->getX() : source->getY(); + + ltrace(200) << "Setting dogleg axis @" << DbU::getValueString(axis) << endl; + dogleg->setAxis ( axis ); + } + return _postDogLeg(gcell); + } + + return NULL; + } + + + bool TrackSegment::canDogLegAt ( GCell* dogLegGCell, bool allowReuse ) + { + ltrace(200) << "TrackSegment::canDogLegAt(GCell*) " << dogLegGCell << endl; + + if ( getDogLegOrder() < Session::getOrder() ) { + ltrace(200) << "No dogleg in current order " << Session::getOrder() + << " yet, allowing (previous:" << _dogLegOrder << ")" << endl; + setDogLegOrder ( Session::getOrder() ); + setSourceDogLeg ( false ); + setTargetDogLeg ( false ); + } + + if ( isFixed() ) { + ltrace(200) << "Cannot dogleg a fixed segment." << endl; + return false; + } + + if ( isLocal() ) { + if ( hasSourceDogLeg() or hasTargetDogLeg() ) { + ltrace(200) << "Cannot dogleg again a local segment." << endl; + return false; + } + if ( isSlackened() ) { + ltrace(200) << "Cannot dogleg a local slackened segment." << endl; + return false; + } + } +// if ( Session::getRoutingGauge()->getLayerDepth(getLayer()) > 3 ) { +// ltrace(200) << "Cannot dogleg on the last top layer." << endl; +// return false; +// } + + vector gcells; + getGCells ( gcells ); + + ltrace(190) << "Source: " << *gcells.begin () << endl; + ltrace(190) << "Target: " << *gcells.rbegin() << endl; + + bool isGCellInside = false; + for ( size_t igcell=0 ; igcellgetUSide(getDirection(),false).intersect(getCanonicalInterval()) ) { + // ltrace(200) << "Segment is almost outside the breaking GCell." << endl; + // return false; + //} + + break; + } + + if ( not isGCellInside ) { + ltrace(200) << "dogleg GCell is outside segment support (go outside GCell active)." << endl; + return false; + } + + return true; + } + + + TrackElement* TrackSegment::makeDogLeg ( GCell* dogLegGCell ) + { + ltrace(200) << "TrackSegment::makeDogLeg(GCell*)" << endl; + ltrace(200) << "Break in: " << dogLegGCell << endl; + + bool upLayer = (Session::getRoutingGauge()->getLayerDepth(getLayer()) < 2); + + GCell* originalGCell = getGCell (); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + base()->makeDogLeg ( dogLegGCell->base(), upLayer ); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + return _postDogLeg ( originalGCell ); + } + + + TrackElement* TrackSegment::_postDogLeg ( GCell* originalGCell ) + { + ltracein(200); + + TrackElement* perpandicular = NULL; + + const vector& dogLegs = Session::getDogLegs(); + if ( not dogLegs.empty() ) { + vector segments; + for ( size_t i=0 ; ibase() == dogLegs[i])*/ ) + // segments[i]->setSlackened (true); + + segments[i]->setDogLegOrder ( Session::getOrder() ); + + switch ( i ) { + case 0: + segments[i]->setTargetDogLeg(); + segments[i]->getDataNegociate()->resetRipupCount(); + + if ( segments[i] != this ) { + cerr << Error ( "Incoherency in TrackSegment LUT, lookup of %p gives %p instead of %p (this)" + , dogLegs[i], segments[i], this + ) << endl; + } + break; + case 1: + perpandicular = segments[i]; + segments[i]->setSourceDogLeg (); + segments[i]->setTargetDogLeg (); + segments[i]->setDogLegLevel ( getDogLegLevel()+1 ); + break; + case 2: + segments[i]->setSourceDogLeg (); + break; + } + } + + ltrace(200) << "Before break: " << originalGCell << endl; + ltrace(200) << "After break: " << getGCell() << endl; + if ( getGCell() != originalGCell ) swapTrack ( segments[2] ); + + for ( size_t i=0 ; ireschedule ( ((i==1) ? 0 : 1) ); + if ( i == 1 ) { + ltrace(200) << "Set canDogleg: dogleg:" << segments[1]->getDataNegociate()->getGCellOrder() + << " vs. session:" << Session::getOrder() << endl; + + if ( segments[1]->getOrder() > Session::getOrder()) { + segments[i]->setCanRipple ( true ); + ltrace(200) << "Adding to ring: " << segments[i] << endl; + Session::getNegociateWindow()->addToRing ( segments[i] ); + } + } + //if ( i == 1 ) { + // RoutingEvent* event = segments[i]->getDataNegociate()->getRoutingEvent(); + // if ( event ) + // event->setCanGoOutsideGCell ( true ); + //} + } + + ltrace(200) << "original: " << segments[0] << endl; + ltrace(200) << "perpand: " << segments[1] << endl; + ltrace(200) << "new paral: " << segments[2] << endl; + } + + ltraceout(200); + + return perpandicular; + } + + + bool TrackSegment::canDesalignate () const + { + ltrace(200) << "TrackSegment::canDesalignate()" << endl; + + return _base->canDesalignate(); + +// Interval baseSpan = _base->getSpanU (); +// if ( baseSpan.getVMin() - Session::getExtensionCap() > _sourceCanonical ) return _base->canDesalignate(); +// if ( baseSpan.getVMax() + Session::getExtensionCap() < _targetCanonical ) return _base->canDesalignate(); + +// return false; + } + + + void TrackSegment::desalignate () + { + ltrace(200) << "TrackSegment::desalignate()" << endl; + ltracein(200); + +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::RemoveFromGCells ); +#endif + _base->desalignate (); +#if ENABLE_STIFFNESS + updateGCellsStiffness ( TrackElement::AddToGCells ); +#endif + + _postModify (); + + // const vector& invalidateds = Session::getInvalidateds(); + // if ( not invalidateds.empty() ) { + // vector segments; + // for ( size_t i=0 ; ireschedule ( 0 ); + + // if ( segments[i]->getDataNegociate()->getGCellOrder() > Session::getOrder() ) { + // ltrace(200) << "Adding to ring: " << segments[i] << endl; + // Session::getNegociateWindow()->addToRing ( segments[i] ); + // } + // } + + // for ( size_t i=0 ; i& invalidateds = Session::getInvalidateds(); + vector segments; + + if ( not invalidateds.empty() ) { + for ( size_t i=0 ; iisCreated() and (segment->getDirection() == perpandicularDir) ) { + ltrace(200) << "Increasing dogleg level to: " << doglegLevel << endl; + segment->setDogLegLevel ( doglegLevel ); + } + + if ( segment->getDataNegociate()->getGCellOrder() == Session::getOrder() ) { + if ( segment->getDirection() == parallelDir ) { + forEach ( TrackElement*, iperpandicular, segment->getCollapsedPerpandiculars() ) { + ltrace(200) << "| pp: " << *iperpandicular << endl; + + if ( iperpandicular->getDataNegociate()->getGCellOrder() == Session::getOrder() ) { + iperpandicular->reschedule ( 0 ); + } else if ( iperpandicular->getDataNegociate()->getGCellOrder() > Session::getOrder() ) { + ltrace(200) << "Adding to ring: " << *iperpandicular << endl; + Session::getNegociateWindow()->addToRing ( *iperpandicular ); + } + } + segment->reschedule ( 0 ); + } + } + } + + ltraceout(200); + } + + + bool TrackSegment::_check () const + { + if ( !base() ) return true; + + bool coherency = true; + + if ( !base()->isCanonical() ) { + cerr << "[CHECK] " << this << " supporting AutoSegment is not canonical." << endl; + coherency = false; + } + + DbU::Unit min; + DbU::Unit max; + base()->getCanonical ( min, max ); + if ( getSourceU() != min ) { + cerr << "[CHECK] " << this << " has bad source position " << DbU::getValueString(min) << "." << endl; + coherency = false; + } + if ( getTargetU() != max ) { + cerr << "[CHECK] " << this << " has bad target position " << DbU::getValueString(max) << "." << endl; + coherency = false; + } +#if ENABLE_STIFFNESS + if ( _routed xor (_track != NULL) ) { + cerr << "[CHECK] " << this << " incoherency between routed/track flags." << endl; + } +#endif + + return coherency; + } + + + string TrackSegment::_getTypeName () const + { return "TrackSegment"; } + + + string TrackSegment::_getString () const + { + string s1 = _base->_getString(); + string s2 = " [" + DbU::getValueString(_sourceU) + + ":" + DbU::getValueString(_targetU) + "]" + + " " + DbU::getValueString(_targetU-_sourceU) + + " " + getString(_dogLegLevel) + + " o:" + getString(_data->getGCellOrder()) + + " [" + ((_track) ? getString(_index) : "npos") + "] " + + ((isSlackened()) ? "S" : "-") + + ((_track ) ? "T" : "-") + + ((_canRipple ) ? "r" : "-") + + ((_sourceDogLeg) ? "s" : "-") + + ((_targetDogLeg) ? "t" : "-"); + + s1.insert ( s1.size()-1, s2 ); + + return s1; + } + + + Record* TrackSegment::_getRecord () const + { + Record* record = TrackElement::_getRecord (); + record->add ( getSlot ( "_base" , _base ) ); + record->add ( getSlot ( "_lock" , _lock ) ); + record->add ( getSlot ( "_revalidated", _revalidated ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/TrackSegmentCost.cpp b/kite/src/TrackSegmentCost.cpp new file mode 100644 index 00000000..7104aa44 --- /dev/null +++ b/kite/src/TrackSegmentCost.cpp @@ -0,0 +1,219 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./TrackSegmentCost.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#include +#include +#include +#include + +#include "hurricane/Bug.h" +#include "hurricane/DebugSession.h" +#include "katabatic/AutoSegment.h" +#include "kite/TrackElement.h" +#include "kite/TrackSegmentCost.h" + + +namespace Kite { + + + using std::cerr; + using std::endl; + using std::map; + using std::multimap; + using std::make_pair; + using std::ostringstream; + using Hurricane::Bug; + using Hurricane::DebugSession; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + using Hurricane::tab; + + +// ------------------------------------------------------------------- +// Class : "TrackSegmentCost". + + + TrackSegmentCost::TrackSegmentCost ( TrackElement* trackSegment ) + : _terminals (0) + , _ripupCount (0) + , _leftMinExtend (DbU::Max) + , _rightMinExtend(DbU::Min) + , _net (trackSegment->getNet()) + , _attractors () + { + //update ( trackSegment ); + } + + + TrackSegmentCost::~TrackSegmentCost () + { } + + + DbU::Unit TrackSegmentCost::getWiringDelta ( DbU::Unit axis ) const + { + DbU::Unit attraction = 0; + for ( size_t i=0 ; i < _attractors.size() ; i++ ) { + if ( _attractors[i] > axis ) attraction += _attractors[i] - axis; + else attraction += axis - _attractors[i]; + } + return attraction; + } + + + void TrackSegmentCost::update ( TrackElement* trackSegment ) + { + DebugSession::open ( trackSegment->getNet(), 148 ); + + ltrace(148) << "TrackSegmentCost::update() - " << trackSegment << endl; + ltracein(148); + + vector collapseds; + vector perpandiculars; + map attractorSpins; + + AutoSegment::getTopologicalInfos ( trackSegment->base() + , collapseds + , perpandiculars + , _leftMinExtend + , _rightMinExtend + ); + + _terminals = AutoSegment::getTerminalCount ( trackSegment->base(), collapseds ); + _attractors.clear (); + + for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) { + Interval interval; + TrackElement* perpandicular; + + if ( perpandiculars[i]->isCanonical() ) { + perpandicular = Session::lookup ( perpandiculars[i]->base() ); + if ( perpandicular ) + perpandicular->getCanonical ( interval ); + } else { + perpandicular = Session::lookup ( perpandiculars[i]->getCanonical(interval)->base() ); + } + + if ( !perpandicular ) { + cerr << Bug("Not a TrackSegment: %s:%s\n (perpandicular: %s:%s)" + ,getString((void*)perpandiculars[i]->getCanonical(interval)->base()).c_str() + ,getString(perpandiculars[i]->getCanonical(interval)).c_str() + ,getString((void*)perpandiculars[i]->base()).c_str() + ,getString(perpandiculars[i]).c_str() + ) << endl; + continue; + } + interval.inflate ( DbU::lambda(-1.5) ); + + ltrace(148) << "| perpandicular: " << perpandiculars[i] << endl; + ltrace(148) << "| canonical: " << perpandicular << endl; + ltracein(148); + ltrace(148) << "interval: " << interval << endl; + + if ( interval.isPonctual() ) { + ltrace(148) << "Punctual attractor @" << DbU::getValueString(interval.getVMin()) << endl; + _attractors.push_back ( interval.getVMin() ); + ltraceout(148); + continue; + } + + if ( ( interval.getVMin() != trackSegment->getAxis() ) + || AutoSegment::isTopologicalBound(perpandiculars[i] + ,false + ,perpandicular->isHorizontal() + ) ) { + map::iterator iattractor = attractorSpins.find ( interval.getVMin() ); + if ( iattractor == attractorSpins.end() ) { + attractorSpins.insert ( make_pair(interval.getVMin(),-1) ); + } else { + iattractor->second -= 1; + } + ltrace(148) << "Left attractor @" << DbU::getValueString(interval.getVMin()) << endl; + } + + if ( ( interval.getVMax() != trackSegment->getAxis() ) + || AutoSegment::isTopologicalBound(perpandiculars[i] + ,true + ,perpandicular->isHorizontal() + ) ) { + map::iterator iattractor = attractorSpins.find ( interval.getVMax() ); + if ( iattractor == attractorSpins.end() ) { + attractorSpins.insert ( make_pair(interval.getVMax(),1) ); + } else { + iattractor->second += 1; + } + ltrace(148) << "Right attractor @" << DbU::getValueString(interval.getVMax()) << endl; + } + + ltraceout(148); + } + + map::iterator iattractor = attractorSpins.begin(); + for ( ; iattractor != attractorSpins.end() ; iattractor++ ) { + if ( iattractor->second != 0 ) + _attractors.push_back ( iattractor->first ); + } + + ostringstream s; + s << "Attractors ["; + for ( size_t i=0 ; i<_attractors.size() ; i++ ) { + if ( i ) s << ", "; + s << DbU::getValueString(_attractors[i]); + } + s << "]"; + ltrace(148) << s.str() << endl; + + + ltraceout(148); + DebugSession::close (); + } + + + string TrackSegmentCost::_getString () const + { + return "<" + _getTypeName() + " " + + getString(_terminals) + + " [" + DbU::getValueString(_leftMinExtend) + + ":" + DbU::getValueString(_rightMinExtend) + + "]>"; + } + + + Record* TrackSegmentCost::_getRecord () const + { + Record* record = new Record ( getString(this) ); + record->add ( getSlot ( "_terminals" , _terminals ) ); + record->add ( getSlot ( "_ripupCount" , _ripupCount ) ); + record->add ( getSlot ( "_leftMinExtend" , &_leftMinExtend ) ); + record->add ( getSlot ( "_rightMinExtend", &_rightMinExtend ) ); + record->add ( getSlot ( "_net" , _net ) ); + + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/Tracks.cpp b/kite/src/Tracks.cpp new file mode 100644 index 00000000..112f1899 --- /dev/null +++ b/kite/src/Tracks.cpp @@ -0,0 +1,329 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./Tracks.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include + +#include "kite/Track.h" +#include "kite/Tracks.h" +#include "kite/RoutingPlane.h" + + +namespace Kite { + + + using std::cerr; + using std::endl; + using Hurricane::tab; + using Hurricane::inltrace; + using Hurricane::ltracein; + using Hurricane::ltraceout; + + +// ------------------------------------------------------------------- +// Class : "Tracks_Range::Locator". + + + Tracks_Range::Locator::Locator ( const RoutingPlane* routingPlane + , const Interval& constraints + ) + : Hurricane::Locator() + , _constraints (constraints) + { + ltrace(147) << "Tracks_Range::Locator()" << endl; + ltrace(147) << "* Constraints: " << _constraints << endl; + + _track = routingPlane->getTrackByPosition ( _constraints.getVMin() ); + + if ( _track && (_track->getAxis() < _constraints.getVMin()) ) _track = _track->getNext(); + if ( _track && (_track->getAxis() > _constraints.getVMax()) ) _track = NULL; + + ltrace(147) << "_track: " << _track << endl;; + } + + + Tracks_Range::Locator::Locator ( const Locator& locator ) + : Hurricane::Locator() + , _constraints(locator._constraints) + , _track (locator._track) + { } + + + Hurricane::Locator* Tracks_Range::Locator::getClone () const + { return new Locator(*this); } + + + bool Tracks_Range::Locator::isValid () const + { return (_track != NULL); } + + + Track* Tracks_Range::Locator::getElement () const + { return _track; } + + + + void Tracks_Range::Locator::progress () + { + if ( !_track ) return; + + _track = _track->getNext (); + if ( _track && (_track->getAxis() > _constraints.getVMax()) ) _track = NULL; + } + + + string Tracks_Range::Locator::_getString () const + { + string s = ""; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "Tracks_Range". + + + Tracks Tracks_Range::get ( RoutingPlane* routingPlane + , Interval& constraints ) + { return new Tracks_Range ( routingPlane, constraints ); } + + + Tracks_Range::Tracks_Range ( const RoutingPlane* routingPlane + , const Interval& constraints ) + : Collection() + , _routingPlane(routingPlane) + , _constraints (constraints) + { } + + + Tracks_Range::Tracks_Range ( const Tracks_Range& tracks ) + : Collection() + , _routingPlane(tracks._routingPlane) + , _constraints (tracks._constraints) + { } + + + Collection* Tracks_Range::getClone () const + { return new Tracks_Range(*this); } + + + Hurricane::Locator* Tracks_Range::getLocator () const + { return new Locator(_routingPlane,_constraints); } + + + string Tracks_Range::_getString () const + { + string s = "<" + _TName("Tracks_Range") + " " + + getString(_routingPlane->getLayer()) + " [" + + getString(_constraints.getVMin()) + ":" + + getString(_constraints.getVMax()) + "]" + + ">"; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "Tracks_Spiral::Locator". + + + Tracks_Spiral::Locator::Locator ( const RoutingPlane* routingPlane + , const Interval& optimal + , const Interval& constraints + ) + : Hurricane::Locator() + , _optimal (optimal) + , _constraints (constraints) + , _onMin (false) + , _inMinOptimal(true) + , _inMaxOptimal(true) + { + ltrace(147) << "Tracks_Spiral::Locator()" << endl; + ltrace(147) << "* Optimal: " << _optimal << endl; + ltrace(147) << "* Constraints: " << _constraints << endl; + + _minTrack = _maxTrack = routingPlane->getTrackByPosition ( _optimal.getCenter() ); + + if ( _minTrack->getAxis() < _constraints.getVMin() ) _minTrack = NULL; + if ( _maxTrack->getAxis() > _constraints.getVMax() ) _maxTrack = NULL; + + if ( _minTrack && !_maxTrack ) { + _minTrack = _minTrack->getPrevious (); + if ( _minTrack->getAxis() < _constraints.getVMin() ) _minTrack = NULL; + } + + if ( _maxTrack && !_minTrack ) { + _maxTrack = _maxTrack->getNext (); + if ( _maxTrack->getAxis() > _constraints.getVMax() ) _maxTrack = NULL; + } + + if ( _minTrack && (_minTrack->getAxis() < _optimal.getVMin()) ) _inMinOptimal = false; + if ( _maxTrack && (_maxTrack->getAxis() > _optimal.getVMax()) ) _inMaxOptimal = false; + + ltrace(147) << "_minTrack: " << _minTrack << endl;; + ltrace(147) << "_maxTrack: " << _maxTrack << endl;; + } + + + Tracks_Spiral::Locator::Locator ( const Locator& locator ) + : Hurricane::Locator() + , _optimal (locator._optimal) + , _constraints (locator._constraints) + , _minTrack (locator._minTrack) + , _maxTrack (locator._maxTrack) + , _onMin (locator._onMin) + , _inMinOptimal(locator._inMinOptimal) + , _inMaxOptimal(locator._inMaxOptimal) + { } + + + Hurricane::Locator* Tracks_Spiral::Locator::getClone () const + { return new Locator(*this); } + + + bool Tracks_Spiral::Locator::isValid () const + { return _minTrack||_maxTrack; } + + + Track* Tracks_Spiral::Locator::getElement () const + { + if ( !_minTrack ) return _maxTrack; + if ( !_maxTrack ) return _minTrack; + + return (_onMin) ? _maxTrack : _minTrack; + } + + + bool Tracks_Spiral::Locator::InOptimal () const + { return _inMinOptimal&&_inMaxOptimal; } + + + + void Tracks_Spiral::Locator::progress () + { + ltrace(147) << "Track_Spiral::progress() - State:" << endl; + ltracein(147); + ltrace(147) << _onMin + << " " << _minTrack + << " " << _maxTrack << endl; + + if ( !isValid() ) { + ltraceout(147); + return; + } + + if ( _onMin ) { + _onMin = (_maxTrack == NULL); + if ( _minTrack ) { + _minTrack = _minTrack->getPrevious(); + + if ( _minTrack ) { + if ( _minTrack->getAxis() < _optimal.getVMin() ) _inMinOptimal = false; + if ( _minTrack->getAxis() < _constraints.getVMin() ) _minTrack = NULL; + } + if ( !_minTrack && _maxTrack ) progress(); + } + } else { + _onMin = (_minTrack != NULL); + if ( _maxTrack ) { + _maxTrack = _maxTrack->getNext(); + + if ( _maxTrack ) { + if ( _maxTrack->getAxis() > _optimal.getVMax() ) _inMaxOptimal = false; + if ( _maxTrack->getAxis() > _constraints.getVMax() ) _maxTrack = NULL; + } + + if ( !_maxTrack && _minTrack ) progress(); + } + } + + ltrace(147) << _onMin + << " " << _minTrack + << " " << _maxTrack << endl; + ltraceout(147); + } + + + string Tracks_Spiral::Locator::_getString () const + { + string s = ""; + return s; + } + + +// ------------------------------------------------------------------- +// Class : "Tracks_Spiral". + + + Tracks Tracks_Spiral::get ( RoutingPlane* routingPlane + , Interval& optimal + , Interval& constraints ) + { return new Tracks_Spiral ( routingPlane, optimal, constraints ); } + + + Tracks_Spiral::Tracks_Spiral ( const RoutingPlane* routingPlane + , const Interval& optimal + , const Interval& constraints ) + : Collection() + , _routingPlane(routingPlane) + , _optimal (optimal) + , _constraints (constraints) + { } + + + Tracks_Spiral::Tracks_Spiral ( const Tracks_Spiral& tracks ) + : Collection() + , _routingPlane(tracks._routingPlane) + , _optimal (tracks._optimal) + , _constraints (tracks._constraints) + { } + + + Collection* Tracks_Spiral::getClone () const + { return new Tracks_Spiral(*this); } + + + Hurricane::Locator* Tracks_Spiral::getLocator () const + { return new Locator(_routingPlane,_optimal,_constraints); } + + + string Tracks_Spiral::_getString () const + { + string s = "<" + _TName("Tracks_Spiral") + " " + + getString(_routingPlane->getLayer()) + " [" + + getString(_constraints.getVMin()) + " (" + + getString(_optimal.getVMin()) + ":" + + getString(_optimal.getVMax()) + ") " + + getString(_constraints.getVMax()) + "]" + + ">"; + return s; + } + + +} // End of Katabatic namespace. diff --git a/kite/src/VerticalTrack.cpp b/kite/src/VerticalTrack.cpp new file mode 100644 index 00000000..e04ad0ba --- /dev/null +++ b/kite/src/VerticalTrack.cpp @@ -0,0 +1,83 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./VerticalTrack.cpp" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#include "kite/VerticalTrack.h" + + +namespace Kite { + + +// ------------------------------------------------------------------- +// Class : "VerticalTrack". + + + VerticalTrack::VerticalTrack ( RoutingPlane* routingPlane, unsigned int index ) + : Track(routingPlane,index) + { } + + + void VerticalTrack::_postCreate () + { } + + + VerticalTrack* VerticalTrack::create ( RoutingPlane* routingPlane, unsigned int index ) + { + VerticalTrack* track = new VerticalTrack ( routingPlane, index ); + + track->_postCreate (); + + return track; + } + + + VerticalTrack::~VerticalTrack () + { } + + + void VerticalTrack::_preDestroy () + { } + + + bool VerticalTrack::isHorizontal () const { return false; } + bool VerticalTrack::isVertical () const { return true; } + unsigned int VerticalTrack::getDirection () const { return Constant::Vertical; } + + + Point VerticalTrack::getPosition ( DbU::Unit coordinate ) const + { return Point ( getAxis(), coordinate ); } + + + string VerticalTrack::_getTypeName () const + { return "VerticalTrack"; } + + + Record* VerticalTrack::_getRecord () const + { + Record* record = Track::_getRecord (); + return record; + } + + +} // End of Kite namespace. diff --git a/kite/src/kite/Configuration.h b/kite/src/kite/Configuration.h new file mode 100644 index 00000000..6809a5ec --- /dev/null +++ b/kite/src/kite/Configuration.h @@ -0,0 +1,128 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./Configuration.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_CONFIGURATION__ +#define __KITE_CONFIGURATION__ + +#include + +#include "katabatic/Configuration.h" + + +namespace Kite { + + using std::string; + using Hurricane::Record; + using Hurricane::Layer; + using Hurricane::DbU; + using CRL::RoutingGauge; + using CRL::RoutingLayerGauge; + + +// ------------------------------------------------------------------- +// Class : "Kite::Configuration". + + + class Configuration : public Katabatic::Configuration { + public: + typedef boost::function< void(void) > PostEventCb_t; + public: + enum RipupTable { BorderRipupLimit =0 + , StrapRipupLimit =1 + , LocalRipupLimit =2 + , GlobalRipupLimit =3 + , LongGlobalRipupLimit=4 + , RipupLimitsTableSize=5 + }; + public: + static void setDefaultEdgeCapacity ( float ); + public: + // Constructor & Destructor. + Configuration ( Katabatic::Configuration* ); + ~Configuration (); + // Decorateds. + virtual bool isGMetal ( const Layer* ) const; + virtual size_t getDepth () const; + virtual size_t getLayerDepth ( const Layer* ) const; + virtual RoutingGauge* getRoutingGauge () const; + virtual RoutingLayerGauge* getLayerGauge ( size_t depth ) const; + virtual const Layer* getRoutingLayer ( size_t depth ) const; + virtual Layer* getContactLayer ( size_t depth ) const; + virtual DbU::Unit getExtensionCap () const; + virtual float getSaturateRatio () const; + virtual DbU::Unit getGlobalThreshold () const; + virtual void setSaturateRatio ( float ); + virtual void setGlobalThreshold ( DbU::Unit ); + // Methods. + inline Katabatic::Configuration* base (); + inline PostEventCb_t& getPostEventCb (); + inline float getExpandStep () const; + inline unsigned int getRipupCost () const; + unsigned int getRipupLimit ( unsigned int type ) const; + inline float getEdgeCapacityPercent () const; + inline void setExpandStep ( float ); + inline void setRipupCost ( unsigned int ); + void setRipupLimit ( unsigned int type, unsigned int limit ); + inline void setPostEventCb ( PostEventCb_t ); + inline void setEdgeCapacityPercent ( float ); + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + private: + // Static Attributes. + static float _defaultEdgeCapacity; + // Attributes. + Katabatic::Configuration* _base; + PostEventCb_t _postEventCb; + float _edgeCapacityPercent; + float _expandStep; + unsigned int _ripupLimits[RipupLimitsTableSize]; + unsigned int _ripupCost; + private: + Configuration ( const Configuration& ); + Configuration& operator= ( const Configuration& ); + }; + + +// Inline Functions. + inline Katabatic::Configuration* Configuration::base () { return _base; } + inline Configuration::PostEventCb_t& Configuration::getPostEventCb () { return _postEventCb; } + inline unsigned int Configuration::getRipupCost () const { return _ripupCost; } + inline float Configuration::getExpandStep () const { return _expandStep; } + inline float Configuration::getEdgeCapacityPercent () const { return _edgeCapacityPercent; } + inline void Configuration::setRipupCost ( unsigned int cost ) { _ripupCost = cost; } + inline void Configuration::setExpandStep ( float step ) { _expandStep = step; } + inline void Configuration::setPostEventCb ( PostEventCb_t cb ) { _postEventCb = cb; } + inline void Configuration::setEdgeCapacityPercent ( float percent ) { _edgeCapacityPercent = percent; } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::Configuration); + + +#endif // __KITE_CONFIGURATION__ diff --git a/kite/src/kite/DataNegociate.h b/kite/src/kite/DataNegociate.h new file mode 100644 index 00000000..41cd11b7 --- /dev/null +++ b/kite/src/kite/DataNegociate.h @@ -0,0 +1,177 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./DataNegociate.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_DATA_NEGOCIATE__ +#define __KITE_DATA_NEGOCIATE__ + +#include +#include + +namespace Hurricane { + class Record; +} + +#include "kite/TrackSegmentCost.h" +#include "kite/TrackElement.h" +#include "kite/RoutingEvent.h" +namespace Katabatic { + class AutoSegment; +} + + +namespace Kite { + + + using std::string; + using std::cerr; + using std::endl; + using Hurricane::Record; + using Katabatic::AutoSegment; + + class Track; + class TrackElement; + class RoutingEvent; + + +// ------------------------------------------------------------------- +// Class : "DataNegociate". + + + class DataNegociate { + + public: + enum SlackState { RipupPerpandiculars=1 + , Minimize + , DogLeg + , Desalignate + , Slacken + , ConflictSolve1 + , ConflictSolve2 + , LocalVsGlobal + , MoveUp + , MaximumSlack + , Unimplemented + }; + + public: + DataNegociate ( TrackElement* ); + ~DataNegociate (); + inline bool isRing () const; + inline bool isBorder () const; + inline bool isLeftBorder () const; + inline bool isRightBorder () const; + inline bool hasRoutingEvent () const; + inline RoutingEvent* getRoutingEvent () const; + inline TrackElement* getTrackSegment () const; + inline Track* getTrack () const; + inline TrackSegmentCost& getCost (); + inline unsigned int getGCellOrder () const; + //inline unsigned int getZ () const; + inline unsigned int getState () const; + inline unsigned int getStateCount () const; + inline unsigned int getRipupCount () const; + inline void setGCellOrder ( unsigned int ); + inline void setState ( unsigned int, bool reset=false ); + inline void setRing ( bool ); + inline void setLeftBorder ( bool ); + inline void setRightBorder ( bool ); + inline void resetBorder (); + inline void setRoutingEvent ( RoutingEvent* ); + inline void setRipupCount ( unsigned int ); + inline void incRipupCount (); + inline void decRipupCount (); + inline void resetRipupCount (); + inline void invalidate ( bool withPerpandiculars=false, bool withConstraints=false ); + void update (); + static string getStateString ( DataNegociate* ); + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + protected: + // Attributes. + RoutingEvent* _routingEvent; + TrackElement* _trackSegment; + TrackSegmentCost _cost; + unsigned int _gcellOrder; + unsigned int _state :5; + unsigned int _stateCount:5; + bool _leftBorder; + bool _rightBorder; + bool _ring; + //unsigned int _z : 5; + + private: + DataNegociate ( const DataNegociate& ); + DataNegociate& operator= ( const DataNegociate& ); + }; + + +// Inline Functions. + inline bool DataNegociate::isRing () const { return _ring; } + inline bool DataNegociate::isBorder () const { return _leftBorder or _rightBorder; } + inline bool DataNegociate::isLeftBorder () const { return _leftBorder; } + inline bool DataNegociate::isRightBorder () const { return _rightBorder; } + inline bool DataNegociate::hasRoutingEvent () const { return _routingEvent != NULL; } + inline RoutingEvent* DataNegociate::getRoutingEvent () const { return _routingEvent; } + inline TrackElement* DataNegociate::getTrackSegment () const { return _trackSegment; } + inline Track* DataNegociate::getTrack () const { return _trackSegment->getTrack(); } + inline TrackSegmentCost& DataNegociate::getCost () { return _cost; } + inline unsigned int DataNegociate::getGCellOrder () const { return _gcellOrder; } + inline unsigned int DataNegociate::getState () const { return _state; } + inline unsigned int DataNegociate::getStateCount () const { return _stateCount; } +//inline unsigned int DataNegociate::getZ () const { return _z; } + inline unsigned int DataNegociate::getRipupCount () const { return _cost.getRipupCount(); } + inline void DataNegociate::setGCellOrder ( unsigned int order ) { _gcellOrder = order; } + inline void DataNegociate::setRing ( bool state ) { _ring = state; } + inline void DataNegociate::setLeftBorder ( bool state ) { _leftBorder=state; } + inline void DataNegociate::setRightBorder ( bool state ) { _rightBorder=state; } + inline void DataNegociate::resetBorder () { _leftBorder=_rightBorder=false; } + inline void DataNegociate::setRoutingEvent ( RoutingEvent* event ) { _routingEvent = event; } + inline void DataNegociate::setRipupCount ( unsigned int count ) { _cost.setRipupCount(count); } + inline void DataNegociate::incRipupCount () { _cost.incRipupCount(); } + inline void DataNegociate::decRipupCount () { _cost.decRipupCount(); } + inline void DataNegociate::resetRipupCount () { _cost.resetRipupCount(); } + inline string DataNegociate::_getTypeName () const { return "DataNegociate"; } + + inline void DataNegociate::invalidate ( bool withPerpandiculars, bool withConstraints ) + { if (_routingEvent) _routingEvent->invalidate(withPerpandiculars,withConstraints); } + + inline void DataNegociate::setState ( unsigned int state, bool reset ) + { + if ( (_state != state) or reset ) { + _state = state; + _stateCount = 1; + } else + _stateCount++; + } + + +} // End of Kite namespace. + + +#endif // __KITE_DATA_NEGOCIATE__ diff --git a/kite/src/kite/GCell.h b/kite/src/kite/GCell.h new file mode 100644 index 00000000..521d82cc --- /dev/null +++ b/kite/src/kite/GCell.h @@ -0,0 +1,217 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./GCell.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_GCELL__ +#define __KITE_GCELL__ + +#include +#include +#include + +#include "hurricane/Collection.h" +namespace Hurricane { + class Name; +} + +#include "katabatic/GCell.h" + + +namespace Kite { + + + using std::vector; + using std::string; + using Hurricane::_TName; + using Hurricane::Record; + using Hurricane::Name; + using Hurricane::DbU; + using Hurricane::Point; + using Hurricane::Box; + using Hurricane::Interval; + using Hurricane::ExtensionGo; + using Hurricane::GenericCollection; + using Hurricane::GenericLocator; + using Hurricane::GenericFilter; + using Katabatic::AutoSegment; + using Katabatic::AutoContact; + + class TrackElement; + class GCellGrid; + + +// ------------------------------------------------------------------- +// Class : "GCell". + + + class GCell { + + public: + // Sub-Class: "CompareByDensity()". + class CompareByDensity { + public: + bool operator() ( GCell* lhs, GCell* rhs ); + }; + // Sub-Class: "CompareByStiffness()". + class CompareByStiffness { + public: + bool operator() ( GCell* lhs, GCell* rhs ); + }; + friend class Compare; + + public: + static bool areDensityConnex ( GCell* a, GCell* b ); + static GCell* getLowestOrder ( TrackElement* ); + static TrackElement* addTrackSegment ( GCell*, AutoSegment*, bool loading=false ); + static GCell* create ( GCellGrid*, Katabatic::GCell* ); + public: + void destroy (); + inline Katabatic::GCell* base (); + inline bool isInRoutingSet () const; + inline unsigned int getOrder () const; + inline const vector& getOwnedSegments () const; + inline void setInRoutingSet ( bool state ); + inline void setRouted ( bool state ); + inline TrackElement* getLeftRp ( size_t ) const; + inline TrackElement* getRightRp ( size_t ) const; + void addTrackSegment ( TrackElement* ); + void removeTrackSegment ( TrackElement* ); + void loadRouting ( unsigned int order ); + void computeBorder (); + double getOwnedWireLength () const; + public: + inline bool isAboveDensity ( float threshold ) const; + inline bool isRouted () const; + inline unsigned int getDepth () const; + inline unsigned int getIndex () const; + inline unsigned int getColumn () const; + inline unsigned int getRow () const; + inline Box getBoundingBox () const; + inline DbU::Unit getX () const; + inline DbU::Unit getY () const; + inline DbU::Unit getXMax () const; + inline DbU::Unit getYMax () const; + inline Interval getUSide ( unsigned int, bool noShrink ) const; + inline float getDensity ( size_t depth ) const; + inline float getCDensity () const; + inline float getDensity () const; + inline float getStiffness () const; + GCell* getLeft () const; + GCell* getRight () const; + GCell* getUp () const; + GCell* getDown () const; + inline vector* getVSegments (); + inline vector* getHSegments (); + inline vector* getContacts (); + inline unsigned int getSegmentCount () const; + inline unsigned int getRoutedCount () const; + inline void incSegmentCount ( int count ); + inline void incRoutedCount ( int count ); + inline void addBlockage ( unsigned int depth, float ); + void anticipateRouting ( unsigned int ); + inline size_t checkDensity () const; + inline size_t updateDensity (); + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + // Attributes. + GCellGrid* _gcellGrid; + Katabatic::GCell* _base; + vector _segments; + unsigned int _order; + bool _isInRoutingSet; + bool _isRouted; + TrackElement* _leftSegments [2]; + TrackElement* _rightSegments[2]; + + protected: + // Constructors & Destructors. + GCell ( GCellGrid*, Katabatic::GCell* ); + virtual ~GCell (); + private: + GCell ( const GCell& ); + GCell& operator= ( const GCell& ); + }; + + +// Inline Functions. + inline Katabatic::GCell* GCell::base () { return _base; } + inline bool GCell::isInRoutingSet () const { return _isInRoutingSet; } + inline bool GCell::isRouted () const { return _isRouted; } + inline bool GCell::isAboveDensity ( float threshold ) const { return _base->isAboveDensity(threshold); } + inline unsigned int GCell::getColumn () const { return _base->getColumn(); } + inline unsigned int GCell::getRow () const { return _base->getRow(); } + inline unsigned int GCell::getDepth () const { return _base->getDepth(); } + inline unsigned int GCell::getOrder () const { return _order; } + inline const vector& GCell::getOwnedSegments () const { return _segments; } + inline TrackElement* GCell::getLeftRp ( size_t i ) const { return _leftSegments[i]; } + inline TrackElement* GCell::getRightRp ( size_t i ) const { return _rightSegments[i]; } + inline void GCell::setInRoutingSet ( bool state ) { _isInRoutingSet = state; } + inline void GCell::setRouted ( bool state ) { _isRouted = state; } + inline unsigned int GCell::getIndex () const { return _base->getIndex(); } + inline Box GCell::getBoundingBox () const { return _base->getBoundingBox(); } + inline DbU::Unit GCell::getX () const { return _base->getX(); } + inline DbU::Unit GCell::getY () const { return _base->getY(); } + inline DbU::Unit GCell::getXMax () const { return _base->getXMax(); } + inline DbU::Unit GCell::getYMax () const { return _base->getYMax(); } + inline float GCell::getDensity ( size_t depth ) const { return _base->getDensity(depth); } + inline float GCell::getCDensity () const { return _base->getCDensity(); } + inline float GCell::getDensity () const { return _base->getDensity(); } + inline float GCell::getStiffness () const { return _base->getStiffness(); } + inline vector* GCell::getVSegments () { return _base->getVSegments(); } + inline vector* GCell::getHSegments () { return _base->getHSegments(); } + inline vector* GCell::getContacts () { return _base->getContacts(); } + inline unsigned int GCell::getSegmentCount () const { return _base->getSegmentCount(); } + inline unsigned int GCell::getRoutedCount () const { return _base->getRoutedCount(); } + inline void GCell::incSegmentCount ( int count ) { _base->incSegmentCount(count); } + inline void GCell::incRoutedCount ( int count ) { _base->incRoutedCount(count); } + inline void GCell::addBlockage ( unsigned int depth, float length ) { _base->addBlockage(depth,length); } + inline size_t GCell::checkDensity () const { return _base->checkDensity(); } + inline size_t GCell::updateDensity () { return _base->updateDensity(); } + + inline Interval GCell::getUSide ( unsigned int dir, bool noShrink ) const + { return _base->getUSide(dir).inflate((noShrink)?Katabatic::GCell::getTopRightShrink():0,0); } + + inline bool operator< ( const GCell& lhs, const GCell& rhs ) { return lhs.getIndex() < rhs.getIndex(); } + inline bool operator> ( const GCell& lhs, const GCell& rhs ) { return lhs.getIndex() > rhs.getIndex(); } + + +// ------------------------------------------------------------------- +// Collections. + + + typedef GenericCollection GCells; + typedef GenericLocator GCellLocator; + typedef GenericFilter GCellFilter; + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::GCell); + + +#endif // __KITE_GCELL__ diff --git a/kite/src/kite/GCellGrid.h b/kite/src/kite/GCellGrid.h new file mode 100644 index 00000000..dfff89dd --- /dev/null +++ b/kite/src/kite/GCellGrid.h @@ -0,0 +1,92 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./GCellGrid.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_GCELL_GRID__ +#define __KITE_GCELL_GRID__ + +namespace Hurricane { + class Cell; +} + +#include "katabatic/GCellGrid.h" +#include "kite/GCell.h" +#include "kite/KiteEngine.h" + + +namespace Kite { + + + using Hurricane::Cell; + class KiteEngine; + + +// ------------------------------------------------------------------- +// Class : "GCellGrid". + + + class GCellGrid : public Katabatic::Grid { + + public: + static GCellGrid* create ( KiteEngine* ); + public: + inline Katabatic::GCellGrid* base (); + inline KiteEngine* getKite (); + Cell* getCell () const; + inline bool checkEdgeSaturation ( float threshold ) const; + void updateContacts ( bool openSession=true ); + void updateDensity (); + double getTotalWireLength () const; + void _check () const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + KiteEngine* _kite; + + protected: + // Constructors & Destructors. + GCellGrid ( KiteEngine* ); + virtual ~GCellGrid (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + GCellGrid ( const GCellGrid& ); + GCellGrid& operator= ( const GCellGrid& ); + }; + + +// Inline Functions. + inline Katabatic::GCellGrid* GCellGrid::base () { return _kite->base()->getGCellGrid(); } + inline KiteEngine* GCellGrid::getKite () { return _kite; }; + + inline bool GCellGrid::checkEdgeSaturation ( float threshold ) const + { return const_cast(this)->base()->checkEdgeSaturation(threshold); } + + +} // End of Kite namespace. + + +#endif // __KITE_GCELL_GRID__ diff --git a/kite/src/kite/GCellRoutingSet.h b/kite/src/kite/GCellRoutingSet.h new file mode 100644 index 00000000..87f51225 --- /dev/null +++ b/kite/src/kite/GCellRoutingSet.h @@ -0,0 +1,158 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./GCellRoutingSet.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_GCELL_ROUTING_SET__ +#define __KITE_GCELL_ROUTING_SET__ + +#include + + +namespace Kite { + + using std::vector; + class TrackElement; + class GCell; + class GCellGrid; + + +// ------------------------------------------------------------------- +// Class : "Statistics". + + + class Statistics { + public: + inline Statistics (); + inline size_t getGCellsCount () const; + inline size_t getSegmentsCount () const; + inline size_t getEventsCount () const; + inline void setGCellsCount ( size_t ); + inline void setSegmentsCount ( size_t ); + inline void setEventsCount ( size_t ); + inline void incGCellCount ( size_t ); + inline void incSegmentsCount ( size_t ); + inline void incEventsCount ( size_t ); + inline Statistics& operator+= ( const Statistics& ); + private: + size_t _gcellsCount; + size_t _segmentsCount; + size_t _eventsCount; + + }; + + +// ------------------------------------------------------------------- +// Class : "GCellRoutingSet". + + + class GCellRoutingSet { + + public: + static GCellRoutingSet* create ( GCell*, float densityExpandRatio ); + virtual void destroy (); + inline unsigned int getOrder () const; + inline const vector& getGCells () const; + vector& getOwnedSegments ( vector& ) const; + unsigned int& loadRouting ( unsigned int& order ); + void loadBorder ( GCellGrid* ); + void freeBorder (); + void expand ( GCellGrid* ); + void setRouted ( bool ); + inline Statistics& getStatistics (); + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + private: + class BorderSegment { + public: + inline BorderSegment ( TrackElement*, unsigned int ); + public: + TrackElement* _segment; + unsigned int _order; + }; + + private: + // Attributes. + unsigned int _order; + float _minDensity; + float* _minDensities; + vector _gcells; + vector _borderSegments; + Statistics _statistics; + + protected: + // Constructors & Destructors. + GCellRoutingSet ( GCell*, float expandRatio, float minDensity ); + virtual ~GCellRoutingSet (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + GCellRoutingSet ( const GCellRoutingSet& ); + GCellRoutingSet& operator= ( const GCellRoutingSet& ); + }; + + +// Inline Functions. + inline unsigned int GCellRoutingSet::getOrder () const { return _order; } + inline const vector& GCellRoutingSet::getGCells () const { return _gcells; } + inline Statistics& GCellRoutingSet::getStatistics () { return _statistics; } + + inline GCellRoutingSet::BorderSegment::BorderSegment ( TrackElement* segment, unsigned int order ) + : _segment(segment) + , _order (order) + { } + + inline Statistics::Statistics () + : _gcellsCount (0) + , _segmentsCount (0) + , _eventsCount (0) + { } + + inline size_t Statistics::getGCellsCount () const { return _gcellsCount; } + inline size_t Statistics::getSegmentsCount () const { return _segmentsCount; } + inline size_t Statistics::getEventsCount () const { return _eventsCount; } + inline void Statistics::setGCellsCount ( size_t count ) { _gcellsCount = count; } + inline void Statistics::setSegmentsCount ( size_t count ) { _segmentsCount = count; } + inline void Statistics::setEventsCount ( size_t count ) { _eventsCount = count; } + inline void Statistics::incGCellCount ( size_t count ) { _gcellsCount += count; } + inline void Statistics::incSegmentsCount ( size_t count ) { _segmentsCount += count; } + inline void Statistics::incEventsCount ( size_t count ) { _eventsCount += count; } + + inline Statistics& Statistics::operator+= ( const Statistics& other ) + { + _gcellsCount += other._gcellsCount; + _segmentsCount += other._segmentsCount; + _eventsCount += other._eventsCount; + return *this; + } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::GCellRoutingSet); + + +#endif // __KITE_GCELL_ROUTING_SET__ diff --git a/kite/src/kite/GraphicKiteEngine.h b/kite/src/kite/GraphicKiteEngine.h new file mode 100644 index 00000000..308f2ac8 --- /dev/null +++ b/kite/src/kite/GraphicKiteEngine.h @@ -0,0 +1,111 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul Chaput | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./GraphicKiteEngine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + +#ifndef __KITE_GRAPHIC_KITE_ENGINE__ +#define __KITE_GRAPHIC_KITE_ENGINE__ + +#include + +namespace Hurricane { + class Go; + class BasicLayer; + class Transformation; + class CellWidget; + class CellViewer; +} + +#include "crlcore/GraphicToolEngine.h" +namespace CRL { + class RoutingGauge; +} + +#include "kite/KiteEngine.h" + + +namespace Kite { + + using Hurricane::Go; + using Hurricane::Box; + using Hurricane::BasicLayer; + using Hurricane::Transformation; + using Hurricane::CellWidget; + using Hurricane::CellViewer; + using CRL::RoutingGauge; + using CRL::GraphicTool; + + +// ------------------------------------------------------------------- +// Class : "CRL::GraphicKiteEngine". + + + class GraphicKiteEngine : public GraphicTool { + Q_OBJECT; + + public: + KiteEngine* createEngine ( const RoutingGauge* ); + KiteEngine* getForFramework (); + static void initKatabaticAc ( CellWidget* ); + static void drawKatabaticAc ( CellWidget* + , const Go* + , const BasicLayer* + , const Box& + , const Transformation& + ); + static void initKatabaticGCell ( CellWidget* ); + static void drawKatabaticGCell ( CellWidget* + , const Go* + , const BasicLayer* + , const Box& + , const Transformation& + ); + static GraphicKiteEngine* grab (); + virtual const Name& getName () const; + Cell* getCell (); + virtual size_t release (); + virtual void addToMenu ( CellViewer* ); + void postEvent (); + public slots: + void loadGlobalSolution (); + void saveGlobalSolution (); + void runGlobal (); + void runDetailed (); + void finalize (); + void save (); + + protected: + static size_t _references; + static GraphicKiteEngine* _singleton; + CellViewer* _viewer; + protected: + GraphicKiteEngine (); + virtual ~GraphicKiteEngine (); + }; + + +} // End of Kite namespace. + + +#endif // __KITE_GRAPHIC_KITE_ENGINE__ diff --git a/kite/src/kite/HorizontalTrack.h b/kite/src/kite/HorizontalTrack.h new file mode 100644 index 00000000..9e176f01 --- /dev/null +++ b/kite/src/kite/HorizontalTrack.h @@ -0,0 +1,67 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./HorizontalTrack.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_HORIZONTAL_TRACK__ +#define __KITE_HORIZONTAL_TRACK__ + +#include "kite/Track.h" + + +namespace Kite { + + +// ------------------------------------------------------------------- +// Class : "HorizontalTrack". + + + class HorizontalTrack : public Track { + + public: + static HorizontalTrack* create ( RoutingPlane*, unsigned int index ); + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual unsigned int getDirection () const; + virtual Point getPosition ( DbU::Unit coordinate ) const; + virtual string _getTypeName () const; + virtual Record* _getRecord () const; + + protected: + // Constructors & Destructors. + HorizontalTrack ( RoutingPlane*, unsigned int index ); + virtual ~HorizontalTrack (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + HorizontalTrack ( const HorizontalTrack& ); + HorizontalTrack& operator= ( const HorizontalTrack& ); + }; + + +} // End of Kite namespace. + + +#endif // __KITE_HORIZONTAL_TRACK__ diff --git a/kite/src/kite/KiteEngine.h b/kite/src/kite/KiteEngine.h new file mode 100644 index 00000000..3e1a4b45 --- /dev/null +++ b/kite/src/kite/KiteEngine.h @@ -0,0 +1,193 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./KiteEngine.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_KITE_ENGINE__ +#define __KITE_KITE_ENGINE__ + +#include "hurricane/Name.h" +namespace Hurricane { + class Layer; + class Net; + class Cell; +} + +#include "crlcore/RoutingGauge.h" +#include "katabatic/KatabaticEngine.h" + +namespace Knik { + class KnikEngine; +} + +#include "kite/TrackElement.h" +#include "kite/Configuration.h" + + +namespace Kite { + + + using Hurricane::Name; + using Hurricane::Layer; + using Hurricane::Net; + using Hurricane::Cell; + using CRL::RoutingGauge; + using Katabatic::KatabaticEngine; + + class GCellGrid; + class Track; + class RoutingPlane; + class NegociateWindow; + + +// ------------------------------------------------------------------- +// Enumerations + + + enum GlobalFlags { BuildGlobalSolution=1, LoadGlobalSolution }; + +// ------------------------------------------------------------------- +// Class : "Kite::KiteEngine". + + + class KiteEngine : public KatabaticEngine { + public: + enum LookupFlags { OnAllCollapseds=1 }; + + public: + static const Name& staticGetName (); + static KiteEngine* create ( const RoutingGauge*, Cell* ); + static KiteEngine* get ( const Cell* ); + public: + inline KatabaticEngine* base (); + inline Configuration* getKiteConfiguration (); + inline Net* getBlockageNet (); + virtual Configuration* getConfiguration (); + inline bool getToolSuccess () const; + inline unsigned int getRipupLimit ( unsigned int type ) const; + unsigned int getRipupLimit ( const TrackElement* ) const; + inline unsigned int getRipupCost () const; + inline float getExpandStep () const; + inline float getEdgeCapacityPercent () const; + inline GCellGrid* getGCellGrid () const; + virtual const Name& getName () const; + inline Configuration::PostEventCb_t& + getPostEventCb (); + inline NegociateWindow* getNegociateWindow (); + inline size_t getRoutingPlanesSize () const; + RoutingPlane* getRoutingPlaneByIndex ( size_t index ) const; + RoutingPlane* getRoutingPlaneByLayer ( const Layer* ) const; + Track* getTrackByPosition ( const Layer*, DbU::Unit axis, unsigned int mode=Constant::Nearest ) const; + void printCompletion () const; + inline void setPostEventCb ( Configuration::PostEventCb_t ); + inline void setMinimumWL ( double ); + inline void setRipupLimit ( unsigned int, unsigned int type ); + inline void setRipupCost ( unsigned int ); + inline void setExpandStep ( float ); + inline void setEdgeCapacityPercent ( float ); + void preProcess (); + void buildBlockages (); + void buildPowerRails (); + void createGlobalGraph ( unsigned int mode ); + virtual void createDetailedGrid (); + void saveGlobalSolution (); + void annotateGlobalGraph (); + void runGlobalRouter ( unsigned int mode ); + virtual void loadGlobalRouting ( unsigned int method, vector& ); + void runNegociate ( unsigned int slowMotion=0 ); + void setInterrupt ( bool ); + virtual void finalizeLayout (); + void _gutKite (); + inline TrackElementLut& _getTrackElementLut (); + void _link ( TrackElement* ); + void _unlink ( TrackElement* ); + TrackElement* _lookup ( Segment* ) const; + inline TrackElement* _lookup ( AutoSegment* ) const; + bool _check ( unsigned int& overlap, const char* message=NULL ) const; + void _check ( Net* ) const; + void _computeCagedConstraints (); + void _computeCagedConstraints ( Net* ); + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + private: + // Attributes. + static Name _toolName; + protected: + Knik::KnikEngine* _knik; + Net* _obstacleNet; + Configuration _configuration; + vector _routingPlanes; + GCellGrid* _kiteGrid; + NegociateWindow* _negociateWindow; + TrackElementLut _trackSegmentLut; + double _minimumWL; + mutable bool _toolSuccess; + + protected: + // Constructors & Destructors. + KiteEngine ( const RoutingGauge*, Cell* ); + virtual ~KiteEngine (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + KiteEngine ( const KiteEngine& ); + KiteEngine& operator= ( const KiteEngine& ); + }; + + +// Inline Functions. + inline KatabaticEngine* KiteEngine::base () { return static_cast(this); } + inline Configuration* KiteEngine::getKiteConfiguration () { return &_configuration; } + inline Net* KiteEngine::getBlockageNet () { return _obstacleNet; } + inline Configuration::PostEventCb_t& KiteEngine::getPostEventCb () { return _configuration.getPostEventCb(); } + inline bool KiteEngine::getToolSuccess () const { return _toolSuccess; } + inline unsigned int KiteEngine::getRipupCost () const { return _configuration.getRipupCost(); } + inline float KiteEngine::getExpandStep () const { return _configuration.getExpandStep(); } + inline float KiteEngine::getEdgeCapacityPercent () const { return _configuration.getEdgeCapacityPercent(); } + inline unsigned int KiteEngine::getRipupLimit ( unsigned int type ) const { return _configuration.getRipupLimit(type); } + inline GCellGrid* KiteEngine::getGCellGrid () const { return _kiteGrid; } + inline NegociateWindow* KiteEngine::getNegociateWindow () { return _negociateWindow; } + inline size_t KiteEngine::getRoutingPlanesSize () const { return _routingPlanes.size(); } + inline void KiteEngine::setRipupLimit ( unsigned int limit, unsigned int type ) { _configuration.setRipupLimit(limit,type); } + inline void KiteEngine::setRipupCost ( unsigned int cost ) { _configuration.setRipupCost(cost); } + inline void KiteEngine::setExpandStep ( float step ) { _configuration.setExpandStep(step); } + inline void KiteEngine::setEdgeCapacityPercent ( float percent ) { _configuration.setEdgeCapacityPercent(percent); } + inline void KiteEngine::setMinimumWL ( double minimum ) { _minimumWL = minimum; } + inline void KiteEngine::setPostEventCb ( Configuration::PostEventCb_t cb ) { _configuration.setPostEventCb(cb); } + inline TrackElementLut& KiteEngine::_getTrackElementLut () { return _trackSegmentLut; } + inline TrackElement* KiteEngine::_lookup ( AutoSegment* as ) const { return _lookup(as->base()); } + + +// Variables. + extern const char* missingRW; + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::KiteEngine); + + +#endif // __KITE_KITE_ENGINE__ diff --git a/kite/src/kite/NegociateWindow.h b/kite/src/kite/NegociateWindow.h new file mode 100644 index 00000000..f36633c6 --- /dev/null +++ b/kite/src/kite/NegociateWindow.h @@ -0,0 +1,158 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./NegociateWindow.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_NEGOCIATE_WINDOW__ +#define __KITE_NEGOCIATE_WINDOW__ + +#include +#include + +namespace Hurricane { + class Cell; +} + +#include "katabatic/Grid.h" +#include "kite/RoutingEventQueue.h" +#include "kite/RoutingEventHistory.h" + + +namespace Kite { + + + using std::vector; + using std::queue; + using Hurricane::Cell; + using Katabatic::GridBox; + + class GCell; + class GCellRoutingSet; + class TrackElement; + class KiteEngine; + + +// ------------------------------------------------------------------- +// Class : "Kite::NegociateWindow". + + + class NegociateWindow { + + public: + enum Stage { Negociation = 1 + , Packing + }; + public: + static NegociateWindow* create ( KiteEngine* kite + , unsigned int columnMin + , unsigned int rowMin + , unsigned int columnMax + , unsigned int rowMax + ); + void destroy (); + inline bool isInterrupted () const; + Cell* getCell () const; + inline GridBox* getGridBox () const; + inline KiteEngine* getKiteEngine () const; + inline RoutingEventQueue& getEventQueue (); + inline RoutingEventHistory& getEventHistory (); + inline const vector& + getGCellRoutingSets () const; + inline Stage getStage () const; + inline void setInterrupt ( bool ); + inline void setStage ( Stage ); + void loadRouting (); + void addInsertEvent ( TrackElement*, unsigned int level ); + inline void rescheduleEvent ( RoutingEvent*, unsigned int level ); + void run ( int slowMotion=0 ); + void addToRing ( TrackElement* ); + void printStatistics () const; + size_t _negociate ( const vector& ); + void _runOnGCellRoutingSet ( GCellRoutingSet* ); + void _loadRing (); + void _unloadRing (); + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + private: + class RingSegment { + public: + static bool orderReached ( const RingSegment& ); + public: + RingSegment ( TrackElement* segment=NULL ); + inline TrackElement* getSegment () const; + inline unsigned int getOrder () const; + private: + TrackElement* _segment; + unsigned int _order; + }; + + private: + // Attributes. + unsigned int _slowMotion; + bool _interrupt; + KiteEngine* _kite; + GridBox* _gridBox; + vector _criticalGCells; + unsigned int _gcellOrder; + vector _gcellRoutingSets; + RoutingEventQueue _eventQueue; + RoutingEventHistory _eventHistory; + vector _ring; + + // Constructors. + protected: + NegociateWindow ( KiteEngine* kite + , unsigned int columnMin + , unsigned int rowMin + , unsigned int columnMax + , unsigned int rowMax + ); + ~NegociateWindow (); + private: + NegociateWindow ( const NegociateWindow& ); + NegociateWindow& operator= ( const NegociateWindow& ); + }; + + +// Inline Functions. + inline bool NegociateWindow::isInterrupted () const { return _interrupt; } + inline string NegociateWindow::_getTypeName () const { return "NegociateWindow"; } + inline GridBox* NegociateWindow::getGridBox () const { return _gridBox; } + inline KiteEngine* NegociateWindow::getKiteEngine () const { return _kite; } + inline RoutingEventQueue& NegociateWindow::getEventQueue () { return _eventQueue; } + inline RoutingEventHistory& NegociateWindow::getEventHistory () { return _eventHistory; } + inline void NegociateWindow::setInterrupt ( bool state ) { _interrupt = state; } + inline void NegociateWindow::rescheduleEvent ( RoutingEvent* event, unsigned int level ) { event->reschedule(_eventQueue,level); } + inline const vector& + NegociateWindow::getGCellRoutingSets () const { return _gcellRoutingSets; } + + inline TrackElement* NegociateWindow::RingSegment::getSegment () const { return _segment; } + inline unsigned int NegociateWindow::RingSegment::getOrder () const { return _order; } + + +} // End of Kite namespace. + + +#endif // __KITE_NEGOCIATE_WINDOW__ diff --git a/kite/src/kite/RoutingEvent.h b/kite/src/kite/RoutingEvent.h new file mode 100644 index 00000000..d84169b1 --- /dev/null +++ b/kite/src/kite/RoutingEvent.h @@ -0,0 +1,272 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./RoutingEvent.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_ROUTING_EVENT__ +#define __KITE_ROUTING_EVENT__ + +#include + +#include "hurricane/Interval.h" +namespace Hurricane { + class Net; +} + +#include "kite/TrackCost.h" +#include "kite/TrackElement.h" +#include "kite/Session.h" + + +namespace Kite { + + + using std::vector; + + using Hurricane::DbU; + using Hurricane::Interval; + using Hurricane::Net; + + class TrackElement; + class Track; + class RoutingEventHistory; + class RoutingEventQueue; + + +// ------------------------------------------------------------------- +// Class : "RoutingEvent". + + + class RoutingEvent { + + private: + class Key { + public: + struct Compare { + bool operator() ( const Key& lhs, const Key& rhs ) const; + }; + public: + Key ( const RoutingEvent* ); + void update ( const RoutingEvent* ); + private: + bool _slackenStrap; + bool _isHorizontal; + bool _canRipple; + unsigned int _tracksNb:6; + float _priority; + unsigned int _eventLevel; + DbU::Unit _length; + DbU::Unit _axis; + DbU::Unit _sourceU; + Net* _net; + unsigned long _id; + friend class Compare; + }; + + public: + // Sub-Class: "Compare". + struct Compare { + bool operator() ( const RoutingEvent* lhs, const RoutingEvent* rhs ) const; + }; + friend class Compare; + + public: + enum Mode { Negociate=1, Pack=2, PostPack=3 }; + + public: + static size_t getAllocateds (); + static size_t getProcesseds (); + static size_t getCloneds (); + static void resetProcesseds (); + public: + static RoutingEvent* create ( TrackElement*, unsigned int mode=Negociate ); + RoutingEvent* clone () const; + void destroy (); + inline bool isCloned () const; + inline bool isValid () const; + bool isUnimplemented () const; + inline bool isProcessed () const; + inline bool isDisabled () const; + inline bool isForcedToHint () const; + inline bool isSheared () const; + inline bool getMode () const; + inline bool canMinimize () const; + unsigned int getState () const; + inline const Key& getKey () const; + inline TrackElement* getSegment () const; + inline const vector& getPerpandiculars () const; + inline DbU::Unit getAxisHint () const; + inline DbU::Unit getAxisHistory () const; + long getAxisWeight ( DbU::Unit ) const; + inline const Interval& getOptimalAxis () const; + inline const Interval& getConstraints () const; + inline const Interval& getOptimal () const; + inline const Interval& getPerpandicular () const; + inline GCell* getShearGCell () const; + inline float getPriority () const; + inline unsigned int getTracksNb () const; + inline unsigned int getTracksFree () const; + inline unsigned int getInsertState () const; + inline unsigned int getEventLevel () const; + inline void invalidate ( bool withPerpandiculars=false, bool withConstraints=false ); + void revalidate ( bool force=false ); + inline void updateKey (); + void process ( RoutingEventQueue&, RoutingEventHistory& ); + void setSegment ( TrackElement* ); + RoutingEvent* reschedule ( RoutingEventQueue&, unsigned int eventLevel ); + inline void setMode ( unsigned int ); + void setState ( unsigned int ); + inline void setProcessed ( bool state=true ); + inline void setDisabled ( bool state=true ); + inline void setMinimized ( bool state=true ); + void setEventLevel ( unsigned int ); + inline void setTracksFree ( unsigned int ); + inline void setForcedToHint ( bool state = true ); + void setAxisHint ( DbU::Unit ); + inline void setOptimalAxis ( Interval ); + inline void incInsertState (); + inline void resetInsertState (); + void _processNegociate ( RoutingEventQueue&, RoutingEventHistory& ); + void _processPacking ( RoutingEventQueue&, RoutingEventHistory& ); + Record* _getRecord () const; + string _getString () const; + string _getTypeName () const; + private: + RoutingEvent ( TrackElement*, unsigned int mode ); + ~RoutingEvent (); + + protected: + // Attributes. + static size_t _allocateds; + static size_t _processeds; + static size_t _cloneds; + mutable bool _cloned; + bool _processed; + bool _disabled; + bool _valid; + bool _validConstraints; + bool _validPerpandiculars; + bool _canHandleConstraints; + bool _minimized; + bool _forceToHint; + TrackElement* _segment; + DbU::Unit _axisHistory; + DbU::Unit _axisHint; + Interval _optimalAxis; + Interval _constraints; + Interval _optimal; + Interval _perpandicular; + GCell* _shearGCell; + unsigned int _tracksNb : 6; + unsigned int _tracksFree : 4; + unsigned int _insertState : 6; + unsigned int _mode : 4; + unsigned int _rippleState : 4; + unsigned int _eventLevel; + float _priority; + vector _perpandiculars; + Key _key; + }; + + +// Inline Functions. + inline bool RoutingEvent::isCloned () const { return _cloned; } + inline bool RoutingEvent::isValid () const { return _valid; } + inline bool RoutingEvent::isProcessed () const { return _processed; } + inline bool RoutingEvent::isDisabled () const { return _disabled; } + inline bool RoutingEvent::isForcedToHint () const { return _forceToHint; } + inline bool RoutingEvent::isSheared () const { return (_shearGCell != NULL); } + inline bool RoutingEvent::getMode () const { return _mode; } + inline bool RoutingEvent::canMinimize () const { return !_minimized; } + inline const RoutingEvent::Key& RoutingEvent::getKey () const { return _key; } + inline TrackElement* RoutingEvent::getSegment () const { return _segment; } + inline const vector& RoutingEvent::getPerpandiculars () const { return _perpandiculars; } + inline DbU::Unit RoutingEvent::getAxisHint () const { return _axisHint; } + inline DbU::Unit RoutingEvent::getAxisHistory () const { return _axisHistory; } + inline const Interval& RoutingEvent::getOptimalAxis () const { return _optimalAxis; } + inline const Interval& RoutingEvent::getConstraints () const { return _constraints; } + inline const Interval& RoutingEvent::getOptimal () const { return _optimal; } + inline const Interval& RoutingEvent::getPerpandicular () const { return _perpandicular; } + inline float RoutingEvent::getPriority () const { return _priority; } + inline unsigned int RoutingEvent::getEventLevel () const { return _eventLevel; } + inline unsigned int RoutingEvent::getTracksNb () const { return _tracksNb; } + inline unsigned int RoutingEvent::getTracksFree () const { return _tracksFree; } + inline unsigned int RoutingEvent::getInsertState () const { return _insertState; } + inline GCell* RoutingEvent::getShearGCell () const { return _shearGCell; } + inline void RoutingEvent::setMode ( unsigned int mode ) { _mode = mode; } + inline void RoutingEvent::setProcessed ( bool state ) { _processed = state; } + inline void RoutingEvent::setDisabled ( bool state ) { _disabled = state; } + inline void RoutingEvent::setMinimized ( bool state ) { _minimized = state; } + inline void RoutingEvent::setTracksFree ( unsigned int nb ) { _tracksFree = nb; } + inline void RoutingEvent::setForcedToHint ( bool state ) { _forceToHint = state; } + inline void RoutingEvent::setOptimalAxis ( Interval i ) { _optimalAxis = i; } + inline void RoutingEvent::incInsertState () { _insertState++; } + inline void RoutingEvent::resetInsertState () { _insertState = 0; } + inline void RoutingEvent::updateKey () { revalidate(); _key.update(this); } + + inline void RoutingEvent::invalidate ( bool withPerpandiculars, bool withConstraints ) + { + _valid = false; + _validPerpandiculars = _validPerpandiculars and !withPerpandiculars; + _validConstraints = _validConstraints and !withConstraints; + } + + +// ------------------------------------------------------------------- +// Macros. + + +# if !defined(NDEBUG) +# define _preCheck(segment) \ + DbU::Unit beforeMin = segment->base()->getSourcePosition(); \ + DbU::Unit beforeMax = segment->base()->getTargetPosition(); \ + segment->base()->checkPositions (); \ + if ( Session::getSegmentStackSize() ) \ + cerr << "[ERROR] Session Segment Stack is not empty (" \ + << Session::getSegmentStackSize() << ")." << endl; + +# define _postCheck(segment) \ + ltrace(149) << "Bounds := [" \ + << DbU::getValueString(segment->base()->getSourcePosition()) << ":" \ + << DbU::getValueString(segment->base()->getTargetPosition()) << "] " \ + << DbU::getValueString(segment->getAxis()) << " " \ + << segment->getTrack() << endl; \ + if ( beforeMin != segment->base()->getSourcePosition() ) \ + cerr << "[ERROR] " << segment \ + << " origin was " << DbU::getValueString(beforeMin) << endl; \ + if ( beforeMax != segment->base()->getTargetPosition() ) \ + cerr << "[ERROR] " << segment \ + << " extremity was " << DbU::getValueString(beforeMax) << endl; +# else +# define _preCheck(segment) ; +# define _postCheck(segment) ; +# endif + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::RoutingEvent); + + +# endif diff --git a/kite/src/kite/RoutingEventHistory.h b/kite/src/kite/RoutingEventHistory.h new file mode 100644 index 00000000..eebadad7 --- /dev/null +++ b/kite/src/kite/RoutingEventHistory.h @@ -0,0 +1,86 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./RoutingEventHistory.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_ROUTING_EVENT_HISTORY__ +#define __KITE_ROUTING_EVENT_HISTORY__ + + +#include +#include + + +namespace Kite { + + + using std::vector; + using std::ostream; + + class RoutingEvent; + + +// ------------------------------------------------------------------- +// Class : "RoutingEventHistory". + + + class RoutingEventHistory { + + public: + RoutingEventHistory (); + ~RoutingEventHistory (); + inline bool looping () const; + inline bool empty () const; + inline size_t size () const; + RoutingEvent* getNth ( size_t ) const; + RoutingEvent* getRNth ( size_t ) const; + void push ( RoutingEvent* ); + void clear (); + void dump ( ostream&, size_t depth=10 ) const; + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + protected: + // Attributes. + vector _events; + size_t _identicals; + + private: + RoutingEventHistory& operator= ( const RoutingEventHistory& ); + RoutingEventHistory ( const RoutingEventHistory& ); + + }; + + +// Inline Functions. + inline bool RoutingEventHistory::looping () const { return _identicals > 30; } + inline bool RoutingEventHistory::empty () const { return _events.empty(); } + inline size_t RoutingEventHistory::size () const { return _events.size(); } + inline string RoutingEventHistory::_getTypeName () const { return "RoutingEventHistory"; } + + +} // End of Kite namespace. + + +#endif // __KITE_ROUTING_EVENT_HISTORY__ diff --git a/kite/src/kite/RoutingEventQueue.h b/kite/src/kite/RoutingEventQueue.h new file mode 100644 index 00000000..3584b49b --- /dev/null +++ b/kite/src/kite/RoutingEventQueue.h @@ -0,0 +1,92 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./RoutingEventQueue.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_ROUTING_EVENT_QUEUE__ +#define __KITE_ROUTING_EVENT_QUEUE__ + + +#include +#include +#include "kite/RoutingEvent.h" + + +namespace Kite { + + + using std::set; + using std::multiset; + using std::vector; + + +// ------------------------------------------------------------------- +// Class : "RoutingEventQueue". + + + class RoutingEventQueue { + + public: + RoutingEventQueue (); + ~RoutingEventQueue (); + void load ( const vector& ); + void add ( TrackElement*, unsigned int level ); + inline bool empty () const; + inline size_t size () const; + inline unsigned int getTopEventLevel () const; + void push ( RoutingEvent* ); + RoutingEvent* pop (); + void repush ( RoutingEvent* ); + void repushInvalidateds (); + void commit (); + void clear (); + void dump () const; + void _keyCheck () const; + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + protected: + // Attributes. + unsigned int _topEventLevel; + set _pushRequests; + multiset _events; + + private: + RoutingEventQueue& operator= ( const RoutingEventQueue& ); + RoutingEventQueue ( const RoutingEventQueue& ); + + }; + + +// Inline Functions. + inline bool RoutingEventQueue::empty () const { return _events.empty(); } + inline size_t RoutingEventQueue::size () const { return _events.size(); } + inline unsigned int RoutingEventQueue::getTopEventLevel () const { return _topEventLevel; } + inline string RoutingEventQueue::_getTypeName () const { return "EventQueue"; } + + +} // End of Kite namespace. + + +#endif // __KITE_ROUTING_EVENT_QUEUE__ diff --git a/kite/src/kite/RoutingPlane.h b/kite/src/kite/RoutingPlane.h new file mode 100644 index 00000000..48f84535 --- /dev/null +++ b/kite/src/kite/RoutingPlane.h @@ -0,0 +1,137 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./RoutingPlane.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_ROUTING_PLANE__ +#define __KITE_ROUTING_PLANE__ + + +#include "crlcore/RoutingLayerGauge.h" +#include "kite/Track.h" + + +namespace Kite { + + + using CRL::RoutingLayerGauge; + class KiteEngine; + + +// ------------------------------------------------------------------- +// Class : "RoutingPlane". + + + class RoutingPlane { + + public: + static RoutingPlane* create ( KiteEngine*, size_t depth ); + void destroy (); + inline bool isHorizontal () const; + inline bool isVertical () const; + inline KiteEngine* getKiteEngine () const; + inline RoutingLayerGauge* getLayerGauge () const; + inline unsigned int getDirection () const; + inline size_t getDepth () const; + inline DbU::Unit getAxisMin () const; + inline DbU::Unit getAxisMax () const; + inline DbU::Unit getTrackMin () const; + inline DbU::Unit getTrackMax () const; + RoutingPlane* getTop () const; + RoutingPlane* getBottom () const; + inline const Layer* getLayer () const; + inline const Layer* getBlockageLayer () const; + inline size_t getTracksSize () const; + inline size_t computeTracksSize () const; + inline DbU::Unit getTrackPosition ( size_t index ) const; + Track* getTrackByIndex ( size_t index ) const; + Track* getTrackByPosition ( DbU::Unit axis, unsigned int mode=Constant::Nearest ) const; + bool _check ( unsigned int& overlaps ) const; + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + protected: + // Sub-Class: TrackCompare. + struct TrackCompare { + inline bool operator() ( Track* track1, Track* track2 ); + }; + + protected: + // Attributes. + KiteEngine* _kite; + RoutingLayerGauge* _layerGauge; + size_t _depth; + DbU::Unit _axisMin; + DbU::Unit _axisMax; + DbU::Unit _trackMin; + DbU::Unit _trackMax; + vector _tracks; + + protected: + // Constructors & Destructors. + RoutingPlane ( KiteEngine*, size_t depth ); + ~RoutingPlane (); + private: + RoutingPlane ( const RoutingPlane& ); + RoutingPlane& operator= ( const RoutingPlane& ); + }; + + +// Inline Functions. + inline bool RoutingPlane::TrackCompare::operator() ( Track* lhs, Track* rhs ) + { return lhs->getAxis() > rhs->getAxis(); }; + + inline KiteEngine* RoutingPlane::getKiteEngine () const { return _kite; } + inline RoutingLayerGauge* RoutingPlane::getLayerGauge () const { return _layerGauge; } + inline unsigned int RoutingPlane::getDirection () const { return _layerGauge->getDirection(); } + inline size_t RoutingPlane::getDepth () const { return _depth; } + inline DbU::Unit RoutingPlane::getAxisMin () const { return _axisMin; } + inline DbU::Unit RoutingPlane::getAxisMax () const { return _axisMax; } + inline DbU::Unit RoutingPlane::getTrackMin () const { return _trackMin; } + inline DbU::Unit RoutingPlane::getTrackMax () const { return _trackMax; } + inline const Layer* RoutingPlane::getLayer () const { return getLayerGauge()->getLayer(); } + inline const Layer* RoutingPlane::getBlockageLayer () const { return getLayerGauge()->getBlockageLayer(); } + inline size_t RoutingPlane::getTracksSize () const { return _tracks.size(); } + inline string RoutingPlane::_getTypeName () const { return "RoutingPlane"; } + + inline size_t RoutingPlane::computeTracksSize () const + { return _layerGauge->getTrackNumber(_axisMin,_axisMax); } + + inline DbU::Unit RoutingPlane::getTrackPosition ( size_t index ) const + { return _layerGauge->getTrackPosition(_axisMin,index); } + + inline bool RoutingPlane::isHorizontal () const + { return (getDirection() == Constant::Horizontal); } + + inline bool RoutingPlane::isVertical () const + { return (getDirection() == Constant::Vertical); } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::RoutingPlane); + + +#endif // __KITE_ROUTING_PLANE__ diff --git a/kite/src/kite/Session.h b/kite/src/kite/Session.h new file mode 100644 index 00000000..9cd6f48a --- /dev/null +++ b/kite/src/kite/Session.h @@ -0,0 +1,212 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./Session.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_SESSION__ +#define __KITE_SESSION__ + +#include +#include +#include + +namespace Hurricane { + class Record; + class Net; + class Segment; +} + +#include "katabatic/Session.h" +namespace Katabatic { + class GCell; + class AutoSegment; +} + + +namespace Kite { + + + using std::set; + using std::vector; + using std::string; + using Hurricane::Record; + using Hurricane::Net; + using Hurricane::Segment; + using Hurricane::DbU; + using Katabatic::AutoSegment; + + class Track; + class TrackElement; + class TrackMarker; + class GCell; + class NegociateWindow; + class Configuration; + class KiteEngine; + + +// ------------------------------------------------------------------- +// Class : "Session". + + + class Session : public Katabatic::Session { + + public: + static Session* open ( KiteEngine* ); + static Session* get ( const char* message=NULL ); + inline static Katabatic::Session* base (); + inline static KiteEngine* getKiteEngine (); + static Configuration* getConfiguration (); + inline static Net* getBlockageNet (); + inline static NegociateWindow* getNegociateWindow (); + inline static unsigned int getRipupCost (); + inline static GCell* getGCellUnder ( DbU::Unit, DbU::Unit ); + inline static unsigned int getOrder (); + inline static void setOrder ( unsigned int ); + inline static void addInsertEvent ( TrackMarker* , Track* ); + inline static void addInsertEvent ( TrackElement* , Track* ); + inline static void addRemoveEvent ( TrackElement* ); + inline static void addMoveEvent ( TrackElement* , Track* ); + inline static void addSortEvent ( Track*, bool forced=false ); + inline static size_t revalidate (); + inline static bool isEmpty (); + static void setInterrupt ( bool ); + static void link ( TrackElement* ); + static void unlink ( TrackElement* ); + static TrackElement* lookup ( Segment* ); + static TrackElement* lookup ( AutoSegment* ); + static GCell* lookup ( Katabatic::GCell* ); + private: + KiteEngine* _getKiteEngine (); + Net* _getBlockageNet (); + NegociateWindow* _getNegociateWindow (); + unsigned int _getRipupCost (); + GCell* _getGCellUnder ( DbU::Unit, DbU::Unit ); + unsigned int _getOrder () const; + void _setOrder ( unsigned int ); + GCell* _lookup ( Katabatic::GCell* ); + void _addInsertEvent ( TrackMarker* , Track* ); + void _addInsertEvent ( TrackElement* , Track* ); + void _addRemoveEvent ( TrackElement* ); + void _addMoveEvent ( TrackElement* , Track* ); + void _addSortEvent ( Track*, bool forced ); + virtual size_t _revalidate (); + bool _isEmpty () const; + virtual Record* _getRecord () const; + virtual string _getTypeName () const; + + protected: + // Internal Classes. + class Event { + public: + inline Event ( TrackElement*, Track* ); + inline Event ( TrackMarker* , Track* ); + public: + TrackElement* _segment; + TrackMarker* _marker; + Track* _track; + }; + + protected: + // Attributes. + unsigned int _order; + vector _insertEvents; + vector _removeEvents; + set _sortEvents; + + protected: + // Constructors & Destructors. + Session ( KiteEngine* ); + virtual ~Session (); + virtual void _postCreate (); + virtual size_t _preDestroy (); + private: + Session ( const Session& ); + Session& operator= ( const Session& ); + + }; + + +// Inline Functions. + inline Session::Event::Event ( TrackElement* segment , Track* track ) + : _segment(segment) + , _marker (NULL) + , _track (track) + { } + + inline Session::Event::Event ( TrackMarker* marker , Track* track ) + : _segment(NULL) + , _marker (marker) + , _track (track) + { } + + + inline Katabatic::Session* Session::base () + { return static_cast(get("base()")); } + + inline KiteEngine* Session::getKiteEngine () + { return get("getKiteEngine()")->_getKiteEngine(); } + + inline Net* Session::getBlockageNet () + { return get("getBlockageNet()")->_getBlockageNet(); } + + inline NegociateWindow* Session::getNegociateWindow () + { return get("getNegociateWindow()")->_getNegociateWindow(); } + + inline unsigned int Session::getRipupCost () + { return get("getRipupCost()")->_getRipupCost(); } + + inline GCell* Session::getGCellUnder ( DbU::Unit x, DbU::Unit y ) + { return get("getGCellUnder()")->_getGCellUnder(x,y); } + + inline unsigned int Session::getOrder () + { return get("getOrder()")->_getOrder(); } + + inline void Session::setOrder ( unsigned int order ) + { get("setOrder()")->_setOrder(order); } + + inline void Session::addInsertEvent ( TrackMarker* marker, Track* track ) + { get("addInsertEvent(TrackMarker*)")->_addInsertEvent(marker,track); } + + inline void Session::addInsertEvent ( TrackElement* segment, Track* track ) + { get("addInsertEvent(TrackElement*)")->_addInsertEvent(segment,track); } + + inline void Session::addRemoveEvent ( TrackElement* segment ) + { get("addRemoveEvent()")->_addRemoveEvent(segment); } + + inline void Session::addMoveEvent ( TrackElement* segment, Track* track ) + { get("addMoveEvent()")->_addMoveEvent(segment,track); } + + inline void Session::addSortEvent ( Track* track, bool forced ) + { get("addSortEvent()")->_addSortEvent(track,forced); } + + inline size_t Session::revalidate () + { return get("revalidate()")->_revalidate(); } + + inline bool Session::isEmpty () + { return get("isEmpty()")->_isEmpty(); } + + +} // End of Kite namespace. + + +#endif // __KITE_SESSION__ diff --git a/kite/src/kite/Track.h b/kite/src/kite/Track.h new file mode 100644 index 00000000..3f4680c8 --- /dev/null +++ b/kite/src/kite/Track.h @@ -0,0 +1,232 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./Track.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK__ +#define __KITE_TRACK__ + +#include "hurricane/Point.h" +namespace Hurricane { + class Layer; +} + +#include "kite/TrackCost.h" +#include "kite/TrackElement.h" + + +namespace Kite { + + + using Hurricane::Point; + using Hurricane::Layer; + + class TrackMarker; + class RoutingPlane; + class KiteEngine; + + +// ------------------------------------------------------------------- +// Class : "Track". + + + class Track { + + public: + enum IndexState { MinTrackMin = (1<<0) + , MinSegmentMin = (1<<1) + , MinSegmentMax = (1<<2) + , MaxTrackMax = (1<<3) + , MaxSegmentMin = (1<<4) + , MaxNextSegmentMin = (1<<5) + , MaxSegmentMax = (1<<6) + , BeforeFirst = MinTrackMin | MaxSegmentMin + , Inside = MinSegmentMin | MaxSegmentMax + , Outside = MinSegmentMax | MaxNextSegmentMin + , AfterLast = MinSegmentMax | MaxTrackMax + , EmptyTrack = MinTrackMin | MaxTrackMax + , MinMask = MinTrackMin + | MinSegmentMin + | MinSegmentMax + , MaxMask = MaxTrackMax + | MaxSegmentMin + | MaxNextSegmentMin + | MaxSegmentMax + }; + + public: + // Static Attributes. + static const size_t NPOS; + + public: + void destroy (); + inline RoutingPlane* getRoutingPlane () const; + KiteEngine* getKiteEngine () const; + virtual bool isHorizontal () const = 0; + virtual bool isVertical () const = 0; + virtual unsigned int getDirection () const = 0; + inline size_t getIndex () const; + unsigned int getDepth () const; + const Layer* getLayer () const; + const Layer* getBlockageLayer () const; + inline DbU::Unit getAxis () const; + inline DbU::Unit getMin () const; + inline DbU::Unit getMax () const; + Track* getNext () const; + Track* getPrevious () const; + inline size_t getSize () const; + TrackElement* getNext ( size_t& index, Net*, bool useOrder=false ) const; + TrackElement* getPrevious ( size_t& index, Net*, bool useOrder=false ) const; + TrackElement* getNextFixed ( size_t& index ) const; + TrackElement* getSegment ( size_t index ) const; + TrackElement* getSegment ( DbU::Unit position ) const; + void getIBounds ( DbU::Unit position, size_t& begin, size_t& end, unsigned int& state ) const; + void getOverlapBounds ( Interval, size_t& begin, size_t& end ) const; + TrackCost getOverlapCost ( Interval, Net*, size_t begin, size_t end ) const; + TrackCost getOverlapCost ( Interval, Net* ) const; + TrackCost getOverlapCost ( TrackElement* ) const; + void getTerminalWeight ( Interval, Net*, size_t& count, unsigned int& weight ) const; + DbU::Unit getSourcePosition ( size_t index ) const; + DbU::Unit getSourcePosition ( vector::iterator ) const; + DbU::Unit getMinimalPosition ( size_t index, unsigned int state ) const; + DbU::Unit getMaximalPosition ( size_t index, unsigned int state ) const; + virtual Point getPosition ( DbU::Unit coordinate ) const = 0; + size_t find ( const TrackElement* ) const; + Interval getFreeInterval ( DbU::Unit position, Net* net=NULL ) const; + Interval expandUsedInterval ( size_t& begin, size_t& end, bool useOrder=false ) const; + Interval expandFreeInterval ( size_t& begin, size_t& end, unsigned int state, Net*, bool useOrder=false ) const; + unsigned int checkOverlap ( unsigned int& overlaps ) const; + void forceSort (); + void insert ( TrackElement* ); + void insert ( TrackMarker* ); + void setSegment ( TrackElement*, size_t ); + size_t pack (); + void sort (); + bool _check ( unsigned int& overlaps, const char* message=NULL ) const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const = 0; + + protected: + // Attributes. + RoutingPlane* _routingPlane; + size_t _index; + DbU::Unit _axis; + DbU::Unit _min; + DbU::Unit _max; + vector _segments; + vector _markers; + bool _segmentsValid; + bool _markersValid; + + protected: + // Constructors & Destructors. + Track ( RoutingPlane*, unsigned int index ); + virtual ~Track (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + Track ( const Track& ); + Track& operator= ( const Track& ); + protected: + // Protected functions. + inline unsigned int setMinimalFlags ( unsigned int& state, unsigned int flags ) const; + inline unsigned int setMaximalFlags ( unsigned int& state, unsigned int flags ) const; + + protected: + // Sub-Classes. + struct SourceCompare { + public: + inline bool operator() ( const TrackElement* lhs , const TrackElement* rhs ); + inline bool operator() ( DbU::Unit lhsSource, const TrackElement* rhs ); + inline bool operator() ( const TrackElement* lhs , DbU::Unit rhsSource ); + private: + inline bool lessSource ( DbU::Unit lhs , DbU::Unit rhsSource ); + }; + struct SegmentCompare { + inline bool operator() ( const TrackElement* lhs, const TrackElement* rhs ); + }; + }; + + +// Inline Functions. + inline bool Track::SourceCompare::operator() ( const TrackElement* lhs, const TrackElement* rhs ) + { return lessSource(lhs->getSourceU(),rhs->getSourceU()); } + + + inline bool Track::SourceCompare::operator() ( DbU::Unit lhsSource, const TrackElement* rhs ) + { return lessSource(lhsSource,rhs->getSourceU()); } + + + inline bool Track::SourceCompare::operator() ( const TrackElement* lhs, DbU::Unit rhsSource ) + { return lessSource(lhs->getSourceU(),rhsSource); } + + + inline bool Track::SourceCompare::lessSource ( DbU::Unit lhsSource, DbU::Unit rhsSource ) + { return lhsSource < rhsSource; } + + + inline bool Track::SegmentCompare::operator() ( const TrackElement* lhs, const TrackElement* rhs ) + { + if ( lhs->getSourceU() < rhs->getSourceU() ) + return true; + else { + if ( ( lhs->getSourceU() == rhs->getSourceU() ) + && ( lhs->getTargetU() > rhs->getTargetU() ) ) + return true; + } + return false; + } + + + inline RoutingPlane* Track::getRoutingPlane () const { return _routingPlane; } + inline size_t Track::getIndex () const { return _index; } + inline DbU::Unit Track::getAxis () const { return _axis; } + inline DbU::Unit Track::getMin () const { return _min; } + inline DbU::Unit Track::getMax () const { return _max; } + inline size_t Track::getSize () const { return _segments.size(); } + + inline unsigned int Track::setMinimalFlags ( unsigned int& state, unsigned int flags ) const + { + state &= ~MinMask; + state |= (flags & MinMask); + return state; + } + + inline unsigned int Track::setMaximalFlags ( unsigned int& state, unsigned int flags ) const + { + state &= ~MaxMask; + state |= (flags & MaxMask); + return state; + } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::Track); + + +#endif // __KITE_TRACK__ diff --git a/kite/src/kite/TrackBlockage.h b/kite/src/kite/TrackBlockage.h new file mode 100644 index 00000000..97d3719e --- /dev/null +++ b/kite/src/kite/TrackBlockage.h @@ -0,0 +1,98 @@ + + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackBlockage.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_OBSTACLE__ +#define __KITE_TRACK_OBSTACLE__ + + +#include "kite/TrackElement.h" + + +namespace Kite { + + + using std::string; + using std::map; + using Hurricane::Record; + using Hurricane::Interval; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Layer; + + class Track; + + +// ------------------------------------------------------------------- +// Class : "TrackBlockage". + + + class TrackBlockage : public TrackElement { + public: + static TrackElement* create ( Track*, Box& ); + public: + virtual AutoSegment* base () const; + virtual bool isFixed () const; + virtual bool isBlockage () const; + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual unsigned long getId () const; + virtual unsigned int getDirection () const; + virtual Net* getNet () const; + virtual const Layer* getLayer () const; + virtual TrackElement* getNext () const; + virtual TrackElement* getPrevious () const; + virtual DbU::Unit getAxis () const; + virtual Interval getFreeInterval ( bool useOrder=false ) const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + // Attributes. + Segment* _segment; + + protected: + // Constructors & Destructors. + TrackBlockage ( Track*, Box& ) ; + virtual ~TrackBlockage (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + TrackBlockage ( const TrackBlockage& ); + TrackBlockage& operator= ( const TrackBlockage& ); + + }; + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::TrackBlockage); + + +# endif diff --git a/kite/src/kite/TrackCost.h b/kite/src/kite/TrackCost.h new file mode 100644 index 00000000..01a6edf4 --- /dev/null +++ b/kite/src/kite/TrackCost.h @@ -0,0 +1,168 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackCost.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_COST__ +#define __KITE_TRACK_COST__ + +#include +#include "hurricane/Interval.h" + + +namespace Kite { + + + using std::string; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Interval; + class Track; + + +// ------------------------------------------------------------------- +// Class : "TrackCost". + + class TrackCost { + + public: + // Sub-Class: "CompareByDelta()". + class CompareByDelta { + public: + bool operator() ( const TrackCost& lhs, const TrackCost& rhs ); + }; + + public: + TrackCost ( Track* track + , const Interval& interval + , size_t begin + , size_t end + ); + ~TrackCost (); + inline bool isBlockage () const; + inline bool isFixed () const; + inline bool isInfinite () const; + inline bool isOverlap () const; + inline bool isLeftOverlap () const; + inline bool isRightOverlap () const; + inline bool isHardOverlap () const; + bool isFree () const; + inline Track* getTrack () const; + inline size_t getBegin () const; + inline size_t getEnd () const; + inline const Interval& getInterval () const; + inline unsigned int getTerminals () const; + inline DbU::Unit getDelta () const; + inline DbU::Unit getDeltaPerpand () const; + inline long getAxisWeight () const; + inline int getRipupCount () const; + inline unsigned int getDataState () const; + inline void setBlockage (); + inline void setFixed (); + inline void setInfinite (); + inline void setOverlap (); + inline void setLeftOverlap (); + inline void setRightOverlap (); + inline void setHardOverlap (); + inline void incTerminals ( unsigned int ); + inline void incDelta ( DbU::Unit ); + inline void incDeltaPerpand ( DbU::Unit ); + inline void incDeltaShared ( DbU::Unit ); + inline void setAxisWeight ( DbU::Unit ); + inline void mergeRipupCount ( int ); + inline void mergeDataState ( unsigned int ); + void consolidate (); + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + // Operators. + friend bool operator< ( const TrackCost& lhs, const TrackCost& rhs ); + + // Attributes. + protected: + Track* _track; + size_t _begin; + size_t _end; + Interval _interval; + bool _blockage; + bool _fixed; + bool _infinite; + bool _hardOverlap; + bool _overlap; + bool _leftOverlap; + bool _rightOverlap; + unsigned int _terminals; + DbU::Unit _delta; + DbU::Unit _deltaShared; + DbU::Unit _deltaPerpand; + DbU::Unit _axisWeight; + DbU::Unit _distanceToFixed; + unsigned int _dataState; + int _ripupCount; + + }; + + +// Inline Functions. + inline bool TrackCost::isBlockage () const { return _blockage; } + inline bool TrackCost::isFixed () const { return _fixed; } + inline bool TrackCost::isInfinite () const { return _infinite; } + inline bool TrackCost::isOverlap () const { return _overlap; } + inline bool TrackCost::isLeftOverlap () const { return _leftOverlap; } + inline bool TrackCost::isRightOverlap () const { return _rightOverlap; } + inline bool TrackCost::isHardOverlap () const { return _hardOverlap; } + inline Track* TrackCost::getTrack () const { return _track; } + inline size_t TrackCost::getBegin () const { return _begin; } + inline size_t TrackCost::getEnd () const { return _end; } + inline const Interval& TrackCost::getInterval () const { return _interval; } + inline unsigned int TrackCost::getTerminals () const { return _terminals; } + inline DbU::Unit TrackCost::getDelta () const { return _delta; } + inline long TrackCost::getAxisWeight () const { return _axisWeight; } + inline int TrackCost::getRipupCount () const { return _ripupCount; } + inline unsigned int TrackCost::getDataState () const { return _dataState; } + inline void TrackCost::setBlockage () { _blockage = true; } + inline void TrackCost::setFixed () { _fixed = true; } + inline void TrackCost::setInfinite () { _infinite = true; } + inline void TrackCost::setOverlap () { _overlap = true; } + inline void TrackCost::setLeftOverlap () { _leftOverlap = true; } + inline void TrackCost::setRightOverlap () { _rightOverlap = true; } + inline void TrackCost::setHardOverlap () { _hardOverlap = true; } + inline void TrackCost::incTerminals ( unsigned int terminals ) { _terminals += terminals; } + inline void TrackCost::incDelta ( DbU::Unit delta ) { _delta += delta; } + inline void TrackCost::incDeltaPerpand ( DbU::Unit delta ) { _deltaPerpand += delta; } + inline void TrackCost::incDeltaShared ( DbU::Unit delta ) { _deltaShared += delta; } + inline void TrackCost::setAxisWeight ( DbU::Unit weight ) { _axisWeight = weight; } + inline void TrackCost::mergeRipupCount ( int count ) { _ripupCount = (count>_ripupCount)?count:_ripupCount; } + inline void TrackCost::mergeDataState ( unsigned int state ) { _dataState = (state>_dataState)?state:_dataState; } + inline string TrackCost::_getTypeName () const { return "TrackCost"; } + + +} // End of Kite namespace. + + +INSPECTOR_V_SUPPORT(Kite::TrackCost); + + +#endif // __KITE_TRACK_COST__ diff --git a/kite/src/kite/TrackElement.h b/kite/src/kite/TrackElement.h new file mode 100644 index 00000000..4f9449ac --- /dev/null +++ b/kite/src/kite/TrackElement.h @@ -0,0 +1,229 @@ + + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackElement.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_ELEMENT__ +#define __KITE_TRACK_ELEMENT__ + + +#include +#include + +#include "hurricane/Interval.h" +namespace Hurricane { + class Record; + class Net; + class Layer; +} + +#include "katabatic/AutoSegment.h" +#include "kite/Session.h" +#include "kite/TrackElements.h" + + +namespace Kite { + + + using std::string; + using std::map; + using Hurricane::Record; + using Hurricane::Interval; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Layer; + using Katabatic::AutoSegment; + + class DataNegociate; + class Track; + class TrackCost; + class GCell; + + + typedef map TrackElementLut; + typedef void (SegmentOverlapCostCB)( const TrackElement*, TrackCost& ); + + +// ------------------------------------------------------------------- +// Class : "TrackElement". + + + class TrackElement { + + public: + enum Flags { AddToGCells=0x1, RemoveFromGCells=0x2, UnRouted=0x4, Routed=0x8 }; + + public: + // Sub-Class: "Compare()". + class Compare { + public: + bool operator() ( TrackElement* lhs, TrackElement* rhs ); + }; + public: + // Sub-Class: "CompareByPosition()". + struct CompareByPosition { + bool operator() ( const TrackElement* lhs, const TrackElement* rhs ) const; + }; + + friend class Compare; + + + public: + static SegmentOverlapCostCB* setOverlapCostCB ( SegmentOverlapCostCB* ); + public: + void destroy (); + virtual AutoSegment* base () const = 0; + virtual bool isCreated () const; + virtual bool isBlockage () const; + virtual bool isFixed () const; + virtual bool isStrap () const; + virtual bool isSlackenStrap () const; + virtual bool isLocal () const; + virtual bool isGlobal () const; + virtual bool isLocked () const; + virtual bool isTerminal () const; + virtual bool isRevalidated () const; + virtual bool isRouted () const; + virtual bool isSlackened () const; + virtual bool isSlackenDogLeg () const; + virtual bool isHorizontal () const = 0; + virtual bool isVertical () const = 0; + virtual bool allowOutsideGCell () const; + virtual bool canDesalignate () const; + virtual bool canGoOutsideGCell () const; + virtual bool canSlacken () const; + virtual bool canPivotUp () const; + virtual bool canMoveUp () const; + virtual bool canRipple () const; + virtual bool hasSourceDogLeg () const; + virtual bool hasTargetDogLeg () const; + virtual bool canDogLeg (); + virtual bool canDogLeg ( Interval ); + virtual bool canDogLegAt ( GCell*, bool allowReuse=false ); + virtual unsigned long getId () const; + virtual unsigned int getDirection () const = 0; + virtual Net* getNet () const = 0; + virtual const Layer* getLayer () const = 0; + inline Track* getTrack () const; + inline size_t getIndex () const; + virtual unsigned long getArea () const; + virtual unsigned int getDogLegLevel () const; + virtual unsigned int getDogLegOrder () const; + virtual TrackElement* getNext () const; + virtual TrackElement* getPrevious () const; + virtual DbU::Unit getAxis () const = 0; + inline DbU::Unit getSourceU () const; + inline DbU::Unit getTargetU () const; + inline DbU::Unit getLength () const; + virtual Interval getFreeInterval ( bool useOrder=false ) const; + inline Interval getCanonicalInterval () const; + virtual Interval getSourceConstraints () const; + virtual Interval getTargetConstraints () const; + virtual DataNegociate* getDataNegociate () const; + virtual TrackElement* getCanonical ( Interval& ); + virtual GCell* getGCell () const; + virtual size_t getGCells ( vector& ) const; + virtual TrackElement* getSourceDogLeg (); + virtual TrackElement* getTargetDogLeg (); + virtual TrackElements getCollapsedPerpandiculars (); + virtual size_t getPerpandicularsBound ( set& ); + virtual unsigned int getOrder () const; + virtual void incOverlapCost ( Net*, TrackCost& ) const; + virtual void dataInvalidate (); + virtual void eventInvalidate (); + virtual void setAllowOutsideGCell ( bool ); + virtual void setRevalidated ( bool ); + virtual void setCanRipple ( bool ); + virtual void setSourceDogLeg ( bool state=true ); + virtual void setTargetDogLeg ( bool state=true ); + virtual void setLock ( bool ); + virtual void setRouted ( bool ); + virtual void setTrack ( Track* ); + inline void setIndex ( size_t ); + virtual void setGCell ( GCell* ); + virtual void setArea (); + virtual void setDogLegLevel ( unsigned int ); + virtual void setDogLegOrder ( unsigned int ); + virtual void updateGCellsStiffness ( unsigned int ); + virtual void swapTrack ( TrackElement* ); + virtual void reschedule ( unsigned int level ); + virtual void detach (); + virtual void revalidate ( bool invalidEvent=false ); + virtual void invalidate (); + virtual void setAxis ( DbU::Unit, unsigned int flags=Katabatic::AxisSet ); + virtual void slacken (); + virtual bool moveUp (); + virtual bool moveAside ( bool onLeft ); + virtual TrackElement* makeDogLeg (); + virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg ); + virtual TrackElement* makeDogLeg ( GCell* ); + virtual TrackElement* _postDogLeg ( GCell* ); + virtual void _postModify (); + virtual void desalignate (); + virtual bool _check () const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + // Static Attributes. + static SegmentOverlapCostCB* _overlapCostCallback; + // Attributes. + Track* _track; + size_t _index; + DbU::Unit _sourceU; + DbU::Unit _targetU; + + protected: + // Constructors & Destructors. + TrackElement ( Track* ) ; + virtual ~TrackElement (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + TrackElement ( const TrackElement& ); + TrackElement& operator= ( const TrackElement& ); + + }; + + +// Inline functions. + inline Track* TrackElement::getTrack () const { return _track; } + inline size_t TrackElement::getIndex () const { return _index; } + inline DbU::Unit TrackElement::getLength () const { return getTargetU() - getSourceU(); } + inline DbU::Unit TrackElement::getSourceU () const { return _sourceU; } + inline DbU::Unit TrackElement::getTargetU () const { return _targetU; } + inline Interval TrackElement::getCanonicalInterval () const { return Interval(getSourceU(),getTargetU()); } + inline void TrackElement::setIndex ( size_t index ) { _index = index; } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::TrackElement); + + +# endif diff --git a/kite/src/kite/TrackElements.h b/kite/src/kite/TrackElements.h new file mode 100644 index 00000000..8922af6d --- /dev/null +++ b/kite/src/kite/TrackElements.h @@ -0,0 +1,158 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackElements.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_TRACKELEMENTS_H__ +#define __KITE_TRACKELEMENTS_H__ + +#include "katabatic/AutoSegments.h" + + +namespace Kite { + + + using std::string; + using std::set; + + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Box; + using Hurricane::Hook; + using Hurricane::Component; + using Hurricane::Contact; + using Hurricane::Segment; + using Hurricane::Net; + using Hurricane::Filter; + using Hurricane::Locator; + using Hurricane::Collection; + using Hurricane::GenericFilter; + using Hurricane::GenericLocator; + using Hurricane::GenericCollection; + + using Katabatic::AutoSegments_CollapsedPerpandicular; + + class TrackElement; + + +// ------------------------------------------------------------------- +// Collections. + + + typedef Hurricane::Filter TrackElementHF; + typedef Hurricane::Locator TrackElementHL; + typedef Hurricane::Collection TrackElementHC; + typedef GenericCollection TrackElements; + typedef GenericLocator TrackElementLocator; + typedef GenericFilter TrackElementFilter; + + +// ------------------------------------------------------------------- +// Class : "TrackElements_CollapsedPerpandicular". + + + class TrackElements_CollapsedPerpandicular : public TrackElementHC { + + public: + // Sub-Class: Locator. + class Locator : public TrackElementHL { + public: + Locator ( TrackElement* segment ); + inline Locator ( const Locator& ); + virtual TrackElement* getElement () const; + virtual TrackElementHL* getClone () const; + virtual bool isValid () const; + virtual void progress (); + virtual string _getString () const; + protected: + AutoSegments_CollapsedPerpandicular::Locator _locator; + TrackElement* _element; + }; + + public: + // TrackElements_CollapsedPerpandicular Methods. + inline TrackElements_CollapsedPerpandicular ( TrackElement* segment ); + inline TrackElements_CollapsedPerpandicular ( const TrackElements_CollapsedPerpandicular& ); + virtual TrackElementHC* getClone () const; + virtual TrackElementHL* getLocator () const; + virtual string _getString () const; + + protected: + // TrackElements_CollapsedPerpandicular Attributes. + TrackElement* _segment; + }; + + + inline TrackElements_CollapsedPerpandicular::Locator::Locator ( const Locator& locator ) + : TrackElementHL() + , _locator (locator._locator) + , _element (NULL) + { } + + + inline TrackElements_CollapsedPerpandicular::TrackElements_CollapsedPerpandicular + ( TrackElement* segment ) + : TrackElementHC() + , _segment (segment) + { } + + + inline TrackElements_CollapsedPerpandicular::TrackElements_CollapsedPerpandicular + ( const TrackElements_CollapsedPerpandicular& tracksegments ) + : TrackElementHC() + , _segment (tracksegments._segment) + { } + + +// ------------------------------------------------------------------- +// Class : "TrackElements_UniqCanonical". + + + class TrackElements_UniqCanonical : public TrackElementHF { + public: + inline TrackElements_UniqCanonical ( set& ); + inline TrackElements_UniqCanonical ( const TrackElements_UniqCanonical& ); + virtual TrackElementHF* getClone () const; + virtual bool accept ( TrackElement* segment ) const; + virtual string _getString () const; + private: + set& _canonicals; + }; + + + inline TrackElements_UniqCanonical::TrackElements_UniqCanonical ( set& canonicals ) + : TrackElementHF() + , _canonicals(canonicals) + {} + + + inline TrackElements_UniqCanonical::TrackElements_UniqCanonical ( const TrackElements_UniqCanonical& filter ) + : TrackElementHF() + , _canonicals(filter._canonicals) + {} + + +} // End of Kite namespace. + + +#endif // __KITE_TRACKELEMENTS__ diff --git a/kite/src/kite/TrackFixedSegment.h b/kite/src/kite/TrackFixedSegment.h new file mode 100644 index 00000000..82835d0e --- /dev/null +++ b/kite/src/kite/TrackFixedSegment.h @@ -0,0 +1,98 @@ + + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackFixedSegment.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_FIXED_SEGMENT__ +#define __KITE_TRACK_FIXED_SEGMENT__ + + +#include "kite/TrackElement.h" + + +namespace Kite { + + + using std::string; + using std::map; + using Hurricane::Record; + using Hurricane::Interval; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Layer; + + class Track; + + +// ------------------------------------------------------------------- +// Class : "TrackFixedSegment". + + + class TrackFixedSegment : public TrackElement { + public: + static TrackElement* create ( Track*, Segment* ); + public: + virtual AutoSegment* base () const; + virtual bool isFixed () const; + virtual bool isBlockage () const; + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual unsigned long getId () const; + virtual unsigned int getDirection () const; + virtual Net* getNet () const; + virtual const Layer* getLayer () const; + virtual TrackElement* getNext () const; + virtual TrackElement* getPrevious () const; + virtual DbU::Unit getAxis () const; + virtual Interval getFreeInterval ( bool useOrder=false ) const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + // Attributes. + Segment* _segment; + + protected: + // Constructors & Destructors. + TrackFixedSegment ( Track*, Segment* ) ; + virtual ~TrackFixedSegment (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + TrackFixedSegment ( const TrackFixedSegment& ); + TrackFixedSegment& operator= ( const TrackFixedSegment& ); + + }; + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::TrackFixedSegment); + + +# endif diff --git a/kite/src/kite/TrackMarker.h b/kite/src/kite/TrackMarker.h new file mode 100644 index 00000000..0e3ffea3 --- /dev/null +++ b/kite/src/kite/TrackMarker.h @@ -0,0 +1,119 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackMarker.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_MARKER__ +#define __KITE_TRACK_MARKER__ + +namespace Hurricane { + class RoutingPad; + class Net; +} + + +namespace Kite { + + using Hurricane::RoutingPad; + using Hurricane::Net; + + class Track; + + +// ------------------------------------------------------------------- +// Class : "TrackMarker". + + + class TrackMarker { + + public: + static TrackMarker* create ( RoutingPad*, size_t depth ); + void destroy (); + public: + Net* getNet () const; + inline DbU::Unit getSourceU () const; + inline DbU::Unit getTargetU () const; + inline Track* getTrack () const; + inline unsigned int getWeight ( const Track* ) const; + inline void setTrack ( Track* ); + Record* _getRecord () const; + string _getString () const; + string _getTypeName () const; + public: + class Compare { + public: + inline bool operator() ( const TrackMarker* lhs , const TrackMarker* rhs ) const; + inline bool operator() ( DbU::Unit lhsU, const TrackMarker* rhs ) const; + inline bool operator() ( const TrackMarker* lhs , DbU::Unit rhsU ) const; + private: + inline bool markerLess ( DbU::Unit lhsU, DbU::Unit rhsU ) const; + }; + + protected: + // Attributes. + RoutingPad* _routingPad; + DbU::Unit _sourcePosition; + DbU::Unit _targetPosition; + Track* _track; + unsigned int _weight; + unsigned int _refcount; + + protected: + // Constructors & destructors. + TrackMarker ( RoutingPad*, size_t depth ); + ~TrackMarker () {}; + private: + TrackMarker ( const TrackMarker& ); + TrackMarker& operator= ( const TrackMarker& ); + }; + + +// Inline Functions. + inline DbU::Unit TrackMarker::getSourceU () const { return _sourcePosition; } + inline DbU::Unit TrackMarker::getTargetU () const { return _targetPosition; } + inline Track* TrackMarker::getTrack () const { return _track; } + inline unsigned int TrackMarker::getWeight ( const Track* track ) const { return _weight; } + inline void TrackMarker::setTrack ( Track* track ) { _track = track; } + + inline bool TrackMarker::Compare::operator() ( const TrackMarker* lhs, const TrackMarker* rhs ) const + { return markerLess ( lhs->getSourceU(), rhs->getSourceU() ); } + + inline bool TrackMarker::Compare::operator() ( DbU::Unit lhsU, const TrackMarker* rhs ) const + { return markerLess ( lhsU, rhs->getSourceU() ); } + + inline bool TrackMarker::Compare::operator() ( const TrackMarker* lhs, DbU::Unit rhsU ) const + { return markerLess ( lhs->getSourceU(), rhsU ); } + + inline bool TrackMarker::Compare::markerLess ( DbU::Unit lhsU, DbU::Unit rhsU ) const + { return ( lhsU < rhsU ); } + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::TrackMarker); + + +#endif // __KITE_TRACK_MARKER__ diff --git a/kite/src/kite/TrackSegment.h b/kite/src/kite/TrackSegment.h new file mode 100644 index 00000000..e8277a47 --- /dev/null +++ b/kite/src/kite/TrackSegment.h @@ -0,0 +1,181 @@ + + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackSegment.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACK_SEGMENT__ +#define __KITE_TRACK_SEGMENT__ + + +#include "kite/TrackElement.h" + + +namespace Kite { + + + using std::string; + using std::map; + using Hurricane::Record; + using Hurricane::Interval; + using Hurricane::DbU; + using Hurricane::Net; + using Hurricane::Layer; + using Katabatic::AutoSegment; + + class DataNegociate; + class Track; + class TrackCost; + class GCell; + + +// ------------------------------------------------------------------- +// Class : "TrackSegment". + + + class TrackSegment : public TrackElement { + public: + static TrackElement* create ( AutoSegment*, Track*, bool& created ); + public: + virtual AutoSegment* base () const; + virtual bool isCreated () const; + virtual bool isFixed () const; + virtual bool isStrap () const; + virtual bool isSlackenStrap () const; + virtual bool isLocal () const; + virtual bool isGlobal () const; + virtual bool isLocked () const; + virtual bool isTerminal () const; + virtual bool isRevalidated () const; + virtual bool isSlackened () const; + virtual bool isSlackenDogLeg () const; + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual bool isRouted () const; + virtual bool allowOutsideGCell () const; + virtual bool canDesalignate () const; + virtual bool canGoOutsideGCell () const; + virtual bool canSlacken () const; + virtual bool canPivotUp () const; + virtual bool canMoveUp () const; + virtual bool canRipple () const; + virtual bool hasSourceDogLeg () const; + virtual bool hasTargetDogLeg () const; + virtual bool canDogLeg (); + virtual bool canDogLeg ( Interval ); + virtual bool canDogLegAt ( GCell*, bool allowReuse=false ); + virtual unsigned long getId () const; + virtual unsigned int getDirection () const; + virtual Net* getNet () const; + virtual const Layer* getLayer () const; + virtual unsigned long getArea () const; + virtual unsigned int getDogLegLevel () const; + virtual unsigned int getDogLegOrder () const; + virtual TrackElement* getNext () const; + virtual TrackElement* getPrevious () const; + virtual DbU::Unit getAxis () const; + virtual Interval getFreeInterval ( bool useOrder=false ) const; + virtual Interval getSourceConstraints () const; + virtual Interval getTargetConstraints () const; + virtual DataNegociate* getDataNegociate () const; + virtual TrackElement* getCanonical ( Interval& ); + virtual GCell* getGCell () const; + virtual size_t getGCells ( vector& ) const; + virtual TrackElement* getSourceDogLeg (); + virtual TrackElement* getTargetDogLeg (); + virtual TrackElements getCollapsedPerpandiculars (); + virtual size_t getPerpandicularsBound ( set& ); + virtual unsigned int getOrder () const; + virtual void updateGCellsStiffness ( unsigned int ); + virtual void dataInvalidate (); + virtual void eventInvalidate (); + virtual void setAllowOutsideGCell ( bool ); + virtual void setRevalidated ( bool ); + virtual void setCanRipple ( bool ); + virtual void setSourceDogLeg ( bool state=true ); + virtual void setTargetDogLeg ( bool state=true ); + virtual void setLock ( bool ); + virtual void setRouted ( bool ); + virtual void setTrack ( Track* ); + virtual void setGCell ( GCell* ); + virtual void setArea (); + virtual void setDogLegLevel ( unsigned int ); + virtual void setDogLegOrder ( unsigned int ); + virtual void swapTrack ( TrackElement* ); + virtual void reschedule ( unsigned int level ); + virtual void detach (); + virtual void revalidate ( bool invalidEvent=false ); + virtual void invalidate (); + virtual void setAxis ( DbU::Unit, unsigned int flags=Katabatic::AxisSet ); + virtual void slacken (); + virtual bool moveUp (); + virtual bool moveAside ( bool onLeft ); + virtual TrackElement* makeDogLeg (); + virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg ); + virtual TrackElement* makeDogLeg ( GCell* ); + virtual TrackElement* _postDogLeg ( GCell* ); + virtual void _postModify (); + virtual void desalignate (); + virtual bool _check () const; + virtual Record* _getRecord () const; + virtual string _getString () const; + virtual string _getTypeName () const; + + protected: + // Attributes. + AutoSegment* _base; + GCell* _gcell; + bool _created; + bool _lock; + bool _revalidated; + bool _sourceDogLeg; + bool _targetDogLeg; + bool _canRipple; + bool _routed; + unsigned long _area; + DataNegociate* _data; + unsigned int _dogLegLevel:4; + unsigned int _dogLegOrder:16; + + protected: + // Constructors & Destructors. + TrackSegment ( AutoSegment*, Track* ) ; + virtual ~TrackSegment (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + TrackSegment ( const TrackSegment& ); + TrackSegment& operator= ( const TrackSegment& ); + + }; + + +} // End of Kite namespace. + + +INSPECTOR_P_SUPPORT(Kite::TrackSegment); + + +# endif diff --git a/kite/src/kite/TrackSegmentCost.h b/kite/src/kite/TrackSegmentCost.h new file mode 100644 index 00000000..0e59ef1b --- /dev/null +++ b/kite/src/kite/TrackSegmentCost.h @@ -0,0 +1,108 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./TrackSegmentCost.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __TRACK_SEGMENT_COST__ +#define __TRACK_SEGMENT_COST__ + + +#include +#include + +#include "hurricane/DbU.h" +namespace Hurricane { + class Record; + class Net; +} + + +namespace Kite { + + + using std::vector; + using std::string; + using Hurricane::Record; + using Hurricane::DbU; + using Hurricane::Net; + + class TrackElement; + + +// ------------------------------------------------------------------- +// Class : "TrackSegmentCost". + + + class TrackSegmentCost { + + public: + TrackSegmentCost ( TrackElement* ); + ~TrackSegmentCost (); + inline unsigned int getTerminals () const; + inline unsigned int getRipupCount () const; + inline DbU::Unit getLeftMinExtend () const; + inline DbU::Unit getRightMinExtend() const; + inline Net* getNet () const; + DbU::Unit getWiringDelta ( DbU::Unit axis ) const; + inline void setRipupCount ( unsigned int ); + inline void incRipupCount (); + inline void decRipupCount (); + inline void resetRipupCount (); + void update ( TrackElement* ); + Record* _getRecord () const; + string _getString () const; + inline string _getTypeName () const; + + protected: + // Attributes. + unsigned int _terminals : 5; + unsigned int _ripupCount : 5; + DbU::Unit _leftMinExtend; + DbU::Unit _rightMinExtend; + Net* _net; + vector _attractors; + + }; + +// Inline Functions. + inline unsigned int TrackSegmentCost::getTerminals () const { return _terminals; } + inline unsigned int TrackSegmentCost::getRipupCount () const { return _ripupCount; } + inline DbU::Unit TrackSegmentCost::getLeftMinExtend () const { return _leftMinExtend; } + inline DbU::Unit TrackSegmentCost::getRightMinExtend () const { return _rightMinExtend; } + inline Net* TrackSegmentCost::getNet () const { return _net; } + inline void TrackSegmentCost::setRipupCount ( unsigned int count ) { _ripupCount = count; } + inline void TrackSegmentCost::incRipupCount () { _ripupCount++; } + inline void TrackSegmentCost::decRipupCount () { if (_ripupCount) _ripupCount--; } + inline void TrackSegmentCost::resetRipupCount () { _ripupCount = 0; } + inline string TrackSegmentCost::_getTypeName () const { return "TrackSegmentCost"; } + + +} // End of Kite namespace. + + +INSPECTOR_PV_SUPPORT(Kite::TrackSegmentCost); + + +#endif // __TRACK_SEGMENT_COST__ diff --git a/kite/src/kite/Tracks.h b/kite/src/kite/Tracks.h new file mode 100644 index 00000000..363fd4d5 --- /dev/null +++ b/kite/src/kite/Tracks.h @@ -0,0 +1,153 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./Tracks.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + + + +#ifndef __KITE_TRACKS__ +#define __KITE_TRACKS__ + +#include +#include "hurricane/Collection.h" +#include "hurricane/Interval.h" + + +namespace Kite { + + + using std::string; + using Hurricane::_TName; + using Hurricane::Locator; + using Hurricane::Collection; + using Hurricane::GenericLocator; + using Hurricane::GenericCollection; + using Hurricane::GenericFilter; + using Hurricane::Interval; + + class Track; + class RoutingPlane; + + typedef GenericCollection Tracks; + typedef GenericLocator TrackLocator; + typedef GenericFilter TrackFilter; + + +// ------------------------------------------------------------------- +// Class : "Tracks_Range". + + + class Tracks_Range: public Collection { + + public: + // Locator Sub-Class. + class Locator : public Hurricane::Locator { + public: + Locator ( const RoutingPlane* routingPlane + , const Interval& constraints ); + Locator ( const Locator& ); + virtual Hurricane::Locator* getClone () const; + virtual bool isValid () const; + virtual Track* getElement () const; + virtual void progress (); + virtual string _getString () const; + + protected: + const Interval _constraints; + Track* _track; + }; + + public: + // Tracks_Range Methods. + static Tracks get ( RoutingPlane* routingPlane + , Interval& constraints ); + Tracks_Range ( const RoutingPlane* routingPlane + , const Interval& constraints ); + Tracks_Range ( const Tracks_Range& ); + virtual Collection* getClone () const; + virtual Hurricane::Locator* getLocator () const; + virtual string _getString () const; + + protected: + // Tracks_Range Attributes. + const RoutingPlane* _routingPlane; + const Interval _constraints; + }; + + +// ------------------------------------------------------------------- +// Class : "Tracks_Spiral". + + + class Tracks_Spiral : public Collection { + + public: + // Locator Sub-Class. + class Locator : public Hurricane::Locator { + public: + Locator ( const RoutingPlane* routingPlane + , const Interval& optimal + , const Interval& constraints ); + Locator ( const Locator& ); + virtual Hurricane::Locator* getClone () const; + virtual bool isValid () const; + virtual Track* getElement () const; + virtual void progress (); + bool InOptimal () const; + virtual string _getString () const; + + protected: + const Interval _optimal; + const Interval _constraints; + Track* _minTrack; + Track* _maxTrack; + bool _onMin; + bool _inMinOptimal; + bool _inMaxOptimal; + }; + + public: + // Tracks_Spiral Methods. + static Tracks get ( RoutingPlane* routingPlane + , Interval& optimal + , Interval& constraints ); + Tracks_Spiral ( const RoutingPlane* routingPlane + , const Interval& optimal + , const Interval& constraints ); + Tracks_Spiral ( const Tracks_Spiral& ); + virtual Collection* getClone () const; + virtual Hurricane::Locator* getLocator () const; + virtual string _getString () const; + + protected: + // Tracks_Spiral Attributes. + const RoutingPlane* _routingPlane; + const Interval _optimal; + const Interval _constraints; + }; + + +} // End of Katabatic namespace. + + +#endif // __KITE_TRACKS__ diff --git a/kite/src/kite/VerticalTrack.h b/kite/src/kite/VerticalTrack.h new file mode 100644 index 00000000..33e178c6 --- /dev/null +++ b/kite/src/kite/VerticalTrack.h @@ -0,0 +1,65 @@ + +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved +// +// =================================================================== +// +// $Id$ +// +// x-----------------------------------------------------------------x +// | | +// | C O R I O L I S | +// | K i t e - D e t a i l e d R o u t e r | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Header : "./VerticalTrack.h" | +// | *************************************************************** | +// | U p d a t e s | +// | | +// x-----------------------------------------------------------------x + + +#ifndef __KITE_VERTICAL_TRACK__ +#define __KITE_VERTICAL_TRACK__ + +#include "kite/Track.h" + + +namespace Kite { + + +// ------------------------------------------------------------------- +// Class : "VerticalTrack". + + + class VerticalTrack : public Track { + + public: + static VerticalTrack* create ( RoutingPlane*, unsigned int index ); + virtual bool isHorizontal () const; + virtual bool isVertical () const; + virtual unsigned int getDirection () const; + virtual Point getPosition ( DbU::Unit coordinate ) const; + virtual string _getTypeName () const; + virtual Record* _getRecord () const; + + protected: + // Constructors & Destructors. + VerticalTrack ( RoutingPlane*, unsigned int index ); + virtual ~VerticalTrack (); + virtual void _postCreate (); + virtual void _preDestroy (); + private: + VerticalTrack ( const VerticalTrack& ); + VerticalTrack& operator= ( const VerticalTrack& ); + }; + + +} // End of Kite namespace. + + +#endif // __KITE_VERTICAL_TRACK__ diff --git a/kite/src/kiteRefactor.conf b/kite/src/kiteRefactor.conf new file mode 100644 index 00000000..6780bcf1 --- /dev/null +++ b/kite/src/kiteRefactor.conf @@ -0,0 +1,141 @@ + +# Refactoring patterns for Kite tool. + KiteFCell --> GCell + LoadRouting --> loadRouting + Update --> update + MIN_TRACK_MIN --> MinTrackMin + MIN_SEGMENT_MIN --> MinSegmentMin + MIN_SEGMENT_MAX --> MinSegmentMax + MAX_TRACK_MAX --> MaxTrackMax + MAX_SEGMENT_MIN --> MaxSegmentMin + MAX_NEXT_SEGMENT_MIN --> MaxNextSegmentMin + MAX_SEGMENT_MAX --> MaxSegmentMax + BEFORE_FIRST --> BeforeFirst + INSIDE --> Inside + OUTSIDE --> Outside + AFTER_LAST --> AfterLast + EMPTY_TRACK --> EmptyTrack + MIN_MASK --> MinMask + MAX_MASK --> MaxMask + EVENT_INSERT --> EventInsert + EVENT_RIPUP --> EventRipup + EVENT_DISPLACE --> EventDisplace + \bFind --> find + MISSING_DATA --> MissingData + MAXIMUM_RIPUP --> MaximumRipup + EMPTY_NATIVE_SLACK --> EmptyNativeSlack + EMPTY_BOUND_SLACK --> EmptyBoundSlack + INSERTED --> Inserted + \bPut --> put + \bProcess --> process + \b_SubProcess --> _subProcess + \b_Ripup --> _ripup + \b_PreCheck --> _preCheck + \b_PostCheck --> _postCheck +# Refactoring patterns for Katabatic tool. + TYPE_GLOBAL --> AutoSegment::Global + TYPE_LOCAL --> AutoSegment::Local + TYPE_GUESS --> AutoSegment::Guess + PERPANDICULAR_ANY --> AutoSegment::PerpandicularAny + PERPANDICULAR_INDIRECT --> AutoSegment::PerpandicularIndirect + PARALLEL_OR_EXPANDED --> AutoSegment::ParallelOrExpanded + PARALLEL_LAYER_CHANGE --> AutoSegment::ParallelAndLayerChange + \bCloseDebugSession --> DebugSession::close + \bOpenDebugSession --> DebugSession::open + \bSession::Close --> Session::close + \bSession::Open --> Session::open + \bSession::Revalidate --> Session::revalidate + \bCreateAutoSegment --> AutoSegment::create + \bLOAD_GR_BY_NET --> LoadGrByNet + \bLOAD_GR_BY_GCELL --> LoadGrByGCell + \bLAYER_ASSIGN_BY_LENGTH --> LayerAssignByLength + \bLAYER_ASSIGN_BY_TRUNK --> LayerAssignByTrunk + \b_LoadNetGlobalRouting --> _loadNetGlobalRouting + \b_LoadGlobalRouting --> _loadGlobalRouting + \b_LoadGRByNet --> _loadGrByNet + \b_LayerAssign --> _layerAssign + \b_Collapse --> _collapse + \b_DeleteAutoSegments --> _destroyAutoSegments + \b_Canonize --> _canonize + \b_SaveNet --> _saveNet + \b_lookup --> _lookup + \b_LinkAutoSegment --> _link + \b_UnlinkAutoSegment --> _unlink + \bLookup --> lookup + \bAutoInvalidate --> autoInvalidate + \bToConstraintAxis --> toConstraintAxis + \bToOptimalAxis --> toOptimalAxis + \bLoadGlobalRouting --> loadGlobalRouting + \bLayerAssign --> layerAssign + \bFCellGridConcrete --> GCellGrid + \bFCellGrid --> GCellGrid + \bStartMeasures --> startMeasures + \bStopMeasures --> stopMeasures + \bRefresh --> refresh + \bXml --> xml + \b_fcellGrid --> _gcellGrid + \bOnRevalidate --> onRevalidate + \bCollapse --> collapse + \bAlignate --> alignate + \bCanonize --> canonize + \bExpand --> expand + \bOrient --> orient +# Refactoring patterns for Hurricane. + \bCloseUpdateSession --> UpdateSession::open + \bOpenUpdateSession --> UpdateSession::close + \b_PostCreate --> _postCreate + \b_PreDelete --> _preDestroy + \bInvalidate --> invalidate + \bIntersect --> intersect + \bTranslate --> translate + \bProgress --> progress + \bContains --> contains + \b_AttachTo --> _attachTo + \bGetUnit --> DbU::lambda + \bCEngine --> ToolEngine + \bUnroute --> unroute + \bBreakUp --> breakUp + \b_MoveTo --> _moveTo + \bMoveTo --> moveTo + \bUpdate --> update + \bCreate --> create + \bDelete --> destroy + \bSort --> sort + \bKNIK --> Knik + \bUserGo --> ExtensionGo + \bExport --> export + \bFlush --> flush + \bUnit --> DbU::Unit + \bRestrict --> restrict + \b_Compute --> _compute + \bCompute --> compute + \bRestore --> restore + \bInflate --> inflate + \b_Remove --> _remove + \bAttach --> attach + \bAccept --> accept + \bRemove --> remove + \bDetach --> detach + \bExtract --> extract + \bPrint --> print + \bClear --> clear + \bCheck --> check + \bReset --> reset + \bMerge --> merge + \bInit --> init + \bHide --> hide + \bShow --> show + \bDump --> dump + \bAdd --> add + \bInc --> inc + \bDec --> dec + \bAdd --> add + \bGet --> get + \bSet --> set + \b_Get --> _get + \b_Set --> _set + \bIs --> is + \bHas --> has + \bAre --> are + \bis_a --> dynamic_cast +