diff --git a/knik/CMakeLists.txt b/knik/CMakeLists.txt
new file mode 100644
index 00000000..727e521d
--- /dev/null
+++ b/knik/CMakeLists.txt
@@ -0,0 +1,40 @@
+PROJECT(KNIK)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0)
+
+IF(APPLE)
+ EXECUTE_PROCESS(
+ COMMAND sw_vers -productVersion
+ OUTPUT_VARIABLE OSX_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ MESSAGE(STATUS "OSX_VERSION='${OSX_VERSION}'")
+ IF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
+ MESSAGE(STATUS "OSX < 10.6")
+ ELSE(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
+ SET(CMAKE_OSX_ARCHITECTURES "i386;ppc") # for QT4.5 32bits on snow leopard
+ ENDIF(${OSX_VERSION} MATCHES "^10\\.[012345]\\.?")
+ENDIF(APPLE)
+
+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)
+
+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")
+
+FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project
+FIND_PACKAGE(HURRICANE REQUIRED)
+FIND_PACKAGE(CORIOLIS REQUIRED)
+
+SET_LIB_LINK_MODE()
+
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(cmake_modules)
diff --git a/knik/cmake_modules/CMakeLists.txt b/knik/cmake_modules/CMakeLists.txt
new file mode 100644
index 00000000..d9c27fbe
--- /dev/null
+++ b/knik/cmake_modules/CMakeLists.txt
@@ -0,0 +1 @@
+install ( FILES FindKNIK.cmake DESTINATION /share/cmake_modules )
diff --git a/knik/cmake_modules/FindKNIK.cmake b/knik/cmake_modules/FindKNIK.cmake
new file mode 100644
index 00000000..e0694d93
--- /dev/null
+++ b/knik/cmake_modules/FindKNIK.cmake
@@ -0,0 +1,64 @@
+# - Find the Knik includes and libraries.
+# The following variables are set if Coriolis is found. If KNIK is not
+# found, KNIK_FOUND is set to false.
+# KNIK_FOUND - True when the Coriolis include directory is found.
+# KNIK_INCLUDE_DIR - the path to where the Coriolis include files are.
+# KNIK_LIBRARIES - The path to where the Coriolis library files are.
+
+
+SET(KNIK_INCLUDE_PATH_DESCRIPTION "directory containing the Knik/flute include files. E.g /usr/local/include/coriolis or /asim/coriolis/include/coriolis")
+
+SET(KNIK_DIR_MESSAGE "Set the KNIK_INCLUDE_DIR cmake cache entry to the ${KNIK_INCLUDE_PATH_DESCRIPTION}")
+
+# don't even bother under WIN32
+IF(UNIX)
+
+ SET(KNIK_DIR_SEARCH $ENV{CORIOLIS_TOP} $ENV{HURRICANE_TOP})
+ #
+ # Look for an installation.
+ #
+ FIND_PATH(KNIK_INCLUDE_PATH NAMES knik/KnikEngine.h PATHS
+ # Look in other places.
+ ${KNIK_DIR_SEARCH}
+ PATH_SUFFIXES include/coriolis
+ # Help the user find it if we cannot.
+ DOC "The ${KNIK_INCLUDE_PATH_DESCRIPTION}"
+ )
+
+ FIND_LIBRARY(KNIK_LIBRARY_PATH
+ NAMES knik
+ PATHS ${KNIK_DIR_SEARCH}
+ PATH_SUFFIXES lib
+ # Help the user find it if we cannot.
+ DOC "The ${KNIK_INCLUDE_PATH_DESCRIPTION}"
+ )
+
+ FIND_LIBRARY(KNIK_STATIC_LIBRARY_PATH
+ NAMES knik-static
+ PATHS ${KNIK_DIR_SEARCH}
+ PATH_SUFFIXES lib
+ # Help the user find it if we cannot.
+ DOC "The ${KNIK_INCLUDE_PATH_DESCRIPTION}"
+ )
+
+ FIND_LIBRARY(FLUTE_LIBRARY_PATH
+ NAMES flute
+ PATHS ${KNIK_DIR_SEARCH}
+ PATH_SUFFIXES lib
+ # Help the user find it if we cannot.
+ DOC "The ${KNIK_INCLUDE_PATH_DESCRIPTION}"
+ )
+
+ FIND_LIBRARY(FLUTE_STATIC_LIBRARY_PATH
+ NAMES flute-static
+ PATHS ${KNIK_DIR_SEARCH}
+ PATH_SUFFIXES lib
+ # Help the user find it if we cannot.
+ DOC "The ${KNIK_INCLUDE_PATH_DESCRIPTION}"
+ )
+
+ SET_LIBRARIES_PATH(KNIK FLUTE)
+ SET_LIBRARIES_PATH(KNIK KNIK)
+ HURRICANE_CHECK_LIBRARIES(KNIK)
+
+ENDIF(UNIX)
diff --git a/knik/doc/ASIM.css b/knik/doc/ASIM.css
new file mode 100644
index 00000000..ce3c1f5b
--- /dev/null
+++ b/knik/doc/ASIM.css
@@ -0,0 +1,428 @@
+
+
+/*
+ * 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%; }
+
+ .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).
+ */
+
+ 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; }
+
+ 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: 4px;
+ 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;
+ border-left-width: 4px;
+ border-left-style: solid;
+ background-color: #ECFFEC;
+ }
+
+ .memproto {
+ background-color: #CCE6CA;
+ }
+
+ .memname {
+ white-space: nowrap;
+ padding-left: 5px;
+ font-size: 105%;
+ }
+
+
+ .memdoc{
+ padding-left: 20px;
+ }
+
+ .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/knik/doc/Edge.dox b/knik/doc/Edge.dox
new file mode 100644
index 00000000..ec571bed
--- /dev/null
+++ b/knik/doc/Edge.dox
@@ -0,0 +1,347 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class Edge
+ * \brief A routing graph edge.\n
+ * - \ref EdgeAttributes "Attributes"
+ * - \ref EdgeAccessors "Accessors"
+ * - \ref EdgeModifiers "Modifiers"
+ * - \ref EdgePredicates "Predicates"
+ *
+ * The Edge was written to be a light object which simplifies the way the routing graph is covered.
+ * Edges are thus separated into two sub-classes : VEdge and HEdge respectively representing vertical edge and
+ * horizontal edge.
+ *
+ * Considering one vertex \b V, we define 4 types of edge :
+ *
+ * - HEdgeOut: a Horizontal Edge linking \b V to a vertex \e w
+ *
- VEdgeOut: a Vertical Edge linking \b V to a vertex \e x
+ *
- HEdgeIn: a Horizontal Edge linking a vertex \e y to \b V
+ *
- VEdgeIn: a Vertical Edge linking a vertex \e z to \b V
+ *
+ *
+ * \section secEdgeImplementation Edge Implementation
+ * The Global Router CEngine uses a technique based on routing graph and thus relies on another
+ * CEngine : Nimbus.
+ */
+
+ /*! \anchor EdgeAttributes Attributes
+ * \name
+ */
+ // \{
+ /*! \var Fence* Edge::_fence
+ * The corresponding fence in the partitionning
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var Splitter* Edge::_splitter
+ * The fence may already have a splitter associted with current net
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var Vertex* Edge::_from
+ * The source vertex
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var Edge* Edge::_nextFrom
+ * Next edge of the same type and with the same source vertex
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var Vertex* Edge::_to
+ * The target vertex
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var Edge* Edge::_nextTo
+ * Next edge of the same type and with the same target vertex
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var int Edge::_connexID
+ * The identification flag for connex component
+ *
+ * \Initial \p -1
+ * \see \ref grpConnexID
+ */
+
+ /*! \var float Edge::_cost
+ * The cost of the edge
+ *
+ * \Initial \p 0.0
+ * \see Edge::GetCost
+ */
+
+ /*! \var unsigned Edge::_capacity
+ * The capacity of the edge which is the copy of the fence capacity based on the routing ressources
+ *
+ * \Initial \p 0
+ */
+
+ /*! \var unsigned Edge::_realOccupancy
+ * The occupancy of the edge based on the routed nets
+ *
+ * \Initial \p 0
+ */
+
+ /*! \var float Edge::_estimateOccupancy
+ * The estimated occupancy of the edge based on the estimation technique
+ *
+ * \Initial \p 0.0
+ * \see Graph::UpdateEstimateCongestion
+ */
+
+ /*! \var unsigned Edge::_netStamp
+ * The net stamp associated with the current net
+ *
+ * \Initial \p 0
+ * \see \ref grpNetStamp
+ */
+ // \}
+
+ /*! \anchor EdgeAccessors Accessors
+ * \name
+ */
+ // \{
+
+ /*! \function Nimbus::Fence* Edge::GetFence();
+ * \Return The corresponding Fence in the partitionning.
+ */
+
+ /*! \function Vertex* Edge::GetFrom() const;
+ * \Return The source vertex of the edge.
+ */
+
+ /*! \function Edge* Edge::GetNextFrom() const;
+ * \Return The next edge of the same type with the same source vertex if one exists, \NULL else.
+ */
+
+ /*! \function Vertex* Edge::GetTo() const;
+ * \Return The target vertex of the edge.
+ */
+
+ /*! \function Edge* Edge::GetNextTo() const;
+ * \Return The next edge of the same type with the same target vertex if one exists, \NULL else.
+ */
+
+ /*! \function Edge* Edge::GetSplitter() const;
+ * \Return The splitter associated with the edge if one exists, \NULL else.
+ */
+
+ /*! \function int* Edge::GetConnexID() const;
+ * \Return The ConnexID of the edge.
+ */
+
+ /*! \function float* Edge::GetCapacity() const;
+ * \Return The capacity of the edge.
+ */
+
+ /*! \function unsigned Edge::GetRealOccupancy() const;
+ * \return The occupancy of the edge based on the class member Edge::_realOccupancy
+ * \exception assert that Edge::_realOccupancy equals Edge::_fence->GetOccupancy()
+ */
+
+ /*! \function unsigned Edge::GetNetStamp() const;
+ * \return The netStamp of the edge
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function Vertex* Edge::GetOpposite(const Vertex* v) const;
+ * \return The opposite vertex of the edge considering the one given as argument.
+ * \param v is the vertex of which we want to get the opposite one
+ * \exception assert that \e v is one of the 2 vertexes of the edge
+ */
+
+ /*! \function float Edge::GetEstimateOccupancy() const;
+ * \return The estimated occupancy of the edge
+ * \note Althought the Edge::_realOccupancy is an \p unsigned \p int, the Edge::_estimateOccupancy is a \p float.
+ * \see Edge::GetCost
+ */
+
+ /*! \function float Edge::GetCost ( Edge* arrivalEdge );
+ * \param arrivalEdge
+ * \return The cost of the edge Edge::_cost
+ *
+ * Edge::_cost is computed considering several variables:
+ *
+ * - \ref KNIK_USECONGESTION "__USE_CONGESTION__"
+ *
- \ref KNIK_USESTATIC "__USE_STATIC_PRECONGESTION__"
+ *
- \ref KNIK_USEDYNAMIC "__USE_DYNAMIC_PRECONGESTION__"
+ *
+ *
+ * 1st case: None of the previous variables is defined :
+ *
+ * \code _cost = 1.0
+ * \endcode
+ *
+ * For 2nd and 3rd case the \ref KNIK_USECONGESTION "__USE_CONGESTION__" variable is defined which means that when
+ * computing the Edge::_cost the existing congestion is taken into account.
+ *
+ * The Edge::_cost is so computed according to a cost function such as the following exemple :
+ * \image html FonctionCout.png "Cost function for _cost"
+ * \image latex FonctionCout.pdf "Cost function for _cost" width=0.7\textwidth
+ *
+ * The corresponding code:
+ * \code
+ * float edge_capacity =(float)1.0;
+ * float edge_occupancy;
+ * float h = 9.0;
+ * float k = 30.0;
+ * ...
+ * _cost = 1.0 + (h / (1.0 + exp(-k * (edge_occupancy - edge_capacity))));
+ * \endcode
+ * The way \p edge_occupancy is computed depends on the variables defined :
+ *
+ * 2nd case: only \ref KNIK_USECONGESTION "__USE_CONGESTION__" is defined :
+ * \code edge_occupancy = (float)GetRealOccupancy() / (float)_capacity;
+ * \endcode
+ *
+ * 3rd case: \ref KNIK_USESTATIC "__USE_STATIC_PRECONGESTION__"
+ * or \ref KNIK_USEDYNAMIC "__USE_DYNAMIC_PRECONGESTION__" is defined :
+ * \code edge_occupancy = ((float)GetRealOccupancy() + GetEstimateOccupancy()) / (float)_capacity;
+ * \endcode
+ *
+ */
+
+ /*! \function virtual Hook* Edge::GetSplitterHook ( Vertex* vertex ) = 0;
+ * \param vertex the vertex of the edge from which we want to get the splitter's hook
+ * \return The splitter's hook of the specified vertex
+ * \exception assert that Edge::_splitter exists
+ * \exception assert that the given vertex is Edge::_from or Edge::_to
+ * \note This function is pure virtual.
+ */
+
+ // \}
+
+ /*! \anchor EdgeModifiers Modifiers
+ * \name
+ */
+ // \{
+
+ /*! \function void Edge::SetNextFrom ( Edge* edge );
+ * \param edge is the next edge of the same type with the same source vertex
+ */
+
+ /*! \function void Edge::SetNextTo ( Edge* edge );
+ * \param edge is the next edge of the same type with the same target vertex
+ */
+
+ /*! \function void Edge::SetSplitter ( Splitter* splitter );
+ * \param splitter is the splitter associated to the edge for the current net
+ */
+
+ /*! \function void Edge::SetConnexID ( int connexID );
+ * \param connexID is the connexID of the edge
+ * \see \ref grpConnexID
+ */
+
+ /*! \function void Edge::SetCost ( float cost );
+ * \param cost is the new cost for the edge
+ */
+
+ /*! \function void Edge::IncCost ( float inc );
+ * \param inc is an increment, it is added to the current Edge::_cost
+ */
+
+ /*! \function void Edge::SetNetStamp ( unsigned netStamp );
+ * \param netStamp is the netStamp of the edge for the current net
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function void Edge::AddSubEstimateOccupancy ( float increment, bool add );
+ * \param increment is the value added / substracted to the estimate occupancy
+ * \param add is a boolean : if set to \True an addition is performed whether if set to \False a substraction is performed
+ */
+
+ /*! \function virtual void Edge::CreateSplitter ( Net* net ) = 0;
+ * \param net the current net for which we want to create a splitter on the Edge
+ * \note This function is pure virtual.
+ */
+
+ // \}
+
+ /*! \anchor EdgePredicates Predicates
+ * \name
+ */
+ // \{
+
+ /*! \function virtual bool Edge::IsVertical ();
+ * \return Return \True if the edge is a vertical edge, else \False
+ * \note This function is pure virtual.
+ */
+
+ /*! \function virtual bool Edge::IsHorizontal ();
+ * \return Return \True if the edge is a horizontal edge, else \False
+ * \note This function is pure virtual.
+ */
+
+ // \}
+
+ /*! \defgroup grpConnexComponent What is a Connex Component ?
+ *
+ * \section secDefinition Definition
+ *
+ * A connex component is a set of vertexes and edges representing a connex part of a net, such as :
+ *
+ * - a connector contained in a GCell
+ *
- a connector spread over several GCells
+ *
- a pre-routed part of a net
+ *
- an already routed part of a net (by previous steps)
+ *
+ *
+ * \image html ConnexComp.png "Connex components exemples for connectors (left) and a routed net (right)"
+ * \image latex ConnexComp.pdf "Connex components exemples for connectors (left) and a routed net (right)" width=0.7\textwidth
+ *
+ * It is also important to note that a connex component has a treelike topology, i.e without any cycle.
+ *
+ * \section secUse Use
+ * Global routing a net consists in transforming a list of several connex components into a unique connex component.
+ *
+ * \see \ref grpConnexID
+ */
+
+ /*! \defgroup grpConnexID What is a ConnexID ?
+ *
+ * \section secDefinition Definition
+ *
+ * A ConnexID is closely linked with the Connex Component concept.
+ * In fact, for a given net, each connex component has its own ConnexID
+ *
+ * \section secImplementation Implementation
+ *
+ * A ConnexID is represented as an \p int. All positive values from 0, may represent a connex component, whereas a connexID
+ * set to \p -1 means that the element (vertex or edge) isn't part of any connex component.
+ *
+ * By construction each element has its connexID set to \p -1
+ *
+ * \section secUse Use
+ * When global routing and thus merging connex components it is always the smaller ConnexID that is kept.
+ * This implies that the last unique connex component will have a ConnexID equal to 0 (when global routing is finished
+ * for the net)
+ *
+ * \see \ref grpConnexComponent
+ *
+ */
+
+ /*! \defgroup grpNetStamp What is a netStamp ?
+ *
+ * \section secDefinition Definition
+ *
+ * blablabla
+ *
+ *
+ *
+ */
+
+}
+
diff --git a/knik/doc/Global.dox b/knik/doc/Global.dox
new file mode 100644
index 00000000..b7e8348f
--- /dev/null
+++ b/knik/doc/Global.dox
@@ -0,0 +1,80 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \namespace KNIK
+ * \brief The namespace dedicated to Knik.
+ *
+ * \section secUsefulDefines Useful defines
+ *
+ *
+ * \anchor KNIK_USECONGESTION
+ * \define __USE_CONGESTION__
+ * \defineD if defined, algorithms will use congestion, useful for edge cost
+ * \defineEND
+ *
+ * \anchor KNIK_USESTATIC
+ * \define __USE_STATIC_PRECONGESTION__
+ * \defineD if defined, algorithms will use static precongestion which means that precongestion will
+ * be computed but NOT UPDATED
+ * \defineEND
+ *
+ * \anchor KNIK_USEDYNAMIC
+ * \define __USE_DYNAMIC_PRECONGESTION__
+ * \defineD if defined, algorithms will use dynamic precongestion which means taht precongestion,
+ * once computed, will be updated considering the current routing congestion
+ * \defineEND
+ * \note The 2 last variables are mutually exclusive
+ */
+
+ /*! \mainpage Global Router Documentation
+ *
+ * This is the documentation of \c Knik which is a global router for Coriolis platform.
+ *
+ * \section secGlobalDesciption Description
+ * This global router is written to be (I hope) a fast and efficient algorithm so it can be use is a refinment loop.
+ * To solve the global routing problem, it uses monotonic routing algorithm (for bi-point nets) and Dijkstra's algorithm.
+ * It also uses an efficient congestion estimation based on Steiner trees generation.
+ *
+ * \section secGlobalOverview Overview
+ * Let's have an overview of the general algorithm of \c Knik :
+ * \code
+ * Knik::InitGlobalRouting ();
+ * // This function prepares everything that the global routing algorithms will need :
+ * // - creates the routing graph
+ * // - fills the _nets_to_route vector by selecting nets that have to be routed
+ *
+ * Graph::SetNetStamp (1);
+ * // initializes the netStamp of the first net that will be routed on the routingGraph
+ *
+ * for each net in Knik::_nets_to_route :
+ * netDegree = Graph::InitRouting ( net );
+ * // this function works on the routingGraph and prepares it for routing a specific net
+ * // - creates each connex component of the net and add a vertex of each connex component to the Graph::_vertexes_to_route vector
+ * // - it returns _vertexes_to_route.size() which is the degree of the net
+ *
+ * // the choice of the global routing algorithm is done based on the degree of the net
+ * switch ( netDegree )
+ * // if netDegree is equal to 0 or 1 : there is nothing to be done
+ * case 0:
+ * case 1:
+ * break;
+ * // if netDegree is equal to 2 : the Monotonic routing algorithm will be used
+ * case 2:
+ * Graph::Monotonic ();
+ * break;
+ * // if netDegree is equal to 3 or more : the Dijkstra's algorithm will be used
+ * default:
+ * Graph::Dijkstra ();
+ * break;
+ *
+ * Graph::IncNetStamp (); // Increments Graph::_netStamp
+ * Graph::CleanRoutingState (); // Cleans the routing graph structure so it can be propoerly reuse with next net
+ * \endcode
+ *
+ */
+
+ }
+
diff --git a/knik/doc/Graph.dox b/knik/doc/Graph.dox
new file mode 100644
index 00000000..f1ef3982
--- /dev/null
+++ b/knik/doc/Graph.dox
@@ -0,0 +1,622 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class Graph
+ * \brief The routing graph.\n
+ * - \ref GraphAttributes "Attributes"
+ * - \ref GraphConstructors "Constructors"
+ * - \ref GraphAccessors "Accessors"
+ * - \ref GraphModifiers "Modifiers"
+ * - \ref GraphTupleQueue "Tuple Priority Queue Methods"
+ *
+ * \section secGraphImplementation Graph Implementation
+ * CEngine : Nimbus.
+ *
+ * \section secGraphUseful Useful defines
+ *
+ * \define EPSILON 10e-4
+ * \defineD EPSILON is used two avoid several float roudness problems
+ * \defineEND
+ *
+ * \anchor GRAPH_FLUTELIMIT
+ * \define FLUTE_LIMIT 150
+ * \defineD When using congestion, FLUTE algorithm will not work properly if number
+ * of pins exceed a limit : MAXD.\n
+ * Knik algorithm must not pass net with more than FLUTE_LIMIT pins to FLUTE.\n
+ * \n
+ * Flute.h:
+ * \code #define MAXD 150 // Setting MAXD to more than 150 is not recommended
+ * \endcode
+ * \defineEND
+ *
+ * \define __USE_SLICINGTREE__
+ * \defineD if defined, the search of a vertex givenits position will be done using a slicingtree instead of using nimbus methods.\n
+ * Using the slicing tree really faster
+ * \defineEND
+ */
+
+ /*! \anchor GraphAttributes Attributes
+ * \name
+ */
+ // \{
+ /*! \var Nimbus* Graph::_nimbus
+ * The corresponding partitionning
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var SlicingTree* Graph::_slicingTree;
+ * The slicing tree, useful for searching a vertex given its position
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var Net* Graph::_working_net;
+ * The curret working net, all algorithms in Graph will refer to this net
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var VertexSet Graph::_vertexes_to_route;
+ * The set of vertexes to route, given a working net to route we can create this set
+ *
+ * \Initial empty
+ * \see Graph::InitRouting
+ */
+
+ /*! \var Vertex* Graph::_lowerLeftVertex;
+ * The lower left vertex of the graph, useful to skim through the graph
+ */
+
+ /*! \var VertexVector Graph::_all_vertexes;
+ * The vector of all the vertexes
+ */
+
+ /*! \var EdgeVector Graph::_all_edges;
+ * The vector of all the edges
+ */
+
+ /*! \var TuplePriorityQueue Graph::_tuplePriorityQueue;
+ * The tuple priority queue for Dijkstra's algorithm implementation
+ */
+
+ /*! \var Box Graph::_searchingArea;
+ * The _searchingArea limits the Dijkstra's algorithm toa certain range
+ */
+
+ /*! \var unsigned Graph::_netStamp
+ * The net stamp associated with the working net
+ *
+ * \Initial \p 0
+ * \see \ref grpNetStamp
+ */
+ // \}
+
+ /*! \anchor GraphConstructors Constructors
+ * \name
+ */
+ // \{
+ /*! \function static Graph* Graph::Create ( Nimbus* nimbus, RoutingGrid* routingGrid, bool benchMode, bool useSegments );
+ * \param nimbus the partionning needed to create the routing graph
+ * \param routingGrid the routingGrid, may be \NULL
+ * \param benchMode for ispd global routing benchmarks
+ * \param useSegments defines if routing is done with segments or splitters
+ * \return the newly created graph
+ */
+ // \}
+
+ /*! \anchor GraphAccessors Accessors
+ * \name
+ */
+ // \{
+
+ /*! \function Hurricane::Cell* Graph::GetCell();
+ * \Return the current top cell
+ */
+
+ /*! \function unsigned Graph::GetNetStamp();
+ * \Return the net stamp of the current working net
+ */
+
+ /*! \function Vertex* Graph::GetPredecessor ( const Vertex* vertex )
+ * \param vertex is the vertex from which we want to get the predecessor
+ * \return the predecessor vertex
+ */
+
+ /*! \function Vertex* Graph::GetCentralVertex ();
+ * \Return the most central vertex of Graph::_vertexes_to_route
+ */
+
+ /*! \function Vertex* Graph::GetVertex ( Point p );
+ * \param p a position
+ * \return the vertex which corresponds to the position
+ */
+
+ /*! \function Vertex* Graph::GetVertex ( Unit x, Unit y );
+ * \param x is the x coordinate of the position
+ * \param y is the y coordinate of the position
+ * \return the vertex which corresponds to the position
+ */
+
+ // \}
+
+ /*! \anchor GraphModifiers Modifiers
+ * \name
+ */
+ // \{
+
+ /*! \function void Graph::CreateHEdge ( Vertex* from, Vertex* to, Fence* fence, DisplaySlot* displaySlot );
+ * \param from the source vertex
+ * \param to the target vertex
+ * \param fence the corresponding fence
+ * \param displaySlot the GTK displaytSlot for edges' graphical display
+ */
+
+ /*! \function void Graph::CreateVEdge ( Vertex* from, Vertex* to, Fence* fence, DisplaySlot* displaySlot );
+ * \param from the source vertex
+ * \param to the target vertex
+ * \param fence the corresponding fence
+ * \param displaySlot the GTK displaytSlot for edges' graphical display
+ */
+
+ /*! \function void Graph::InitConnexComp ( Vertex* vertex, int newConnexID = -1 );
+ * This function initialize a connex component as the source on for Dijkstra's algorithm implementation, the connex component
+ * is considered based on the connexID of given vertex.\n
+ * The connexID of the connex component may be changed by specifiing it as argument, if not the connexID will not be changed.
+ * \param vertex one vertex of the connex component
+ * \param newConnexID the new connexID for the connex component (optional)
+ * \see \ref grpConnexID, \ref grpConnexComponent
+ */
+
+ /*! \function void Graph::InitConnexComp ( Vertex* vertex, Edge* arrivalEdge, int newConnexID );
+ * This is the recusive part of Graph::InitConnexComp
+ * \param vertex one vertex of the connex component
+ * \param arrivalEdge the edge that leads to the current vertex (in order not to skim through it again)
+ * \param newConnexID the new connexID for the connex component
+ * \see \ref grpConnexID, \ref grpConnexComponent
+ */
+
+ /*! \function void Graph::UpdateConnexComp ( VertexList reachedVertexes, Vertex* firstVertex );
+ * This function create the new connex component from a reached vertex to the first source vertex thanks to the path
+ * found by global routing.
+ * \param reachedVertexes is the list of reachedVertexes (see Bug)
+ * \param firstVertex is the source vertex
+ * \see \ref grpConnexID, \ref grpConnexComponent
+ * \bug The parameter VertexList reachedVertexes should be a simple Vertex* reachedVertex !
+ */
+
+ /*! \function void Graph::MaterializeRouting ( Vertex* vertex );
+ * This function materializes the routing of a net. Global routing algorithms have routed the net so there is only one connex
+ * component. Starting with one vertex of the connex component and using connexID, it's easy to skim through all the connex
+ * component.
+ * \param vertex is a representant of the connex component to materialize
+ */
+
+ /*! \function void Graph::MaterializeRouting ( Vertex* vertex, Edge* arrivalEdge, Contact* initialContact );
+ * This recursive function starts from a \e vertex and skim through all its edges (except the \e arrivalEdge) to check the ConnexID
+ * and materialize routing between 2 vertexes if the ConnexID match.
+ *
+ * \n What does "MaterializeRouting" means:
+ *
+ * The result of the global routing algorithms (Monotonic or Dijkstra) is a connex composant which is respresented by a set of
+ * vertexes and edges that have the same ConnexID.
+ *
+ * Each edge of the connex component represents a crossing of the corresponding fence. Thus for the _working_net a Splitter is
+ * created and attached to the LocalRingHook of each vertex of the edge.
+ *
+ * \n Overview:
+ *
+ * \code
+ * for each edge of vertex:
+ * // if edge and vertex have the same connexID
+ * if Vertex::GetConnexID equals Edge::GetConnexID :
+ * // creates the splitter (if not exist)
+ * edge-> Edge::CreateSplitter ( _working_net );
+ * // get the hook of the splitter corresponding to the vertex
+ * hook = edge-> Edge::GetSplitterHook ( vertex );
+ * // if the vertex has a LocalRingHook set
+ * if previousHook = Vertex::GetLocalRingHook exists:
+ * // attaches the 2 hooks
+ * hook->Attach ( previousHook );
+ * // sets the _localRingHook of the vertex
+ * Vertex::SetLocalRingHook ( hook );
+ *
+ * if edge is not arrivalEdge:
+ * // recursive call
+ * MaterializeRouting ( edge-> Edge::GetOpposite ( vertex ), edge );
+ * \endcode
+ * \param vertex starting vertex
+ * \param arrivalEdge the edge that leaded to the starting vertex
+ * \param initialContact optional
+ * \see \ref grpConnexID
+ */
+
+ /*! \function void Graph::ResetVertexes ();
+ * This function clears the Graph::_vertexes_to_route set.
+ */
+
+ /*! \function void Graph::SetNetStamp ( unsigned netStamp );
+ * \param netStamp is the netStamp corresponding to the Graph::_working_net
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function void Graph::IncNetStamp ();
+ * Increments GRaph::_netStamp by 1.
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function int Graph::CountVertexes ( Net* net );
+ * This function count the number of connex components that have to be routed for the given net.
+ *
+ * It is very similar to the Graph::InitRouting function but is simpler since it just have to count and not initialize the routing
+ * graph.
+ * \param net is the Graph::_working_net
+ * \return the number of connex components
+ */
+
+ /*! \function int Graph::InitRouting ( Net* net );
+ * This function prepares everything needed to properly global route a given net on the routing graph. It creates all the connex
+ * components (with connexID) and fills the _vertexes_to_route set which represents all the connex components that have to be routed.
+ * The set contains only one unique representant vertex for each connex components.
+ * \param net the new Graph::_working_net
+ * \return _vertexes_to_route.size()
+ *
+ * \overview
+ * \code
+ * _working_net = net;
+ * // first sets the new _working_net
+ *
+ * currentConnexID = 0;
+ * // initializes the connexID for the first connex component
+ *
+ * for each component in net->GetComponents()
+ * if the component is a routingPad
+ * vertex = Graph::GetVertex ( component->GetCenter() );
+ *
+ * if vertex not in _vertexes_to_route
+ * _vertexes_to_route.Insert ( vertex );
+ * _searchingArea.Merge ( area of Vertex::_gcell );
+ * Vertex::SetConnexID ( currentConnexID );
+ * Vertex::SetNetStamp ( _netStamp );
+ * currentConnexID++;
+ *
+ * Vertex::AttachToLocalRing ( component );
+ *
+ * for each other_vertex that component would cover
+ * _searchingArea.Merge ( area of Vertex::_gcell );
+ * Vertex::SetConnexID ( currentConnexID - 1 );
+ * Vertex::SetNetStamp ( _netStamp );
+ * Vertex::LinkToVertex ( vertex );
+ * \endcode
+ * \exception assert that the parameter \e net does exist
+ * \bug the for each other vertex that component would cover part is not implemented right now !
+ * \see \ref grpConnexID
+ */
+
+ /*! \function void Graph::Dijkstra ();
+ * This is the implementation of Dijkstra's algorithm.
+ */
+
+ /*! \function void Graph::Monotonic ();
+ * This is the implementation of Monotonic routing.
+ *
+ * \b Definition:
+ *
+ * The Monotonic routing is a very simple algorithm that found the shortest path between a single source and a single target
+ * whithin the bouding box of S and T. The idea is that the path always directs towards T, it implies a very important property
+ * of monotonic routing : each vertex within the bounding box has only one or two vertexes that can be its predecessor.
+ *
+ * Thus it is easy to understand how the distance will be propagated from S to T in order to find the shortest path.
+ *
+ * In order not to treat too many cases, the algorithm orders source and target vertexes so that the source is the leftest vertex
+ * (or most bottom if same x coordinate).
+ *
+ * \overview
+ * \code
+ * // first gets the source and target vertexes
+ * source = (*_vertexes_to_route.begin()); // gets the first element of the set
+ * target = (*_vertexes_to_route.rbegin()); // gets the last (second) element of the set
+ *
+ * // then their x and y coordinates
+ * sourceX, sourceY, targetX and targetY with Vertex::GetPosition
+ *
+ * // the source vertex will be the bottom-leftest one :
+ * if sourceX is greater than targetX:
+ * exchange source with target
+ * else if sourceX equals targetX:
+ * if sourceY is greater than target Y:
+ * exchange source with target
+ *
+ * // now source and target vertex have been ordered, reinitializes x and y coordinates
+ * sourceX, sourceY, targetX and targetY with Vertex::GetPosition
+ *
+ * // sets the source vertex distance to 0
+ * source-> Vertex::SetDistance (0);
+ *
+ * // find the shortest path from source
+ * FindShortestPath();
+ *
+ * // creates the new connex component
+ * while currentVertex has a predecessor:
+ * // set connexID
+ * currentVertex-> Vertex::SetConnexID ( sourceID );
+ * predecessor-> Edge::SetConnexID ( sourceID );
+ * // get next vertex
+ * currentVertex = predecessor-> Edge::GetOpposite ( currentVertex );
+ *
+ * // now materializes the routing
+ * Graph::MaterializeRouting ( source );
+ *
+ * // since the net is now routed, substracts its contribution to estimated congestion
+ * #if defined ( __USE_DYNAMIC_PRECONGESTION__ )
+ * Graph::UpdateEstimateCongestion();
+ * #endif
+ * \endcode
+ *
+ * \n How to find the shortest path:
+ *
+ * There are 2 cases to consider :
+ *
+ * - 1st case:
+ * \image html MonotonicRouting1.png "Monotonic routing first case"
+ * \image latex MonotonicRouting1.pdf "Monotonic routing first case" width=0.7\textwidth
+ *
+ * \code
+ * if sourceY is lesser than or equal to targetY:
+ * // propagates distance for all vertexes which y coordinate is sourceY and x coordinate is lesser than or equal to targetX (1)
+ * // propagates distance for all vertexes which x corrdinate is sourceX and y coordinate is greater than or equal to targetY (2)
+ * // propagates distance for all other vertexes by column order
+ * \endcode
+ *
+ *
+ *
+ *
+ * \image html MonotonicRouting1-1.png "(1)"
+ * \image latex MonotonicRouting1-1.png "(1)" width=0.5\textwidth
+ * |
+ *
+ * \image html MonotonicRouting1-2.png "(2)"
+ * \image latex MonotonicRouting1-2.png "(2)" width=0.5\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * When all the distances of all vertexes have been set, it's easy to find the shortest path following the predecessor from target
+ * to source vertex.
+ *
+ *
+ *
+ *
+ * \image html MonotonicRouting1-3.png "Example of monotonic shortest path"
+ * \image latex MonotonicRouting1-3.png "Example of monotonic shortest path" width=0.5\textwidth
+ * |
+ *
+ * \image html MonotonicRouting1-4.png "Monotonic default shortest path (when all edge costs are equal)"
+ * \image latex MonotonicRouting1-4.png "Monotonic default shortest path (when all edge costs are equal)" width=0.5\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * - 2nd case:
+ * \image html MonotonicRouting2.png "Monotonic routing second case"
+ * \image latex MonotonicRouting2.pdf "Monotonic routing second case" width=0.7\textwidth
+ *
+ * \code
+ * if sourceY is greater than targetY:
+ * // propagates distance for all vertexes which y coordinate is sourceY and x coordinate is lesser than or equal to targetX (1)
+ * // propagates distance for all vertexes which x corrdinate is sourceX and y coordinate is lesser than or equal to targetY (2)
+ * // propagates distance for all other vertexes by column order
+ * \endcode
+ *
+ *
+ *
+ *
+ * \image html MonotonicRouting2-1.png "(1)"
+ * \image latex MonotonicRouting2-1.png "(1)" width=0.5\textwidth
+ * |
+ *
+ * \image html MonotonicRouting2-2.png "(2)"
+ * \image latex MonotonicRouting2-2.png "(2)" width=0.5\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * When all the distances of all vertexes have been set, it's easy to find the shortest path following the predecessor from target
+ * to source vertex.
+ *
+ *
+ *
+ *
+ * \image html MonotonicRouting2-3.png "Example of monotonic shortest path"
+ * \image latex MonotonicRouting2-3.png "Example of monotonic shortest path" width=0.5\textwidth
+ * |
+ *
+ * \image html MonotonicRouting2-4.png "Monotonic default shortest path (when all edge costs are equal)"
+ * \image latex MonotonicRouting2-4.png "Monotonic default shortest path (when all edge costs are equal)" width=0.5\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * \exception assert that Graph::_vertexes_to_route set size is equal to 2
+ * \exception assert that the 2 vertexes present in Graph::_vertexes_to_route set are different
+ * \bug For the moment Monotonic routing works only with a regular routing graph !
+ */
+
+ /*! \function FTree Graph::CreateFluteTree ();
+ * \Return the newly created FLUTE Tree
+ */
+
+ /*! \function void Graph::CleanRoutingState ();
+ * This function cleans everything left by Monotonic, Dijkstra and MaterializeRouting functions
+ */
+
+ /*! \function void Graph::UpdateEstimateCongestion ( bool create = false );
+ * This function manages the estimated congestion. It can either create or update it depending on the value of the \e create parameter.
+ *
+ * \n How to compute estimated congestion:
+ *
+ * The idea is that for each net a rectilinear Steiner minimal tree will be constructed and estimations will be done based on this
+ * Steiner tree. The important point is that when updating estimated congestion, we must be able to reconstruct the same Steiner tree.
+ * Thus the algorithm that creates the Steiner tree have to be determinist, it is also a good point if it is fast because the algorithm
+ * may be called many times.
+ *
+ * Such an algorithm exists in FLUTE
+ * (http://class.ee.iastate.edu/cnchu/flute.hml).
+ *
+ * Based on the Graph::_vertexes_to_route set, the Graph::CreateFluteTree function creates and returns the Steiner tree.
+ *
+ * Let's consider a simple example to illustrates what FLUTE does :
+ * \image html Steiner1.png "A simple example of a net with 4 pins"
+ * \image latex Steiner1.pdf "A simple example of a net with 4 pins" width=0.7\textwidth
+ *
+ * To works, FLUTE needs the x and y coordinates of each pin (vertex), just like :
+ * \code
+ * // FLUTE Input
+ * 100 400
+ * 200 100
+ * 200 400
+ * 300 200
+ * \endcode
+ *
+ * And then FLUTE will return a Steiner tree. The Steiner tree is described based on its branches :
+ * \code
+ * // FLUTE Output
+ * 200 100
+ * 200 200
+ *
+ * 300 200
+ * 200 200
+ *
+ * 100 400
+ * 200 400
+ *
+ * 200 200
+ * 200 400
+ * \endcode
+ * \image html Steiner2.png "Representation of the resulting Steiner tree with intermediate Steiner node"
+ * \image latex Steiner2.pdf "Representation of the resulting Steiner tree with intermediate Steiner node" width=0.7\textwidth
+ *
+ * \n As said before, FLUTE creates a rectilinear Steiner minimal tree, but it is important to understand that when several rectilinear
+ * Steiner minimal sub-trees of the same length exist, FLUTE returns the different possibilities :
+ *
+ *
+ *
+ *
+ * \image html Steiner3.png "A net with 4 pins"
+ * \image latex Steiner3.pdf "A net with 4 pins" width=0.7\textwidth
+ * |
+ *
+ * \code
+ * // FLUTE Input
+ * 100 100
+ * 200 200
+ * 400 200
+ * 500 400
+ * \endcode
+ * |
+ *
+ *
+ *
+ *
+ *
+ * \image html Steiner4.png "All rectilinear Steiner minimal trees"
+ * \image latex Steiner4.pdf "All rectilinear Steiner minimal trees" width=0.7\textwidth
+ * |
+ *
+ * \image html Steiner5.png "Representation of FLUTE result"
+ * \image latex Steiner5.pdf "Representation of FLUTE result" width=0.7\textwidth
+ * |
+ *
+ * \code
+ * // FLUTE Output
+ * 100 100
+ * 200 200
+ *
+ * 500 400
+ * 400 200
+ *
+ * 200 200
+ * 400 200
+ * \endcode
+ * |
+ *
+ *
+ *
+ *
+ * \n Since we exactly know what FLUTE returns, we can now define how estimated congestion is computed. FLUTE returns a set of branches.
+ * Each branch is represented by 2 vertexes and the estimate congestion depends on 2 cases :
+ *
+ * - the 2 vertexes are vertically or horizontally aligned:
+ *
+ *
+ *
+ *
+ * \image html SteinerCongestion1.png "Horizontally aligned"
+ * \image latex SteinerCongestion1.pdf "Horizontally aligned" width=0.7\textwidth
+ * |
+ *
+ * \image html SteinerCongestion2.png "Vertically aligned"
+ * \image latex SteinerCongestion2.pdf "Vertically aligned" width=0.7\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * For all the edges between the 2 vertexes the estimate congestion is incremented by 1.
+ *
+ * - the 2 vertexes are not aligned:
+ *
+ *
+ *
+ *
+ * \image html SteinerCongestion3.png ""
+ * \image latex SteinerCongestion3.pdf "" width=0.7\textwidth
+ * |
+ *
+ * \image html SteinerCongestion4.png ""
+ * \image latex SteinerCongestion4.pdf "" width=0.7\textwidth
+ * |
+ *
+ *
+ *
+ *
+ * There are 2 possible L-pathes, the algorithm consider that each path has a 50% probability, that means that the estimated
+ * congestion of each edge on a path is incremented by 0.5.
+ *
+ * \n Create or Update estimated congestion:
+ *
+ * The \e create parameter determines wether to create or update the estimated congestion, in fact it affects the
+ * Edge::AddSubEstimateOccupancy function. So depending on it, the estimated congestion computed just as bellow is
+ * added or substracted.
+ *
+ * When creating the estimated congestion (during Knik::InitGlobalRouting) \e create is \True while during the global routing step,
+ * in Graph::Monotonic or Graph::Dijkstra, as the Graph::_working_net is routed it does not contribute to the estimated congestion
+ * and thus \e create is \False.
+ *
+ *
+ * \param create specifies whether to create or to update the estimated congestion
+ * \exception return if Graph::_vertexes_to_route size is lesser than 2
+ * \exception return if Graph::_vertexes_to_route size is greater than or equal to \ref GRAPH_FLUTELIMIT
+ */
+
+ // \}
+
+ /*! \anchor GraphTupleQueue Tuple Priority Queue Methods
+ * \name
+ */
+ // \{
+
+ /*! \function Vertex* Graph::ExtractMinFromPriorityQueue();
+ * \Return the vertex in tuple priority queue which has the minimum priority
+ */
+
+ // \}
+
+}
diff --git a/knik/doc/HEdge.dox b/knik/doc/HEdge.dox
new file mode 100644
index 00000000..435e5211
--- /dev/null
+++ b/knik/doc/HEdge.dox
@@ -0,0 +1,76 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class HEdge
+ * \brief A routing graph horizontal edge.\n
+ * - \ref HEdgeConstructors "Constructors"
+ * - \ref HEdgeAccessors "Accessors"
+ * - \ref HEdgeModifiers "Modifiers"
+ * - \ref HEdgePredicates "Predicates"
+ *
+ * The HEdge represents a horizontal edge of the routing graph. The class is derivated from KNIK::Edge and can be instanciated.
+ *
+ * \section secHEdgeImplementation HEdge Implementation
+ * This class exists only because it simplifies a lot the way specific functions are written
+ */
+
+ /*! \anchor HEdgeConstructors Constructors
+ * \name
+ */
+ // \{
+
+ /*! \function static HEdge* HEdge::Create( Fence* fence, Vertex* from, Vertex* to, DisplaySlot* displaySlot );
+ * \param fence is the fence associated to the edge
+ * \param from is the source vertex
+ * \param to is the target vertex
+ * \param displaySlot is the displaySlot used by GTK for graphical display
+ * \return The newly created HEdge
+ * \exception error if \e from or \e to are \NULL
+ * \exception error if the object can not be allocated
+ */
+
+ // \}
+
+ /*! \anchor HEdgeAccessors Accessors
+ * \name
+ */
+ // \{
+
+ /*! \function virtual Hook* HEdge::GetSplitterHook ( Vertex* vertex );
+ * \param vertex the vertex of the edge from which we want to get the splitter's hook
+ * \return The splitter's hook of the specified vertex
+ * \exception assert that Edge::_splitter exists
+ * \exception assert that the given vertex is Edge::_from or Edge::_to
+ */
+ // \}
+
+ /*! \anchor HEdgeModifiers Modifiers
+ * \name
+ */
+ // \{
+
+ /*! \function virtual void HEdge::CreateSplitter ( Net* net );
+ * \param net the current net for which we want to create a splitter on the Edge
+ */
+
+ // \}
+
+ /*! \anchor HEdgePredicates Predicates
+ * \name
+ */
+ // \{
+
+ /*! \function virtual bool HEdge::IsVertical ();
+ * \return Return \False
+ */
+
+ /*! \function virtual bool HEdge::IsHorizontal ();
+ * \return Return \True
+ */
+
+ // \}
+
+}
diff --git a/knik/doc/Knik.dox b/knik/doc/Knik.dox
new file mode 100644
index 00000000..3177d0bc
--- /dev/null
+++ b/knik/doc/Knik.dox
@@ -0,0 +1,130 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class Knik
+ * \brief The Global Router CEngine itself.\n
+ * - \ref KnikTypes "Types"
+ * - \ref KnikAttributes "Attributes"
+ * - \ref KnikConstructors "Constructors"
+ * - \ref KnikModifiers "Modifiers"
+ *
+ * \section secKnikImplementation Knik Implementation
+ * The Global Router CEngine uses a technique based on routing graph and thus relies on another
+ * CEngine : Nimbus.
+ */
+
+ /* \struct Knik::NetRecord
+ *
+ * \brief A NetRecord in Knik
+ *
+ * blablablabla
+ */
+
+ /*! \anchor KnikAttributes Attributes
+ * \name
+ */
+ // \{
+ //
+ /*! \var NIMBUS::Nimbus* Knik::_nimbus
+ * The CEngine Nimbus corresponding to the partitionning
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var Graph* Knik::_routingGraph
+ * The routing graph for Knik
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var CRLCORE::CTimer Knik::_timer
+ * A useful timer to measure execution time
+ */
+
+ /*! \var Knik::NetVector Knik::_nets_to_route
+ * The \STL vector of nets to route by Knik
+ *
+ * \Initial empty
+ */
+ // \}
+
+ /*! \anchor KnikConstructors Constructors
+ * \name
+ */
+ // \{
+ /*! \function static Knik* Knik::Create ( Cell* cell, unsigned congestion, unsigned precongestion, bool benchMode, bool useSegments, float edgeCost );
+ * \param cell is the cell on which the Knik CEngine will work
+ * \param congestion 0: None, 1: Congestion
+ * \param precongestion 0: None, 1: Static, 2: Dynamic
+ * \param benchMode for ispr 2007 global routing benchmarks
+ * \param useSegments defines whether routing is done with segments or splitters
+ * \param edgeCost
+ * \return the newly created Knik CEngine
+ */
+ // \}
+
+ /*! \anchor KnikModifiers Modifiers
+ * \name
+ */
+ // \{
+ /*! \function void Knik::InitGlobalRouting();
+ * This function initializes several thngs that the global routing algorithms will need :
+ * - creates the routing graph
+ * - lists the net that will be routed (filters supply and clock nets and also nets with too many pins)
+ * - creates the estimated congestion (if needed)
+ *
+ * \overview
+ * \code
+ * if no routing graph exists:
+ * // creates the routing graph
+ * Graph::Create ( Knik::_nimbus );
+ *
+ * for each net of cell:
+ * // filters net
+ * if net->IsGlobal() or net->IsSupply() or net->IsClock() :
+ * continue;
+ *
+ * // get netDegree
+ * netDegree = Graph::CountVertexes ();
+ * // still filtering
+ * if netDegree > 1 and netDegree < 1000
+ * Knik::_nets_to_route .push_back ( net );
+ *
+ * #if defined __USE_STATIC_PRECONGESTION__ or __USE_DYNAMIC_PRECONGESTION__
+ * // creates the estimate congestion on the routing graph
+ * Graph::UpdateEstimateCongestion ( true );
+ *
+ * // cleans routing graph
+ * Graph::ResetVertexes ();
+ * \endcode
+ *
+ * \b Note \b 1:
+ * The for each net of cell loop is in fact a loop on net occurrences which allows to get all nets of the hierarchy
+ * of the cell. The first thing done in the loop is then to get the net corresponding to the occurrence.
+ *
+ * \b Note\b 2:
+ * The Knik::_nets_to_route vector does not contains Net but NetRecord which is a structure that associates a Net with a value that
+ * measures it's size. The cost function of the size is :
+ * \code cost = ( netBoundingBoxWidth + 1 ) * ( netBoundingBoxHeight + 1 )
+ * \endcode
+ * This cost function allows to sort nets so flat and small nets will be routed first.
+ * \exception error if the routing graph already exists
+ * \exception asserts that Knik::_nets_to_route is empty when the function is called
+ * \see \ref KNIK_USESTATIC "__USE_STATIC_PRECONGESTION__", \ref KNIK_USEDYNAMIC "__USE_DYNAMIC_PRECONGESTION__"
+ */
+ // \}
+
+ /*! \anchor KnikTypes Types
+ * \name
+ */
+ // \{
+ /* \typedef vector Knik::NetVector;
+ */
+ // \}
+
+
+ }
+
diff --git a/knik/doc/VEdge.dox b/knik/doc/VEdge.dox
new file mode 100644
index 00000000..40733fb7
--- /dev/null
+++ b/knik/doc/VEdge.dox
@@ -0,0 +1,76 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class VEdge
+ * \brief A routing graph vertical edge.\n
+ * - \ref VEdgeConstructors "Constructors"
+ * - \ref VEdgeAccessors "Accessors"
+ * - \ref VEdgeModifiers "Modifiers"
+ * - \ref VEdgePredicates "Predicates"
+ *
+ * The VEdge represents a horizontal edge of the routing graph. The class is derivated from KNIK::Edge and can be instanciated.
+ *
+ * \section secVEdgeImplementation VEdge Implementation
+ * This class exists only because it simplifies a lot the way specific functions are written
+ */
+
+ /*! \anchor VEdgeConstructors Constructors
+ * \name
+ */
+ // \{
+
+ /*! \function static VEdge* VEdge::Create( Fence* fence, Vertex* from, Vertex* to, DisplaySlot* displaySlot );
+ * \param fence is the fence associated to the edge
+ * \param from is the source vertex
+ * \param to is the target vertex
+ * \param displaySlot is the displaySlot used by GTK for graphical display
+ * \return The newly created VEdge
+ * \exception error if \e from or \e to are \NULL
+ * \exception error if the object can not be allocated
+ */
+
+ // \}
+
+ /*! \anchor VEdgeAccessors Accessors
+ * \name
+ */
+ // \{
+
+ /*! \function virtual Hook* VEdge::GetSplitterHook ( Vertex* vertex );
+ * \param vertex the vertex of the edge from which we want to get the splitter's hook
+ * \return The splitter's hook of the specified vertex
+ * \exception assert that Edge::_splitter exists
+ * \exception assert that the given vertex is Edge::_from or Edge::_to
+ */
+ // \}
+
+ /*! \anchor VEdgeModifiers Modifiers
+ * \name
+ */
+ // \{
+
+ /*! \function virtual void VEdge::CreateSplitter ( Net* net );
+ * \param net the current net for which we want to create a splitter on the Edge
+ */
+
+ // \}
+
+ /*! \anchor VEdgePredicates Predicates
+ * \name
+ */
+ // \{
+
+ /*! \function virtual bool VEdge::IsVertical ();
+ * \return Return \True
+ */
+
+ /*! \function virtual bool VEdge::IsHorizontal ();
+ * \return Return \False
+ */
+
+ // \}
+
+}
diff --git a/knik/doc/Vertex.dox b/knik/doc/Vertex.dox
new file mode 100644
index 00000000..527e2f9c
--- /dev/null
+++ b/knik/doc/Vertex.dox
@@ -0,0 +1,242 @@
+
+ // -*- C++ -*-
+
+
+ namespace KNIK {
+
+ /*! \class Vertex
+ * \brief A routing graph vertex.\n
+ * - \ref VertexAttributes "Attributes"
+ * - \ref VertexConstructors "Constructors"
+ * - \ref VertexAccessors "Accessors"
+ * - \ref VertexModifiers "Modifiers"
+ * - \ref VertexPredicates "Predicates"
+ *
+ * The Edge was written to be a light object which simplifies the way the routing graph is covered.
+ * Edges are thus separated into two sub-classes : VEdge and HEdge respectively representing vertical edge and
+ * horizontal edge.
+ *
+ * \section secVertexImplementation Edge Implementation
+ * The Global Router CEngine uses a technique based on routing graph and thus relies on another
+ * CEngine : Nimbus.
+ */
+
+ /*! \anchor VertexAttributes Attributes
+ * \name
+ */
+ // \{
+ /*! \var Graph* Vertex::_routingGraph
+ * The routingGraph to which current vertex belongs
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var GCell* Vertex::_gcell
+ * The gcell associated with current vertex
+ *
+ * \Initial by constructor
+ */
+
+ /*! \var Edge* Vertex::_firstEdges[4]
+ * This array regroups the first edge of each type, it is ordered as follow :
+ * - _firstEdges[0] = first horizontal edge out
+ * - _firstEdges[1] = first vertical edge out
+ * - _firstEdges[2] = first horizontal edge in
+ * - _firstEdges[3] = first vertical edge in
+ *
+ * \Initial empty
+ *
+ * \note Not all the firstEdges need to be defined. For example some vertex may only have 2 edges
+ */
+
+ /*! \var Edge* Vertex::_predecessor
+ * When global routing one needs to know what was the predecessor vertex, instead of the vertex, the vertex hold the edge between
+ * the 2 vertexes
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var Point* Vertex::_position
+ * The position of the vertex
+ *
+ * \Initial _gcell->GetCenter()
+ */
+
+ /*! \var Tuple* Vertex::_tuple
+ * In Dijkstra's algortihm implementation a priority stack is used to ordered vertexes, the stack contains Tuple and each vertex
+ * may have an associated Tuple
+ *
+ * \Initial \NULL
+ */
+
+ /*! \var float Vertex::_distance
+ * In Dijkstra's algorithm implementation each vertex has a distance from source vertex
+ *
+ * \Initial (float)(HUGE)
+ */
+
+ /*! \var int Vertex::_connexID
+ * The identification flag for connex component
+ *
+ * \Initial \p -1
+ * \see \ref grpConnexID
+ */
+
+ /*! \var unsigned Vertex::_netStamp
+ * The net stamp associated with the current net
+ *
+ * \Initial \p 0
+ * \see \ref grpNetStamp
+ */
+
+ /*! \var Unit Vertex::_halfWidth
+ * The half width of the correspoding gcell, it is useful for all graphic parts
+ *
+ * \Initial _gcell->GetHalfWidth()
+ */
+
+ /*! \var Unit Vertex::_halfHeight
+ * The half height of the corresponding gcell, it is useful for all graphic parts
+ *
+ * \Initial _gcell->GetHalfHeight()
+ */
+ // \}
+
+ /*! \anchor VertexConstructors Constructors
+ * \name
+ */
+ // \{
+ /*! \function static Vertex* Vertex::Create ( GCell* gcell, DisplaySlot* displaySlot, Graph* routingGraph );
+ * \param gcell the corresponding gcell in the partitionning
+ * \param displaySlot the GTK displaySlot for vertexes' graphical display
+ * \param routingGraph the routingGraph to which current vertex belongs
+ * \return the newly created vertex
+ * \exception error if the vertex cannot be allocated
+ */
+ // \}
+
+ /*! \anchor VertexAccessors Accessors
+ * \name
+ */
+ // \{
+
+ /*! \function GCell* Vertex::GetGCell();
+ * \Return The corresponding GCell
+ */
+
+ /*! \function Edge* Vertex::GetHEdgeOut() const;
+ * \Return The first horizontal edge out : Vertex::_firstEdges[0]
+ */
+
+ /*! \function Edge* Vertex::GetVEdgeOut() const;
+ * \Return The first vertical edge out : Vertex::_firstEdges[1]
+ */
+
+ /*! \function Edge* Vertex::GetHEdgeIn() const;
+ * \Return The first horizontal edge in : Vertex::_firstEdges[2]
+ */
+
+ /*! \function Edge* Vertex::GetVEdgeIn() const;
+ * \Return The first vertical edge in : Vertex::_firstEdges[3]
+ */
+
+ /*! \function Edges* Vertex::GetAdjacentEdges() const;
+ * \Return The collection of all edges attached to thecurrent vertex
+ */
+
+ /*! \function Edge* Vertex::GetPredecessor() const;
+ * \Return The predecessor edge : Vertex::_predecessor
+ */
+
+ /*! \function int* Vertex::GetConnexID() const;
+ * \Return The ConnexID of the vertex : Vertex::_connexID
+ */
+
+ /*! \function float* Vertex::GetDistance() const;
+ * \Return The distance from the source vertex : Vertex::_distance
+ */
+
+ /*! \function unsigned Vertex::GetNetStamp() const;
+ * \return The netStamp of the vertex : Vertex::_netStamp
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function Point* Vertex::GetPosition() const;
+ * \Return The position of the vertex : Vertex::_position
+ */
+
+ /*! \function Tuple* Vertex::GetTuple() const;
+ * \Return The tuple associated with the vertex : Vertex::_tuple
+ */
+
+ /*! \function Graph* Vertex::GetRoutingGraph() const;
+ * \Return The routing graph
+ */
+ // \}
+
+ /*! \anchor VertexModifiers Modifiers
+ * \name
+ */
+ // \{
+
+ /*! \function void Vertex::SetHEdgeOut ( Edge* edge );
+ * \param edge is the first horizontal edge out
+ */
+
+ /*! \function void Vertex::SetVEdgeOut ( Edge* edge );
+ * \param edge is the first vertical edge out
+ */
+
+ /*! \function void Vertex::SetHEdgeIn ( Edge* edge );
+ * \param edge is the first horizontal edge in
+ */
+
+ /*! \function void Vertex::SetVEdgeIn ( Edge* edge );
+ * \param edge is the first vertical edge in
+ */
+
+ /*! \function void Vertex::SetPredecessor ( Edge* edge );
+ * \param edge is the predecessor of the vertex
+ */
+
+ /*! \function void Vertex::SetConnexID ( int connexID );
+ * \param connexID is the connexID of the vertex
+ * \see \ref grpConnexID
+ */
+
+ /*! \function void Vertex::SetDistance ( float distance );
+ * \param distance is the distance from the source vertex (in Dijkstra's algorithm implementation)
+ */
+
+ /*! \function void Vertex::SetNetStamp ( unsigned netStamp );
+ * \param netStamp is the netStamp of the edge for the current net
+ * \see \ref grpNetStamp
+ */
+
+ /*! \function void Vertex::SetTuple ( Tuple* tuple );
+ * \param tuple the tuple associated with the vertex
+ */
+
+ /*! \function void Vertex::AttachToLocalRing ( Component* component );
+ * \param component the component which has a master hook to add to the local ring
+ * \exception assert if component does not exist
+ */
+
+ // \}
+
+ /*! \anchor VertexPredicates Predicates
+ * \name
+ */
+ // \{
+
+ /*! \function bool Vertex::IsVerticallyAligned ( Vertex* vertex );
+ * \return Return \True if current vertex y coordinate is equal to vertex's one, else \False
+ */
+
+ /*! \function bool Vertex::IsHorizontallyAligned ( Vertex* vertex);
+ * \return Return \True if current vertex x coordinate is equal to vertex's one, else \False
+ */
+
+ // \}
+
+}
diff --git a/knik/doc/asimbook.cls b/knik/doc/asimbook.cls
new file mode 100644
index 00000000..54270780
--- /dev/null
+++ b/knik/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/knik/doc/footer.html b/knik/doc/footer.html
new file mode 100644
index 00000000..7070e631
--- /dev/null
+++ b/knik/doc/footer.html
@@ -0,0 +1,17 @@
+
+
+
+
+