├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── include ├── DataProc.h ├── DataType.h ├── EdgeShift.h ├── RSMT.h ├── a_star.h ├── algo.h ├── bookshelf_IO.h ├── defDataBase.h ├── detpart.h ├── detpart_astar.h ├── detpart_astar_data.h ├── detpart_astar_local.h ├── dist.h ├── dl.h ├── err.h ├── fastroute.h ├── flute.h ├── flute_mst.h ├── fr_global.h ├── global.h ├── global_variable_extern.h ├── grGen.h ├── header.h ├── heap.h ├── lefDataBase.h ├── maxflow.h ├── maze.h ├── maze3D.h ├── maze_finegrain.h ├── maze_finegrain_concurrent.h ├── maze_finegrain_lateupdate.h ├── maze_lock.h ├── memAlloc.h ├── mst2.h ├── neighbors.h ├── ripup.h ├── route.h ├── setup_heap.h ├── soft_cap.h ├── sproute.h ├── sprouteDataType.h ├── utility.h ├── verbose.h └── writeFile.h ├── lib ├── POST9.dat └── POWV9.dat ├── src ├── CMakeLists.txt ├── RSMT.cpp ├── a_star.cpp ├── bookshelf_IO.c ├── defDataBase.cpp ├── detpart_astar_local.cpp ├── dist.c ├── dl.c ├── edgeshift.cpp ├── err.c ├── flute-ckt.c ├── flute-net.c ├── flute.cpp ├── heap.c ├── invalidnets_adj.cpp ├── lefDataBase.cpp ├── maze.cpp ├── mazeMSMD.cpp ├── memAlloc.c ├── mempin_adj.cpp ├── mst2.c ├── neighbors.c ├── rand-pts.c ├── ripup.cpp ├── route.cpp ├── rudy.cpp ├── runGlobalRoute.cpp ├── setup_heap.cpp ├── soft_cap.cpp ├── sproute.cpp ├── sproute_run.cpp └── utility.cpp └── test ├── CMakeLists.txt └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Clion build folders 35 | CMakeFiles/ 36 | cmake-build-debug/ 37 | .idea/ 38 | 39 | # Ignore the build and lib dirs 40 | build/ 41 | 42 | # Ignore any executables 43 | bin/ 44 | 45 | # Ignore Mac specific files 46 | *.DS_Store 47 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(lefdef-SPRoute 4 | LANGUAGES CXX) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") 9 | 10 | ############################################################################ 11 | # Detect the installation path of LEF parser and DEF parser, 12 | # and check if the liblef and libdef library can be found or not 13 | ############################################################################ 14 | message(STATUS "Detecting environment variable LEF_ROOT...") 15 | set(LEF_ROOT "") 16 | if (DEFINED ENV{LEF_ROOT}) 17 | message(STATUS "Environment variable LEF_ROOT detected: " $ENV{LEF_ROOT}) 18 | include_directories($ENV{LEF_ROOT}/include) 19 | link_directories($ENV{LEF_ROOT}/lib) 20 | set(LEF_ROOT $ENV{LEF_ROOT}) 21 | else () 22 | message(STATUS "Environment variable LEF_ROOT not found, using ACT_HOME instead") 23 | include_directories($ENV{ACT_HOME}/include) 24 | link_directories($ENV{ACT_HOME}/lib) 25 | set(LEF_ROOT $ENV{ACT_HOME}) 26 | endif () 27 | find_library( 28 | LEF_LIBRARY 29 | NAMES lef 30 | PATHS ${LEF_ROOT}/lib 31 | REQUIRED 32 | ) 33 | if (NOT LEF_LIBRARY) 34 | message(FATAL_ERROR "Cannot find liblef.a") 35 | else () 36 | message(STATUS "Found liblef.a: " ${LEF_LIBRARY}) 37 | endif () 38 | 39 | message(STATUS "Detecting environment variable DEF_ROOT...") 40 | set(DEF_ROOT "") 41 | if (DEFINED ENV{DEF_ROOT}) 42 | message(STATUS "Environment variable DEF_ROOT detected: " $ENV{DEF_ROOT}) 43 | include_directories($ENV{DEF_ROOT}/include) 44 | link_directories($ENV{DEF_ROOT}/lib) 45 | set(DEF_ROOT $ENV{DEF_ROOT}) 46 | else () 47 | message(STATUS "Environment variable DEF_ROOT not found, using ACT_HOME instead") 48 | include_directories($ENV{ACT_HOME}/include) 49 | link_directories($ENV{ACT_HOME}/lib) 50 | set(DEF_ROOT $ENV{ACT_HOME}) 51 | endif () 52 | find_library( 53 | DEF_LIBRARY 54 | NAMES def 55 | PATHS ${DEF_ROOT}/lib 56 | REQUIRED 57 | ) 58 | if (NOT DEF_LIBRARY) 59 | message(FATAL_ERROR "Cannot find libdef.a") 60 | else () 61 | message(STATUS "Found libdef.a: " ${DEF_LIBRARY}) 62 | endif () 63 | 64 | 65 | 66 | if(GALOIS_ENABLE_VTUNE) 67 | set(VTune_ROOT /opt/intel/vtune_amplifier) 68 | find_package(VTune REQUIRED) 69 | include_directories(${VTune_INCLUDE_DIRS}) 70 | add_definitions(-DGALOIS_ENABLE_VTUNE) 71 | 72 | set(VTune_LIBRARY_PATH_CANDIDATES lib lib64 lib32 bin64/k1om bin32/k1om) 73 | find_path(VTune_INCLUDE_DIRS ittnotify.h PATHS ${VTune_ROOT} PATH_SUFFIXES include) 74 | find_library(VTune_LIBRARY NAMES ittnotify PATHS ${VTune_ROOT} PATH_SUFFIXES ${VTune_LIBRARY_PATH_CANDIDATES}) 75 | find_library(VTune_LIBRARIES NAMES dl PATH_SUFFIXES lib lib64 lib32) 76 | link_directories(/opt/intel/oneapi/vtune/latest/lib64/) 77 | endif() 78 | 79 | 80 | message(STATUS "Detecting environment variable $ENV{ACT_HOME}...") 81 | if (DEFINED ENV{ACT_HOME}) 82 | message(STATUS "Environment variable ACT_HOME detected: " $ENV{ACT_HOME}) 83 | else () 84 | message(FATAL_ERROR "Environment variable $ENV{ACT_HOME} not found") 85 | endif () 86 | include_directories($ENV{ACT_HOME}/include) 87 | link_directories($ENV{ACT_HOME}/lib) 88 | find_library(PHYDB_LIBRARY 89 | NAMES phydb 90 | PATHS $ENV{ACT_HOME}/lib 91 | REQUIRED) 92 | if (NOT PHYDB_LIBRARY) 93 | message(FATAL_ERROR "libphydb.a is not found") 94 | else () 95 | message(STATUS "libphydb.a found") 96 | endif() 97 | 98 | message(STATUS "Detecting Galois libraries...") 99 | set(Galois_FOUND TRUE) 100 | find_library( 101 | GALOIS_EDA_LIBRARY 102 | NAMES galois_eda 103 | PATHS $ENV{ACT_HOME}/lib 104 | ) 105 | if (GALOIS_EDA_LIBRARY) 106 | set(Galois_LIBRARIES ${GALOIS_EDA_LIBRARY}) 107 | message(STATUS "Found libgalois_eda.a: " ${GALOIS_EDA_LIBRARY}) 108 | else() 109 | message(STATUS "Cannot find libgalois_eda.a") 110 | set(Galois_FOUND FALSE) 111 | endif() 112 | find_library( 113 | GALOIS_SHMEM_LIBRARY 114 | NAMES galois_shmem 115 | PATHS $ENV{ACT_HOME}/lib 116 | ) 117 | if (GALOIS_SHMEM_LIBRARY) 118 | set(Galois_LIBRARIES ${Galois_LIBRARIES} ${GALOIS_SHMEM_LIBRARY}) 119 | message(STATUS "Found libgalois_shmem.a: " ${GALOIS_SHMEM_LIBRARY}) 120 | else() 121 | message(STATUS "Cannot find libgalois_shmem.a") 122 | set(Galois_FOUND FALSE) 123 | endif() 124 | 125 | if (UNIX AND (NOT APPLE)) 126 | find_library( 127 | NUMA_LIBRARY 128 | NAMES numa 129 | ) 130 | if (NUMA_LIBRARY) 131 | set(Galois_LIBRARIES ${Galois_LIBRARIES} ${NUMA_LIBRARY}) 132 | message(STATUS "Found libnuma: " ${NUMA_LIBRARY}) 133 | else() 134 | message(STATUS "Cannot find libnuma") 135 | set(Galois_FOUND FALSE) 136 | endif() 137 | endif() 138 | 139 | 140 | find_package(Boost 1.71.0 REQUIRED) 141 | message(STATUS "Boost library path: ${Boost_LIBRARY_DIRS}") 142 | message(STATUS "Boost include path: ${Boost_INCLUDE_DIR}") 143 | message(STATUS "Boost libs: ${Boost_LIBRARIES}") 144 | include_directories(${Boost_INCLUDE_DIRS}) 145 | 146 | # 147 | # This is needed because Boost doesn't auto-detect the C++17 deprecation of 148 | # std::unary_function and std::binary_function 149 | # 150 | add_compile_options("-D_HAS_AUTO_PTR_ETC=0") 151 | 152 | # Set a default build type if none was specified 153 | set(default_build_type "RELEASE") 154 | if (NOT CMAKE_BUILD_TYPE) 155 | message(STATUS "Setting build type to '${default_build_type}' as none was specified.") 156 | set(CMAKE_BUILD_TYPE "${default_build_type}") 157 | # Set the possible values of build type for cmake-gui 158 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 159 | "DEBUG" "RELEASE") 160 | endif () 161 | 162 | #add_compile_options(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic) 163 | #set(CMAKE_CXX_FLAGS_DEBUG "-g -Wno-unused-variable -Wno-unused-but-set-variable -Wno-maybe-uninitialized -Wno-unused-function -Wno-shadow -Wno-unused-parameter") 164 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -Wno-unused-variable -Wno-unused-but-set-variable -Wno-maybe-uninitialized -Wno-unused-function -Wno-shadow -Wno-unused-parameter") 165 | #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -DNDEBUG -Wno-unused-variable -Wno-unused-but-set-variable -Wno-maybe-uninitialized -Wno-unused-function -Wno-shadow -Wno-unused-parameter") 166 | 167 | set(CMAKE_CXX_FLAGS_DEBUG "-g") 168 | set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") 169 | 170 | # Set the output directory of static libraries 171 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib) 172 | 173 | # Set the output directory of executables 174 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) 175 | 176 | include_directories(include) 177 | FILE(GLOB CPP_SOURCES "src/*.cpp") 178 | FILE(GLOB C_SOURCES "src/*.c") 179 | add_subdirectory(test) 180 | 181 | add_library(sproute 182 | STATIC 183 | ${CPP_SOURCES} ${C_SOURCES}) 184 | target_link_libraries(sproute 185 | lef def galois_shmem pthread phydb) 186 | 187 | if(BUILD_BIN) 188 | add_executable(SPRoute 189 | test/main.cpp) 190 | target_link_libraries(SPRoute 191 | lef 192 | def 193 | sproute 194 | pthread 195 | phydb 196 | ${Galois_LIBRARIES} 197 | ) 198 | endif() 199 | 200 | ###################################### 201 | # specify the installation directory: ${ACT_HOME} 202 | ###################################### 203 | 204 | message(STATUS "Detecting environment variable ACT_HOME...") 205 | if (DEFINED ENV{ACT_HOME}) 206 | message(STATUS "Environment variable ACT_HOME detected: " $ENV{ACT_HOME}) 207 | else () 208 | message(FATAL_ERROR "Environment variable ACT_HOME not found") 209 | endif () 210 | message(STATUS "Changing Installation directory to ACT_HOME") 211 | set(CMAKE_INSTALL_PREFIX $ENV{ACT_HOME} CACHE PATH "installation path" FORCE) 212 | message(STATUS "Current installation directory: " ${CMAKE_INSTALL_PREFIX}) 213 | 214 | 215 | ###################################### 216 | # Install header files 217 | ###################################### 218 | install(DIRECTORY include/ DESTINATION include/sproute COMPONENT Development FILES_MATCHING PATTERN "*.h") 219 | 220 | ###################################### 221 | # Install library and FLUTE's files 222 | ###################################### 223 | install(DIRECTORY lib/ 224 | DESTINATION lib) 225 | 226 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | -------------- FLUTE - Version 3.0 ----------------- 2 | by 3 | Chris C.-N. Chu 4 | Dept. of ECpE, Iowa State University 5 | Copyright (c) - 2005 6 | Iowa State University Research Foundation, Inc. 7 | ---------------------------------------------------- 8 | 9 | 10 | BSD 3-Clause License 11 | 12 | Copyright (c) 2018, Iowa State University 13 | All rights reserved. 14 | 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 17 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 18 | 19 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 20 | 21 | * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SPRoute: A Scalable Parallel Global Router 2 | 3 | ### Build tools 4 | * CMake, version >= 3.16 5 | * GNU Compiler Collection (GCC), version >= 4.8.5 6 | 7 | ### Pre-requisite libraries 8 | * Boost, version >= 1.61.0 9 | * Si2 LEF/DEF parser: [LEF parser](https://github.com/The-OpenROAD-Project/lef) and [DEF parser](https://github.com/The-OpenROAD-Project/def). Use `cmake .. -DCMAKE_INSTALL_PREFIX=path/to/install` to specify the installation destination for each parser, and export the path as environment variable `LEF_ROOT` and `DEF_ROOT`. This LEF/DEF parser requires BISON (>= 3.0.4) 10 | * [ACT](https://github.com/asyncvlsi/act): environment variable `ACT_HOME` determines the installation destination of this package 11 | * PhyDB: phydb should be installed in 'ACT_HOME': 'ACT_HOME/include' should contain a 'phydb' folder with all phydb headers, 'ACT_HOME/lib' should contain libphydb.a 12 | * Galois: https://github.com/IntelligentSoftwareSystems/Galois, should be installed in ACT_HOME 13 | * POWV.dat and POST.dat: from FLUTE (http://home.eng.iastate.edu/~cnchu/flute.html), shoule be in the working directory 14 | 15 | ### Required Evironment variable 16 | * 'LEF_ROOT': installation path of the Si2 lef parser 17 | * 'DEF_ROOT': installation path of the Si2 def parser 18 | * 'ACT_HOME': installation path of ACT, where PhyDB and Galois is installed as well 19 | 20 | ### Clone, compile, and install 21 | $ git clone https://github.com/asyncvlsi/SPRoute.git 22 | $ cd SPRoute/ 23 | $ mkdir build 24 | $ cd build 25 | $ cmake .. 26 | $ make 27 | $ make install 28 | If you want an executable of SPRoute, run "cmake .. -DBUILD_BIN=1" in the cmake step. 29 | "make install" creates a folder `sproute` under folder `$ACT_HOME/include` with all .h of PWRoute/include, and a static library `libsproute.a` under folder `$ACT_HOME/lib`. 30 | 31 | ### Performance 32 | This version of SPRoute differs from the ones used for SPRoute 1.0 (ICCAD2019) or 2.0 (ASP-DAC2022). 33 | If you want to compare the runtime and performance of SPRoute 1.0/2.0, please email @Michael Jiayuan He (hejiayuan19920229@gmail.com) for a standalone version of SPRoute. 34 | -------------------------------------------------------------------------------- /include/DataProc.h: -------------------------------------------------------------------------------- 1 | #ifndef _DATAPROC_H_ 2 | #define _DATAPROC_H_ 3 | 4 | namespace sproute { 5 | 6 | #define BUFFERSIZE 800 7 | #define STRINGLEN 200 8 | #define MAXNETDEG 5000 9 | 10 | #define MAXLEN 20000 11 | 12 | #define XRANGE 3000 13 | #define YRANGE 3000 14 | 15 | 16 | } //namespace sproute 17 | 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/DataType.h: -------------------------------------------------------------------------------- 1 | #ifndef _DATATYPE_H_ 2 | #define _DATATYPE_H_ 3 | 4 | #include "galois/Galois.h" 5 | 6 | namespace sproute { 7 | 8 | #define MAXDEMAND 500 // MAX # Segments over an edge 9 | #define MAXLAYER 20 // MAX # Layer of a routing 10 | #define FILESTRLEN 100 // MAX length of file name 11 | #define BIG_INT 1e7 // big integer used as infinity 12 | 13 | typedef char Bool; 14 | 15 | typedef struct { 16 | bool xFirst; // route x-direction first (only for L route) 17 | bool HVH; // TRUE = HVH or FALSE = VHV (only for Z route) 18 | bool maze; // Whether this segment is routed by maze 19 | 20 | short x1, y1, x2, y2; // coordinates of two endpoints 21 | int netID; // the netID of the net this segment belonging to 22 | short Zpoint; // The coordinates of Z point (x for HVH and y for VHV) 23 | short* route; // array of H and V Edges to implement this Segment 24 | int numEdges; // number of H and V Edges to implement this Segment 25 | } Segment; // A Segment is a 2-pin connection 26 | 27 | typedef struct { 28 | std::string name; // net name 29 | int netIDorg; // orginal net ID in the input file 30 | short numPins; // number of pins in the net 31 | short deg; // net degree (number of MazePoints connecting by the net, pins in 32 | // same MazePoints count only 1) 33 | short* pinX; // array of X coordinates of pins 34 | short* pinY; // array of Y coordinates of pins 35 | short* pinL; // array of L coordinates of pins 36 | short minwidth; 37 | bool small; 38 | } Net; // A Net is a set of connected MazePoints 39 | 40 | typedef struct edge_t : public galois::runtime::Lockable { 41 | // galois::substrate::SimpleLock lock; 42 | int congCNT; 43 | int cap; // the capacity of the edge 44 | std::atomic usage; // the usage of the edge 45 | int red; 46 | int last_usage; 47 | float est_usage; // the estimated usage of the edge 48 | 49 | } Edge; // An Edge is the routing track holder between two adjacent MazePoints 50 | 51 | typedef struct { 52 | unsigned short cap; // the capacity of the edge 53 | unsigned short usage; // the usage of the edge 54 | unsigned short red; 55 | 56 | } Edge3D; 57 | 58 | typedef struct { 59 | bool assigned; 60 | 61 | short status; 62 | short conCNT; 63 | short botL, topL; 64 | short heights[6]; 65 | 66 | short x, y; // position in the grid graph 67 | short nbr[3]; // three neighbors 68 | short edge[3]; // three adjacent edges 69 | int hID; 70 | int lID; 71 | int eID[6]; 72 | int stackAlias; 73 | int layer; 74 | } TreeNode; 75 | 76 | #define NOROUTE 0 77 | #define LROUTE 1 78 | #define ZROUTE 2 79 | #define MAZEROUTE 3 80 | 81 | typedef char RouteType; 82 | 83 | typedef struct { 84 | RouteType type; // type of route: LROUTE, ZROUTE, MAZEROUTE 85 | bool 86 | xFirst; // valid for LROUTE, TRUE - the route is horizontal first (x1, y1) 87 | // - (x2, y1) - (x2, y2), FALSE (x1, y1) - (x1, y2) - (x2, y2) 88 | bool 89 | HVH; // valid for ZROUTE, TRUE - the route is HVH shape, FALSE - VHV shape 90 | short Zpoint; // valid for ZROUTE, the position of turn point for Z-shape 91 | short* 92 | gridsX; // valid for MAZEROUTE, a list of grids (n=routelen+1) the route 93 | // passes, (x1, y1) is the first one, but (x2, y2) is the lastone 94 | short* 95 | gridsY; // valid for MAZEROUTE, a list of grids (n=routelen+1) the route 96 | // passes, (x1, y1) is the first one, but (x2, y2) is the lastone 97 | short* gridsL; // n 98 | int routelen; // valid for MAZEROUTE, the number of edges in the route 99 | // Edge3D *edge; // list of 3D edges the route go through; 100 | 101 | } Route; 102 | 103 | typedef struct { 104 | bool assigned; 105 | 106 | int len; // the Manhanttan Distance for two end nodes 107 | int n1, n1a; 108 | int n2, n2a; 109 | Route route; 110 | 111 | int n_ripups; 112 | bool ripup; 113 | double res; 114 | double cap; 115 | } TreeEdge; 116 | 117 | typedef struct { 118 | int deg; 119 | TreeNode* nodes; // the nodes (pin and Steiner nodes) in the tree 120 | TreeEdge* edges; // the tree edges 121 | short x_min, x_max, y_min, y_max; 122 | } StTree; 123 | 124 | typedef struct { 125 | 126 | int treeIndex; 127 | int minX; 128 | float npv; // net length over pin 129 | } OrderNetPin; 130 | 131 | typedef struct { 132 | int length; 133 | int treeIndex; 134 | int xmin; 135 | } OrderTree; 136 | 137 | typedef struct { 138 | short l; 139 | int x, y; 140 | } parent3D; 141 | 142 | typedef struct { 143 | int length; 144 | int edgeID; 145 | } OrderNetEdge; 146 | 147 | typedef enum { NORTH, EAST, SOUTH, WEST, ORIGIN, UP, DOWN } dirctionT; 148 | typedef enum { NONE, HORI, VERT, BID } viaST; 149 | 150 | } //namespace sproute 151 | 152 | #endif /* _DATATYPE_H_ */ 153 | 154 | 155 | -------------------------------------------------------------------------------- /include/EdgeShift.h: -------------------------------------------------------------------------------- 1 | #ifndef _EDGESHIFT_H_ 2 | #define _EDGESHIFT_H_ 3 | 4 | #include 5 | #include 6 | #include "DataType.h" 7 | #include "flute.h" 8 | #include "DataProc.h" 9 | #include "route.h" 10 | #include "ripup.h" 11 | 12 | namespace sproute { 13 | 14 | int edgeShift(Tree* t); 15 | 16 | // exchange Steiner nodes at the same position, then call edgeShift() 17 | int edgeShiftNew(Tree* t); 18 | 19 | } //namespace sproute 20 | #endif 21 | -------------------------------------------------------------------------------- /include/RSMT.h: -------------------------------------------------------------------------------- 1 | #ifndef _RSMT_H 2 | #define _RSMT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "DataType.h" 8 | #include "flute.h" 9 | #include "DataProc.h" 10 | #include "EdgeShift.h" 11 | #include "utility.h" 12 | 13 | namespace sproute { 14 | 15 | #define FLUTEACCURACY 2 16 | 17 | struct pnt { 18 | DTYPE x, y; 19 | int o; 20 | }; 21 | 22 | // global variable 23 | // ** V_table; 24 | // int ** H_table; 25 | 26 | /*static int ordery1(const void *a, const void *b) 27 | { 28 | struct wire *pa, *pb; 29 | 30 | pa = *(struct wire**)a; 31 | pb = *(struct wire**)b; 32 | 33 | if (pa->y1 < pb->y1) return -1; 34 | if (pa->y1 > pb->y1) return 1; 35 | return 0; 36 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 37 | 38 | } 39 | 40 | static int ordery2(const void *a, const void *b) 41 | { 42 | struct wire *pa, *pb; 43 | 44 | pa = *(struct wire**)a; 45 | pb = *(struct wire**)b; 46 | 47 | if (pa->y2 < pb->y2) return -1; 48 | if (pa->y2 > pb->y2) return 1; 49 | return 0; 50 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 51 | 52 | } 53 | 54 | static int orderx1(const void *a, const void *b) 55 | { 56 | struct wire *pa, *pb; 57 | 58 | pa = *(struct wire**)a; 59 | pb = *(struct wire**)b; 60 | 61 | if (pa->x1 < pb->x1) return -1; 62 | if (pa->x1 > pb->x1) return 1; 63 | return 0; 64 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 65 | 66 | } 67 | 68 | static int orderx2(const void *a, const void *b) 69 | { 70 | struct wire *pa, *pb; 71 | 72 | pa = *(struct wire**)a; 73 | pb = *(struct wire**)b; 74 | 75 | if (pa->x2 < pb->x2) return -1; 76 | if (pa->x2 > pb->x2) return 1; 77 | return 0; 78 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 79 | 80 | }*/ 81 | 82 | /*int orderx(const void *a, const void *b) 83 | { 84 | struct pnt *pa, *pb; 85 | 86 | pa = *(struct pnt**)a; 87 | pb = *(struct pnt**)b; 88 | 89 | if (pa->x < pb->x) return -1; 90 | if (pa->x > pb->x) return 1; 91 | return 0; 92 | //return Y(*(struct Segment*)a.x1-*(struct Segment*)b.x1); 93 | } 94 | 95 | 96 | static int ordery(const void *a, const void *b) 97 | { 98 | struct pnt *pa, *pb; 99 | 100 | pa = *(struct pnt**)a; 101 | pb = *(struct pnt**)b; 102 | 103 | if (pa->y < pb->y) return -1; 104 | if (pa->y > pb->y) return 1; 105 | return 0; 106 | }*/ 107 | 108 | // binary search to map the new coordinates to original coordinates 109 | int mapxy(int nx, int xs[], int nxs[], int d); 110 | 111 | void copyStTree(int ind, Tree rsmt); 112 | void fluteNormal(int netID, int d, DTYPE x[], DTYPE y[], int acc, float coeffV, 113 | Tree* t); 114 | void fluteCongest(int netID, int d, DTYPE x[], DTYPE y[], int acc, float coeffV, 115 | Tree* t); 116 | 117 | bool netCongestion(int netID); 118 | 119 | bool VTreeSuite(int netID); 120 | 121 | bool HTreeSuite(int netID); 122 | 123 | float coeffADJ(int netID); 124 | 125 | void gen_brk_RSMT(bool congestionDriven, bool reRoute, bool genTree, 126 | bool newType, bool noADJ); 127 | 128 | } //namespace sproute 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /include/a_star.h: -------------------------------------------------------------------------------- 1 | #ifndef ASTAR_H 2 | #define ASTAR_H 3 | #include 4 | #include "maze.h" 5 | 6 | namespace sproute { 7 | 8 | class astar_pq_grid { 9 | public: 10 | float* d1_p; 11 | float d1_push; 12 | float target_dist_push; 13 | astar_pq_grid() { 14 | d1_p = NULL; 15 | d1_push = 0; 16 | target_dist_push = 0; 17 | }; 18 | astar_pq_grid(float* d1_p, float d1_push, float target_dist_push) { 19 | this->d1_p = d1_p; 20 | this->d1_push = d1_push; 21 | this->target_dist_push = target_dist_push; 22 | } 23 | }; 24 | 25 | struct astar_pq_less { 26 | bool operator()(const astar_pq_grid& left, const astar_pq_grid& right) const { 27 | return left.d1_push + left.target_dist_push < right.d1_push + right.target_dist_push; 28 | } 29 | }; 30 | 31 | typedef galois::PerThreadMinHeap astar_PerThread_PQ; 32 | typedef galois::gstl::PQ astar_local_pq; 33 | 34 | // ripup a tree edge according to its ripup type and Z-route it 35 | // put all the nodes in the subtree t1 and t2 into heap1 and heap2 36 | // netID - the ID for the net 37 | // edgeID - the ID for the tree edge to route 38 | // d1 - the distance of any grid from the source subtree t1 39 | // pq1 - the priority queue stored the node, cost from src, distance to dst 40 | // v2 - the vector stored the destination nodes 41 | void setupHeap_astar(int netID, int edgeID, astar_local_pq& pq1, local_vec& v2, 42 | int regionX1, int regionX2, int regionY1, int regionY2, 43 | float** d1, int** corrEdge, bool** inRegion, float astar_weight); 44 | 45 | 46 | 47 | } //namespace sproute 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/algo.h: -------------------------------------------------------------------------------- 1 | #ifndef ALGO_H 2 | #define ALGO_H 3 | #include 4 | #include 5 | 6 | namespace sproute { 7 | 8 | enum Algo { 9 | FineGrain = 0, 10 | NonDet, 11 | Det, 12 | RUDY, 13 | PIN_DENSITY, 14 | DRC_MAP 15 | }; 16 | 17 | static Algo StrToAlgo(string algo_str) { 18 | if(algo_str == "FineGrain") 19 | return FineGrain; 20 | else if(algo_str == "NonDet") 21 | return NonDet; 22 | else if(algo_str == "Det") 23 | return Det; 24 | else if(algo_str == "RUDY") 25 | return RUDY; 26 | else if(algo_str == "PIN_DENSITY") 27 | return PIN_DENSITY; 28 | else if(algo_str == "DRC_MAP") 29 | return DRC_MAP; 30 | else { 31 | std::cout << "unknown algorithm: " << algo_str << std::endl; 32 | exit(1); 33 | } 34 | 35 | } 36 | 37 | } //namespace sproute 38 | 39 | #endif -------------------------------------------------------------------------------- /include/bookshelf_IO.h: -------------------------------------------------------------------------------- 1 | /* ----------- FastPlace - Version 1.0 ---------------- 2 | by 3 | Natarajan Viswanathan and Chris C.-N. Chu 4 | Dept. of ECpE, Iowa State University 5 | Copyright (c) - 2004 6 | Iowa State University Research Foundation, Inc. 7 | -------------------------------------------------------- */ 8 | /* -------------------------------------------------------------------------- 9 | Header file used in bookshelf_IO.c 10 | ----------------------------------------------------------------------------*/ 11 | 12 | #ifndef _BOOKSHELF_IO_H_ 13 | #define _BOOKSHELF_IO_H_ 14 | 15 | #define BUFFERSIZE 200 16 | #define STRINGLEN 30 17 | 18 | /* ----------------------------------------------------------------------------- 19 | Reads the .nodes file and creates a hash linking cell name to cell index for 20 | all the nodes in the circuit (movable nodes + fixed nodes + I/O pads) 21 | 22 | creates extern vars: 23 | cellName[i] (i = 1..movableNodes + numTerminals) 24 | -------------------------------------------------------------------------------- 25 | */ 26 | extern void createHash(char benchmarkPath[], char nodesFile[]); 27 | extern void freeHash(); 28 | 29 | /* ----------------------------------------------------------------------------- 30 | Reads the .aux file to get the other file names 31 | 32 | creates extern vars: 33 | nodesFile[], netsFile[], wtsFile[], sclFile[], plFile[], benchmarkName[] 34 | -------------------------------------------------------------------------------- 35 | */ 36 | extern void readAuxFile(char benchmarkPath[], char auxFile[]); 37 | 38 | /* ----------------------------------------------------------------------------- 39 | Reads the .nodes file to get cell widths and heights 40 | 41 | creates extern vars: 42 | movableNodes, numTerminals, averageCellWidth, cellWidth[], cellHeight[] 43 | -------------------------------------------------------------------------------- 44 | */ 45 | extern void readNodesFile(char benchmarkPath[], char nodesFile[]); 46 | 47 | /* ----------------------------------------------------------------------------- 48 | Reads the .nets file to get the netlist information 49 | 50 | creates extern vars: 51 | numNets, numPins, netlist[], netlistIndex[], xPinOffset[], yPinOffset[] 52 | -------------------------------------------------------------------------------- 53 | */ 54 | extern void readNetsFile(char benchmarkPath[], char netsFile[]); 55 | 56 | /* ----------------------------------------------------------------------------- 57 | Reads the .pl file to get coordinates of all the nodes and the placement 58 | boundary based on the position of the I/O pads 59 | 60 | creates extern vars: 61 | xCellCoord[], yCellCoord[], minX, maxX, minY, maxY 62 | -------------------------------------------------------------------------------- 63 | */ 64 | extern void readPlFile(char benchmarkPath[], char plFile[]); 65 | 66 | /* ----------------------------------------------------------------------------- 67 | Reads the .scl file to get placement (core) region information 68 | 69 | creates extern vars: 70 | siteOriginX, siteEndX, siteOriginY, siteEndY, siteWidth, siteSpacing, 71 | numRows, coreRowHeight, coreWidth, coreHeight 72 | -------------------------------------------------------------------------------- 73 | */ 74 | extern void readSclFile(char benchmarkPath[], char sclFile[]); 75 | 76 | /* ----------------------------------------------------------------------------- 77 | writes out a bookshelf format .pl file 78 | -------------------------------------------------------------------------------- 79 | */ 80 | extern void writePlFile(char outputDir[], char benchmarkName[], float xCoord[], 81 | float yCoord[]); 82 | 83 | /*-------------- Extern Variables ------------------*/ 84 | 85 | extern char** cellName; 86 | 87 | extern char nodesFile[BUFFERSIZE], netsFile[BUFFERSIZE], wtsFile[BUFFERSIZE]; 88 | extern char sclFile[BUFFERSIZE], plFile[BUFFERSIZE], benchmarkName[BUFFERSIZE]; 89 | 90 | extern int movableNodes, numTerminals; 91 | extern float averageCellWidth, *cellWidth, *cellHeight; 92 | 93 | extern int numNets, numPins, *netlist, *netlistIndex; 94 | extern float *xPinOffset, *yPinOffset; 95 | 96 | extern float *xCellCoord, *yCellCoord, minX, maxX, minY, maxY; 97 | extern int *areaArrayIO, numAreaArrayIO; 98 | 99 | extern int numRows, numRowBlockages; 100 | extern float siteOriginY, siteEndY, coreHeight; 101 | extern float siteOriginX, siteEndX, coreWidth; 102 | extern float siteWidth, siteSpacing, coreRowHeight; 103 | extern float *rowOriginX, *rowEndX; 104 | extern float *xRowBlockage, *yRowBlockage, *widthRowBlockage; 105 | 106 | #endif /* _BOOKSHELF_IO_H_*/ 107 | 108 | /* ----------------------------------------------------------------------------------------------- 109 | Description of Extern Variables 110 | 111 | cellName[i] = cell name corresponding to cell index "i" 112 | (i = 1..movableNodes+numTerminals) 113 | 114 | movableNodes = number of movable nodes, 115 | numTerminals = number of fixed nodes (I/O Pads + Fixed Macros) 116 | averageCellWidth = avg width of movable nodes, 117 | cellWidth[i] = width of cell "i" (i 118 | = 1..movableNodes+numTerminals) cellHeight[i] = height of cell "i" (i 119 | = 1..movableNodes+numTerminals) 120 | 121 | numNets = number of nets 122 | numPins = number of pins 123 | netlist[] = netlist of the circuit 124 | xPinOffset[] = x-offset of the pins from the center of the cell 125 | yPinOffset[] = y-offset ( " ) 126 | netlistIndex[] = index to the netlist and offset vectors 127 | 128 | xCellCoord[i] = x-coordinate of cell "i" (i 129 | = 1..movableNodes+numTerminals) yCellCoord[i] = y-coordinate of cell 130 | "i", minX, maxX = left and right boundaries of the chip (Note: not 131 | the placement region) minY, maxY = bottom and top boundaries of the 132 | chip areaArrayIO[] = All fixed terminals with which there can be an 133 | overlap of movable nodes (eg area array IOs) numAreaArrayIO = the total 134 | number of area array IOs 135 | 136 | siteOriginX[] = left boundary of the placement region within a row 137 | siteEndX[] = right boundary of the placement region within a row 138 | siteOriginY = bottom boundary of the placement region 139 | siteEndY = top boundary of the placement region 140 | siteWidth = width of a placement site within a row 141 | siteSpacing = the space b/w adjacent placement sites within a row 142 | numRows = number of placement rows 143 | coreRowHeight = row Height 144 | coreWidth = siteEndX - siteOriginX 145 | coreHeight = siteEndY - siteOriginY 146 | 147 | ---------------------------------------------------------------------------------------------------*/ 148 | -------------------------------------------------------------------------------- /include/defDataBase.h: -------------------------------------------------------------------------------- 1 | #ifndef DEFDATABASE_H 2 | #define DEFDATABASE_H 3 | 4 | #include "header.h" 5 | #include "lefDataBase.h" 6 | #include "writeFile.h" 7 | 8 | namespace sproute_db 9 | { 10 | 11 | class defVia 12 | { 13 | public: 14 | string name; 15 | int idx; 16 | string viaRuleName; 17 | Size2D cutSize; 18 | string layers[3]; 19 | Size2D cutSpacing; 20 | Size2D botEnc; 21 | Size2D topEnc; 22 | int numCutRows; 23 | int numCutCols; 24 | Size2D origin; 25 | Size2D botOffset; 26 | Size2D topOffset; 27 | 28 | vector> rect2DLayers; 29 | string pattern; 30 | 31 | defVia( ) { } 32 | 33 | void clear() 34 | { 35 | name = ""; 36 | viaRuleName = ""; 37 | cutSize.clear(); 38 | layers[0] = ""; 39 | layers[1] = ""; 40 | layers[2] = ""; 41 | cutSpacing.clear(); 42 | botEnc.clear(); 43 | topEnc.clear(); 44 | numCutRows = 0; 45 | numCutCols = 0; 46 | origin.clear(); 47 | botOffset.clear(); 48 | topOffset.clear(); 49 | } 50 | void print() 51 | { 52 | cout << "Via: " << name << " VIARule: " << viaRuleName << endl; 53 | cout << "CUT: " << cutSize.x << " " << cutSize.y << endl; 54 | cout << "Layer: " << layers[0] << " " << layers[1] << " " << layers[2] << endl; 55 | cout << "CUTSPACING: " << cutSpacing.x << " " << cutSpacing.y << endl; 56 | cout << "botEnc: " << botEnc.x << " " << botEnc.y << endl; 57 | cout << "topEnc: " << topEnc.x << " " << topEnc.y << endl; 58 | cout << " row: " << numCutRows << " col: " << numCutCols << endl; 59 | cout << " origin: " << origin.x << " " << origin.y << endl; 60 | cout << " botOffset: " << botOffset.x << " " << botOffset.y << endl; 61 | cout << " topOffset: " << topOffset.x << " " << topOffset.y << endl; 62 | } 63 | }; 64 | 65 | 66 | class Row 67 | { 68 | public: 69 | string name; 70 | string siteName; 71 | int origX; 72 | int origY; 73 | string siteOrient; 74 | int numX; 75 | int numY; 76 | int stepX; 77 | int stepY; 78 | }; 79 | 80 | class Track 81 | { 82 | public: 83 | string direction; 84 | int start; 85 | int numTracks; 86 | int step; 87 | std::vector layerNames; 88 | 89 | Track() 90 | { 91 | direction = ""; 92 | start = 0; 93 | numTracks = 0; 94 | step = 0; 95 | } 96 | void reset() 97 | { 98 | direction = ""; 99 | start = 0; 100 | numTracks = 0; 101 | step = 0; 102 | layerNames.clear(); 103 | } 104 | void print() 105 | { 106 | cout << "TRACKS : " << direction << " start " << start << " DO " << numTracks << " step " << step << " "; 107 | for(auto layer : layerNames) 108 | cout << " " << layer; 109 | cout << endl; 110 | } 111 | }; 112 | 113 | class Component 114 | { 115 | public: 116 | int idx; 117 | string name; 118 | string macroName; 119 | string source; 120 | string locationType; 121 | Point2D location; 122 | string orient; 123 | 124 | int weight; 125 | 126 | Macro macro; 127 | Component() {} 128 | void clear() 129 | { 130 | idx = -1; 131 | name = ""; 132 | macroName = ""; 133 | source = ""; 134 | locationType = ""; 135 | location.x = 0; 136 | location.y = 0; 137 | orient = ""; 138 | } 139 | void print() { 140 | cout << "Comp name:" << name << " Macro name:" << macroName < componentNames; 157 | std::vector pinNames; 158 | 159 | Net() 160 | { 161 | name = ""; 162 | source = ""; 163 | use = ""; 164 | } 165 | void clear() 166 | { 167 | name = ""; 168 | source = ""; 169 | use = ""; 170 | componentNames.clear(); 171 | pinNames.clear(); 172 | } 173 | void reset() 174 | { 175 | name = ""; 176 | source = ""; 177 | use = ""; 178 | componentNames.clear(); 179 | pinNames.clear(); 180 | } 181 | void print() 182 | { 183 | cout << "NET: " << name << endl; 184 | for(int i = 0; i < componentNames.size(); i++) 185 | cout << " ( " << componentNames.at(i) << " " << pinNames.at(i) << " ) " ; 186 | cout << endl; 187 | } 188 | 189 | }; 190 | 191 | class Path 192 | { 193 | public: 194 | string layerName; 195 | int width; 196 | string shape; 197 | string viaName; 198 | 199 | int beginExt; 200 | int endExt; 201 | Rect2D rect; 202 | Point2D begin; 203 | Point2D end; 204 | Path() { 205 | layerName = ""; 206 | width = 0; 207 | shape = ""; 208 | viaName = ""; 209 | beginExt = 0; 210 | endExt = 0; 211 | } 212 | void print() 213 | { 214 | cout << " NEW " << layerName << " " << width << " + SHAPE " << shape; 215 | if(!rect.empty()) 216 | cout << " (" << rect.lowerLeft.x << " " << rect.lowerLeft.y << " " << rect.upperRight.x << " " << rect.upperRight.y << ")"; 217 | if(!begin.empty()) 218 | cout << " (" << begin.x << " " << begin.y << " ) "; 219 | if(!end.empty()) 220 | cout << " (" << end.x << " " << end.y << " ) "; 221 | if(beginExt != 0 || endExt != 0) 222 | cout << " EXT " << beginExt << " " << endExt; 223 | if(viaName != "") 224 | cout << viaName; 225 | cout << endl; 226 | } 227 | 228 | 229 | }; 230 | 231 | class SNet 232 | { 233 | public: 234 | string name; 235 | 236 | std::vector paths; 237 | void clear() 238 | { 239 | name = ""; 240 | paths.clear(); 241 | } 242 | void print() 243 | { 244 | cout << "SNET: " << name << endl; 245 | for(auto p : paths) 246 | p.print(); 247 | } 248 | }; 249 | 250 | class GcellGrid 251 | { 252 | public: 253 | string direction; 254 | int start; 255 | int numBoundaries; 256 | int step; 257 | 258 | GcellGrid() 259 | { 260 | direction = ""; 261 | start = 0; 262 | numBoundaries = 0; 263 | step = 0; 264 | } 265 | void reset() 266 | { 267 | direction = ""; 268 | start = 0; 269 | numBoundaries = 0; 270 | step = 0; 271 | } 272 | void print() 273 | { 274 | cout << " " << direction << " " << start << " DO " << numBoundaries << " STEP " << step << endl; 275 | } 276 | 277 | }; 278 | 279 | enum GcellState{ 280 | NO_OBS = 0, 281 | HAS_OBS, 282 | FULLYCOVERED 283 | }; 284 | 285 | class Gcell 286 | { 287 | public: 288 | bool trackUsed[15]; 289 | int numPoints; 290 | int numNodeOffset; 291 | int numTracks; 292 | GcellState obs_state; 293 | std::vector OBSIDlist; // for verification, can be removed 294 | 295 | Gcell() 296 | { 297 | obs_state = NO_OBS; 298 | numPoints = 0; 299 | numTracks = 0; 300 | OBSIDlist.reserve(16); 301 | } 302 | 303 | }; 304 | 305 | class IOPin 306 | { 307 | public: 308 | int idx; 309 | string name; 310 | string netName; 311 | string direction; 312 | string use; 313 | 314 | string layerName; 315 | Rect2D rect; 316 | 317 | Point2D location; 318 | string orient; 319 | 320 | void clear() 321 | { 322 | idx = -1; 323 | name = ""; 324 | netName = ""; 325 | direction = ""; 326 | use = ""; 327 | layerName = ""; 328 | rect.set(0,0,0,0); 329 | location.set(0,0); 330 | orient = ""; 331 | } 332 | void print() 333 | { 334 | cout << "PIN: " << name << " net: " << netName << " direction: " << direction << endl; 335 | cout << " layer: " << layerName << " orient: " << orient << endl; 336 | cout << " RECT: "; 337 | rect.print(); 338 | cout << " LOCATION: " ; 339 | location.print(); 340 | 341 | } 342 | }; 343 | 344 | class CapReduction 345 | { 346 | public: 347 | int x; 348 | int y; 349 | int z; 350 | int newCap; 351 | CapReduction( ) 352 | { 353 | x = 0; 354 | y = 0; 355 | z = 0; 356 | newCap = 0; 357 | } 358 | }; 359 | 360 | 361 | class defDataBase 362 | { 363 | public: 364 | string version; 365 | string dividerChar; 366 | string busBitChars; 367 | string designName; 368 | 369 | Rect2D dieArea; 370 | 371 | Point3D gcellGridDim; 372 | Point2D commonGcell; 373 | 374 | int dbuPerMicro; 375 | int numComponents; 376 | int numIOPins; 377 | int numSpecialNets; 378 | int numNets; 379 | int numVias; 380 | 381 | std::vector rows; 382 | std::vector tracks; 383 | std::vector components; 384 | std::vector iopins; 385 | std::vector snets; 386 | std::vector vias; 387 | std::vector nets; 388 | std::vector gcellGrids; 389 | std::vector gcells; 390 | 391 | std::map component2idx; 392 | std::map iopin2idx; 393 | std::map defVia2idx; 394 | std::map layerName2trackidx; 395 | std::map netName2netidx; 396 | std::map layeridx2trackidx; 397 | 398 | std::vector xGcellBoundaries; 399 | std::vector yGcellBoundaries; 400 | 401 | std::vector>> origOBS; 402 | std::vector>> designRuleOBS; 403 | 404 | Gcell& getGcell(int x, int y, int z); 405 | 406 | }; 407 | 408 | enum defKeyword { 409 | VERSION = 0, 410 | DIVIDERCHAR, 411 | BUSBITCHARS, 412 | DESIGN, 413 | UNITS, 414 | DIEAREA, 415 | ROW, 416 | TRACKS, 417 | COMPONENTS, 418 | PINS, 419 | SPECIALNETS, 420 | NETS, 421 | VIAS, 422 | GCELLGRID, 423 | END 424 | }; 425 | 426 | int find_Gcell(int pin_in, std::vector GcellBoundaries); 427 | 428 | 429 | } //namespace sproute_db 430 | 431 | #endif 432 | -------------------------------------------------------------------------------- /include/detpart_astar_local.h: -------------------------------------------------------------------------------- 1 | #ifndef DETPART_ASTAR_LOCAL_H 2 | #define DETPART_ASTAR_LOCAL_H 3 | 4 | #include "ripup.h" 5 | 6 | namespace sproute { 7 | 8 | class Usage_Update { 9 | public: 10 | int grid; 11 | bool is_H; 12 | int delta; 13 | Usage_Update(int g, bool h, int d) { 14 | grid = g; 15 | is_H = h; 16 | delta = d; 17 | } 18 | }; 19 | 20 | bool newRipupCheck_atomic_local(TreeEdge* treeedge, int ripup_threshold, int netID, 21 | int edgeID, int* h_local_usage, int* v_local_usage); 22 | 23 | } //namespace sproute 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/dist.h: -------------------------------------------------------------------------------- 1 | #ifndef _DIST_H_ 2 | #define _DIST_H_ 3 | 4 | #include "fr_global.h" 5 | 6 | long dist(Point p, Point q); 7 | 8 | long dist2(Point* p, Point* q); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/dl.h: -------------------------------------------------------------------------------- 1 | #ifndef DL_H 2 | #define DL_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct dl_el_s { 8 | struct dl_el_s *prev, *next; 9 | } dl_el; 10 | 11 | typedef struct { 12 | dl_el *first, *last; 13 | unsigned int count; 14 | } dl_s, *dl_t; 15 | 16 | dl_t dl_alloc(void); 17 | void dl_delete(dl_t dl, dl_el* el); 18 | void dl_clear(dl_t dl); 19 | void dl_concat(dl_t list1, dl_t list2); 20 | void dl_sort(dl_t dl, size_t el_size, int (*compar)(void*, void*)); 21 | 22 | #define dl_length(dl) (dl)->count 23 | 24 | #define dl_empty(dl) ((dl)->count <= 0) 25 | 26 | #define dl_data(type, el) *(type*)(((dl_el*)(el)) + 1) 27 | 28 | #define dl_data_p(type, el) ((type*)(((dl_el*)(el)) + 1)) 29 | 30 | #define dl_forall(type, dl, data) \ 31 | { \ 32 | dl_el *_el, *_next; \ 33 | dl_t _curr_dl = (dl); \ 34 | for (_el = _curr_dl->first; _el; _el = _next) { \ 35 | _next = _el->next; \ 36 | (data) = dl_data(type, _el); 37 | 38 | #define dl_forall_p(type, dl, data_p) \ 39 | { \ 40 | dl_el *_el, *_next; \ 41 | dl_t _curr_dl = (dl); \ 42 | for (_el = _curr_dl->first; _el; _el = _next) { \ 43 | _next = _el->next; \ 44 | (data_p) = dl_data_p(type, _el); 45 | 46 | #define dl_current() _el 47 | #define dl_delete_current() dl_delete(_curr_dl, _el) 48 | 49 | #define dl_endfor \ 50 | } \ 51 | } 52 | 53 | #define dl_forall_reverse(type, dl, data) \ 54 | { \ 55 | dl_el *_el, *_next; \ 56 | dl_t _curr_dl = (dl); \ 57 | for (_el = _curr_dl->last; _el; _el = _next) { \ 58 | _next = _el->prev; \ 59 | (data) = dl_data(type, _el); 60 | 61 | #define dl_forall_reverse_p(type, dl, data_p) \ 62 | { \ 63 | dl_el *_el, *_next; \ 64 | dl_t _curr_dl = (dl); \ 65 | for (_el = _curr_dl->last; _el; _el = _next) { \ 66 | _next = _el->prev; \ 67 | (data_p) = dl_data_p(type, _el); 68 | 69 | #define dl_first(type, dl) dl_data(type, (dl)->first) 70 | 71 | #define dl_first_element(dl) (dl)->first 72 | 73 | #define dl_last(type, dl) dl_data(type, (dl)->last) 74 | 75 | #define dl_pop_first(type, dl, data) \ 76 | { \ 77 | (data) = dl_first(type, dl); \ 78 | dl_delete((dl), (dl)->first); \ 79 | } 80 | 81 | #define dl_pop_last(type, dl, data) \ 82 | { \ 83 | (data) = dl_last(type, dl); \ 84 | dl_delete((dl), (dl)->last); \ 85 | } 86 | 87 | #define dl_insert_before(type, dl, element, data) \ 88 | { \ 89 | if ((element) == (dl)->first) { \ 90 | dl_prepend(type, dl, data); \ 91 | } else { \ 92 | dl_el* _el = (dl_el*)malloc(sizeof(dl_el) + sizeof(type)); \ 93 | if (!_el) { \ 94 | printf("Out of memory!!\n"); \ 95 | } else { \ 96 | memcpy(_el + 1, &(data), sizeof(type)); \ 97 | _el->prev = (element)->prev; \ 98 | _el->next = (element); \ 99 | (element)->prev->next = _el; \ 100 | (element)->prev = _el; \ 101 | (dl)->count++; \ 102 | } \ 103 | } \ 104 | } 105 | 106 | #define dl_insert_after(type, dl, element, data) \ 107 | { \ 108 | if ((element) == (dl)->last) { \ 109 | dl_append(type, dl, data); \ 110 | } else { \ 111 | dl_el* _el = (dl_el*)malloc(sizeof(dl_el) + sizeof(type)); \ 112 | if (!_el) { \ 113 | printf("Out of memory!!\n"); \ 114 | } else { \ 115 | memcpy(_el + 1, &(data), sizeof(type)); \ 116 | _el->next = (element)->next; \ 117 | _el->prev = (element); \ 118 | (element)->next->prev = _el; \ 119 | (element)->next = _el; \ 120 | (dl)->count++; \ 121 | } \ 122 | } \ 123 | } 124 | 125 | #define dl_append(type, dl, data) \ 126 | { \ 127 | dl_el* _el = (dl_el*)malloc(sizeof(dl_el) + sizeof(type)); \ 128 | if (!_el) { \ 129 | printf("Out of memory!!\n"); \ 130 | } else { \ 131 | memcpy(_el + 1, &(data), sizeof(type)); \ 132 | _el->next = 0; \ 133 | if ((dl)->count <= 0) { \ 134 | _el->prev = 0; \ 135 | (dl)->first = (dl)->last = _el; \ 136 | (dl)->count = 1; \ 137 | } else { \ 138 | _el->prev = (dl)->last; \ 139 | (dl)->last->next = _el; \ 140 | (dl)->last = _el; \ 141 | (dl)->count++; \ 142 | } \ 143 | } \ 144 | } 145 | 146 | #define dl_prepend(type, dl, data) \ 147 | { \ 148 | dl_el* _el = (dl_el*)malloc(sizeof(dl_el) + sizeof(type)); \ 149 | if (!_el) { \ 150 | printf("Out of memory!!\n"); \ 151 | } else { \ 152 | memcpy(_el + 1, &(data), sizeof(type)); \ 153 | _el->prev = 0; \ 154 | if ((dl)->count <= 0) { \ 155 | _el->next = 0; \ 156 | (dl)->first = (dl)->last = _el; \ 157 | (dl)->count = 1; \ 158 | } else { \ 159 | _el->next = (dl)->first; \ 160 | (dl)->first->prev = _el; \ 161 | (dl)->first = _el; \ 162 | (dl)->count++; \ 163 | } \ 164 | } \ 165 | } 166 | 167 | #define dl_free(dl) \ 168 | { \ 169 | dl_clear(dl); \ 170 | free(dl); \ 171 | dl = 0; \ 172 | } 173 | 174 | #define dl_duplicate(dest, src, type) \ 175 | { \ 176 | dest = dl_alloc(); \ 177 | type _data_el; \ 178 | dl_forall(type, src, _data_el) { dl_append(type, dest, _data_el); } \ 179 | dl_endfor; \ 180 | } 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /include/err.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERR_H_ 2 | #define _ERR_H_ 3 | 4 | void err_msg(char* msg); 5 | 6 | void err_exit(char* msg); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/fastroute.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTROUTE_H 2 | #define FASTROUTE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "galois/Galois.h" 11 | #include "galois/Reduction.h" 12 | #include "galois/PriorityQueue.h" 13 | #include "galois/Timer.h" 14 | #include "galois/graphs/Graph.h" 15 | #include "galois/graphs/TypeTraits.h" 16 | #include "galois/substrate/SimpleLock.h" 17 | #include "galois/AtomicHelpers.h" 18 | #include "galois/runtime/Profile.h" 19 | 20 | #include "galois/LargeArray.h" 21 | 22 | //#include "Lonestar/BFS_SSSP.h" 23 | 24 | #include "DataType.h" 25 | #include "flute.h" 26 | #include "DataProc.h" 27 | #include "RSMT.h" 28 | #include "maze.h" 29 | #include "RipUp.h" 30 | #include "utility.h" 31 | #include "route.h" 32 | //#include "maze3D.h" 33 | #include "maze_finegrain.h" 34 | #include "maze_finegrain_lateupdate.h" 35 | #include "maze_lock.h" 36 | 37 | #include "algo.h" 38 | #include "grGen.h" 39 | #include "detpart.h" 40 | #include "a_star.h" 41 | #include "detpart_astar.h" 42 | #include "detpart_astar_data.h" 43 | #include "detpart_astar_local.h" 44 | 45 | 46 | 47 | void printUndone(galois::LargeArray& done) { 48 | cout << "undone nets: " << endl; 49 | for(int netID=0; netIDname << endl; 52 | } 53 | } 54 | 55 | 56 | 57 | 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/flute.h: -------------------------------------------------------------------------------- 1 | #ifndef _FLUTE_H_ 2 | #define _FLUTE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace sproute { 12 | //#include "flute_mst.h" 13 | 14 | /*****************************/ 15 | /* User-Defined Parameters */ 16 | /*****************************/ 17 | #define MAXD 5000 // max. degree that can be handled 18 | #define ACCURACY 10 // Default accuracy 19 | #define LOCAL_REFINEMENT 1 // Suggestion: Set to 1 if ACCURACY >= 5 20 | #define REMOVE_DUPLICATE_PIN 1 // Remove dup. pin for flute_wl() & flute() 21 | 22 | #ifndef DTYPE // Data type for distance 23 | #define DTYPE int 24 | #endif 25 | 26 | /*****************************/ 27 | /* User-Callable Functions */ 28 | /*****************************/ 29 | // void readLUT(); 30 | // DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc); 31 | // DTYPE flutes_wl(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 32 | // Tree flute(int d, DTYPE x[], DTYPE y[], int acc); 33 | // Tree flutes(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 34 | // DTYPE wirelength(Tree t); 35 | // void printtree(Tree t); 36 | // void plottree(Tree t); 37 | 38 | /*************************************/ 39 | /* Internal Parameters and Functions */ 40 | /*************************************/ 41 | #define POWVFILE "POWV9.dat" // LUT for POWV (Wirelength Vector) 42 | #define POSTFILE "POST9.dat" // LUT for POST (Steiner Tree) 43 | #define FLUTE_D 9 // LUT is used for d <= FLUTE_D , FLUTE_D <= 9 44 | #define TAU(A) (8 + 1.3 * (A)) 45 | #define D1(A) (25 + 120 / ((A) * (A))) // flute_mr is used for D1 < d <= D2 46 | #define D2(A) ((A) <= 6 ? 500 : 75 + 5 * (A)) 47 | 48 | typedef struct { 49 | DTYPE x, y; // starting point of the branch 50 | int n; // index of neighbor 51 | } Branch; 52 | 53 | typedef struct { 54 | int deg; // degree 55 | DTYPE length; // total wirelength 56 | Branch* branch; // array of tree branches 57 | } Tree; 58 | 59 | #if REMOVE_DUPLICATE_PIN == 1 60 | #define flutes_wl(d, xs, ys, s, acc) flutes_wl_RDP(d, xs, ys, s, acc) 61 | #define flutes(d, xs, ys, s, acc) flutes_RDP(d, xs, ys, s, acc) 62 | #else 63 | #define flutes_wl(d, xs, ys, s, acc) flutes_wl_ALLD(d, xs, ys, s, acc) 64 | #define flutes(d, xs, ys, s, acc) flutes_ALLD(d, xs, ys, s, acc) 65 | #endif 66 | 67 | #define flutes_wl_ALLD(d, xs, ys, s, acc) flutes_wl_LMD(d, xs, ys, s, acc) 68 | #define flutes_ALLD(d, xs, ys, s, acc) \ 69 | (d <= FLUTE_D? flutes_LD(d, xs, ys, s) : flutes_MD(d, xs, ys, s, acc)) 70 | // : (d<=D1(acc) ? flutes_MD(d, xs, ys, s, acc) 71 | // : flutes_HD(d, xs, ys, s, acc))) 72 | 73 | #define flutes_wl_LMD(d, xs, ys, s, acc) \ 74 | (d <=FLUTE_D? flutes_wl_LD(d, xs, ys, s) : flutes_wl_MD(d, xs, ys, s, acc)) 75 | #define flutes_LMD(d, xs, ys, s, acc) \ 76 | (d <=FLUTE_D? flutes_LD(d, xs, ys, s) : flutes_MD(d, xs, ys, s, acc)) 77 | 78 | //#define max(x,y) ((x)>(y)?(x):(y)) 79 | //#define min(x,y) ((x)<(y)?(x):(y)) 80 | // to work around max conflict with bitmap 81 | //#define abs(x) ((x)<0?(-x):(x)) 82 | using namespace std; 83 | #define ADIFF(x, y) ((x) > (y) ? (x - y) : (y - x)) // Absolute difference 84 | 85 | #if FLUTE_D<= 7 86 | #define MGROUP 5040 / 4 // Max. # of groups, 7! = 5040 87 | #define MPOWV 15 // Max. # of POWVs per group 88 | #elif FLUTE_D== 8 89 | #define MGROUP 40320 / 4 // Max. # of groups, 8! = 40320 90 | #define MPOWV 33 // Max. # of POWVs per group 91 | #elif FLUTE_D== 9 92 | #define MGROUP 362880 / 4 // Max. # of groups, 9! = 362880 93 | #define MPOWV 79 // Max. # of POWVs per group 94 | #endif 95 | extern int numgrp[10]; 96 | 97 | struct csoln { 98 | unsigned char parent; 99 | unsigned char seg[11]; // Add: 0..i, Sub: j..10; seg[i+1]=seg[j-1]=0 100 | unsigned char rowcol[FLUTE_D - 2]; // row = rowcol[]/16, col = rowcol[]%16, 101 | unsigned char neighbor[2 * FLUTE_D - 2]; 102 | }; 103 | extern struct csoln* LUT[FLUTE_D + 1][MGROUP]; // storing 4 .. D 104 | extern int numsoln[FLUTE_D + 1][MGROUP]; 105 | 106 | typedef struct node_pair_s { // pair of nodes representing an edge 107 | int node1, node2; 108 | } node_pair; 109 | extern node_pair* heap; 110 | 111 | struct point_flute { 112 | DTYPE x, y; 113 | int o; 114 | }; 115 | 116 | void readLUT(); 117 | DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc); 118 | DTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]); 119 | DTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 120 | DTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 121 | Tree flute(int d, DTYPE x[], DTYPE y[], int acc); 122 | Tree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]); 123 | Tree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 124 | Tree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc); 125 | Tree dmergetree(Tree t1, Tree t2); 126 | Tree hmergetree(Tree t1, Tree t2, int s[]); 127 | Tree vmergetree(Tree t1, Tree t2); 128 | void local_refinement(Tree* tp, int p); 129 | DTYPE wirelength(Tree t); 130 | void printtree(Tree t); 131 | void plottree(Tree t); 132 | 133 | #define MAX_HEAP_SIZE (MAXD * 2) 134 | extern int max_heap_size; 135 | inline void init_param() { 136 | heap = (node_pair*)malloc(sizeof(node_pair) * (max_heap_size + 1)); 137 | } 138 | 139 | [[noreturn]] inline void abort_with_message(std::string message) noexcept { 140 | std::cerr << message << std::endl; 141 | std::abort(); 142 | } 143 | 144 | void readLUT(const char* fluteDir); 145 | 146 | static int orderx(const void* a, const void* b) { 147 | struct point_flute *pa, *pb; 148 | 149 | pa = *(struct point_flute**)a; 150 | pb = *(struct point_flute**)b; 151 | 152 | if (pa->x < pb->x) 153 | return -1; 154 | if (pa->x > pb->x) 155 | return 1; 156 | return 0; 157 | } 158 | 159 | static int ordery(const void* a, const void* b) { 160 | struct point_flute *pa, *pb; 161 | 162 | pa = *(struct point_flute**)a; 163 | pb = *(struct point_flute**)b; 164 | 165 | if (pa->y < pb->y) 166 | return -1; 167 | if (pa->y > pb->y) 168 | return 1; 169 | return 0; 170 | } 171 | 172 | } //namespace sproute 173 | 174 | 175 | #endif /* _FLUTE_H_ */ 176 | 177 | 178 | -------------------------------------------------------------------------------- /include/fr_global.h: -------------------------------------------------------------------------------- 1 | #ifndef _FR_GLOBAL_H_ 2 | #define _FR_GLOBAL_H_ 3 | 4 | #include 5 | 6 | #define TRUE 1 7 | #define FALSE 0 8 | #define MAXLONG 0x7fffffffL 9 | 10 | struct point 11 | { 12 | long x, y; 13 | }; 14 | 15 | typedef struct point Point; 16 | 17 | typedef long nn_array[8]; 18 | 19 | #endif /* _FR_GLOBAL_H_ */ 20 | -------------------------------------------------------------------------------- /include/global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #include "flute.h" 5 | 6 | namespace sproute { 7 | 8 | int numgrp[10] = {0, 0, 0, 0, 6, 30, 180, 1260, 10080, 90720}; 9 | 10 | struct csoln* LUT[FLUTE_D + 1][MGROUP]; // storing 4 .. D 11 | int numsoln[FLUTE_D + 1][MGROUP]; 12 | 13 | float round_avg_dist; 14 | int round_avg_length; 15 | int xGrid, yGrid, numGrids, numNets, vCapacity, hCapacity; 16 | float vCapacity_lb, hCapacity_lb, vCapacity_ub, hCapacity_ub; 17 | int MaxDegree; 18 | int MinWidth[MAXLAYER], MinSpacing[MAXLAYER], ViaSpacing[MAXLAYER]; 19 | int xcorner, ycorner, wTile, hTile; 20 | int enlarge, costheight, ripup_threshold, ahTH; 21 | int numValidNets, 22 | numInvalidNets; // # nets need to be routed (having pins in different grids) 23 | int numLayers; 24 | int totalNumSeg; // total # segments 25 | int totalOverflow; // total # overflow 26 | int mazeThreshold; // the wirelen threshold to do maze routing 27 | Net** nets; 28 | Net** invalid_nets; 29 | Edge *h_edges, *v_edges; 30 | float d1[YRANGE][XRANGE]; 31 | float d2[YRANGE][XRANGE]; 32 | 33 | /*Bool HV[YRANGE][XRANGE]; 34 | Bool hyperV[YRANGE][XRANGE]; 35 | Bool hyperH[YRANGE][XRANGE]; 36 | 37 | int corrEdge[YRANGE][XRANGE];*/ //Michael 38 | int SLOPE; 39 | int vCapacity3D[MAXLAYER], hCapacity3D[MAXLAYER]; 40 | 41 | float LB; 42 | float UB; 43 | int THRESH_M; 44 | double LOGIS_COF; 45 | int ENLARGE; 46 | int STEP; 47 | int COSHEIGHT; 48 | int STOP; 49 | int VCA; 50 | float L; 51 | int VIA, slope, max_adj; 52 | 53 | char benchFile[STRINGLEN]; 54 | 55 | Segment* seglist; 56 | int* seglistIndex; // the index for the segments for each net 57 | int* seglistCnt; // the number of segements for each net 58 | int* segOrder; // the order of segments for routing 59 | Tree* trees; // the tree topologies 60 | StTree* sttrees; // the Steiner trees 61 | DTYPE** gxs; // the copy of xs for nets, used for second FLUTE 62 | DTYPE** gys; // the copy of xs for nets, used for second FLUTE 63 | DTYPE** gs; // the copy of vertical sequence for nets, used for second FLUTE 64 | int MD = 0, TD = 0; 65 | 66 | Edge3D* h_edges3D; 67 | Edge3D* v_edges3D; 68 | 69 | OrderNetPin* treeOrderPV; 70 | OrderTree* treeOrderCong; 71 | int numTreeedges; 72 | int viacost; 73 | 74 | int layerGrid[MAXLAYER][MAXLEN]; 75 | int gridD[MAXLAYER][MAXLEN]; 76 | int viaLink[MAXLAYER][MAXLEN]; 77 | 78 | int d13D[MAXLAYER][YRANGE][XRANGE]; 79 | short d23D[MAXLAYER][YRANGE][XRANGE]; 80 | 81 | dirctionT*** directions3D; 82 | int*** corrEdge3D; 83 | parent3D*** pr3D; 84 | 85 | int mazeedge_Threshold; 86 | bool inRegion[YRANGE][XRANGE]; 87 | 88 | bool heapVisited[MAXNETDEG]; 89 | // int heapQueue[MAXNETDEG]; //Michael 90 | 91 | int gridHV, gridH, gridV, gridHs[MAXLAYER], gridVs[MAXLAYER]; 92 | 93 | int** heap13D; 94 | short** heap23D; 95 | 96 | float *h_costTable, *v_costTable; 97 | bool stopDEC, errorPRONE; 98 | // OrderNetEdge netEO[2000]; //Michael 99 | int xcor[MAXD * 2 - 3], ycor[MAXD * 2 - 3], dcor[MAXD * 2 - 3]; 100 | 101 | StTree* sttreesBK; 102 | 103 | short **parentX1, **parentY1, **parentX3, **parentY3; 104 | 105 | /*float **heap2,**heap1; //Michael 106 | 107 | Bool *pop_heap2;*/ 108 | 109 | // Michael: 110 | int LOCK; 111 | 112 | int max_heap_size = MAX_HEAP_SIZE; 113 | node_pair* heap; 114 | 115 | 116 | float costHVH[XRANGE]; // Horizontal first Z 117 | float costVHV[YRANGE]; // Vertical first Z 118 | float costH[YRANGE]; // Horizontal segment cost 119 | float costV[XRANGE]; // Vertical segment cost 120 | float costLR[YRANGE]; // Left and right boundary cost 121 | float costTB[XRANGE]; // Top and bottom boundary cost 122 | 123 | float costHVHtest[YRANGE]; // Vertical first Z 124 | float costVtest[XRANGE]; // Vertical segment cost 125 | float costTBtest[XRANGE]; // Top and bottom boundary cost 126 | 127 | } 128 | 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /include/global_variable_extern.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_VARIABLE_EXTERN_H 2 | #define GLOBAL_VARIABLE_EXTERN_H 3 | 4 | #include "DataType.h" 5 | #include "DataProc.h" 6 | #include "flute.h" 7 | 8 | namespace sproute { 9 | 10 | extern int numgrp[10]; 11 | 12 | extern struct csoln* LUT[FLUTE_D + 1][MGROUP]; // storing 4 .. D 13 | extern int numsoln[FLUTE_D + 1][MGROUP]; 14 | 15 | extern float round_avg_dist; 16 | extern int round_avg_length; 17 | extern int xGrid, yGrid, numGrids, numNets, vCapacity, hCapacity; 18 | extern float vCapacity_lb, hCapacity_lb, vCapacity_ub, hCapacity_ub; 19 | extern int MaxDegree; 20 | extern int MinWidth[MAXLAYER], MinSpacing[MAXLAYER], ViaSpacing[MAXLAYER]; 21 | extern int xcorner, ycorner, wTile, hTile; 22 | extern int enlarge, costheight, ripup_threshold, ahTH; 23 | extern int numValidNets, 24 | numInvalidNets; // # nets need to be routed (having pins in different grids) 25 | extern int numLayers; 26 | extern int totalNumSeg; // total # segments 27 | extern int totalOverflow; // total # overflow 28 | extern int mazeThreshold; // the wirelen threshold to do maze routing 29 | 30 | extern Net** nets; 31 | extern Net** invalid_nets; 32 | extern Edge *h_edges, *v_edges; 33 | extern float d1[YRANGE][XRANGE]; 34 | extern float d2[YRANGE][XRANGE]; 35 | 36 | extern int SLOPE; 37 | extern int vCapacity3D[MAXLAYER], hCapacity3D[MAXLAYER]; 38 | 39 | extern float LB; 40 | extern float UB; 41 | extern int THRESH_M; 42 | extern double LOGIS_COF; 43 | extern int ENLARGE; 44 | extern int STEP; 45 | extern int COSHEIGHT; 46 | extern int STOP; 47 | extern int VCA; 48 | extern float L; 49 | extern int VIA, slope, max_adj; 50 | 51 | extern char benchFile[STRINGLEN]; 52 | 53 | extern Segment* seglist; 54 | extern int* seglistIndex; // the index for the segments for each net 55 | extern int* seglistCnt; // the number of segements for each net 56 | extern int* segOrder; // the order of segments for routing 57 | extern Tree* trees; // the tree topologies 58 | extern StTree* sttrees; // the Steiner trees 59 | extern DTYPE** gxs; // the copy of xs for nets, used for second FLUTE 60 | extern DTYPE** gys; // the copy of xs for nets, used for second FLUTE 61 | extern DTYPE** gs; // the copy of vertical sequence for nets, used for second FLUTE 62 | extern int MD, TD; 63 | 64 | extern Edge3D* h_edges3D; 65 | extern Edge3D* v_edges3D; 66 | 67 | extern OrderNetPin* treeOrderPV; 68 | extern OrderTree* treeOrderCong; 69 | extern int numTreeedges; 70 | extern int viacost; 71 | 72 | extern int layerGrid[MAXLAYER][MAXLEN]; 73 | extern int gridD[MAXLAYER][MAXLEN]; 74 | extern int viaLink[MAXLAYER][MAXLEN]; 75 | 76 | extern int d13D[MAXLAYER][YRANGE][XRANGE]; 77 | extern short d23D[MAXLAYER][YRANGE][XRANGE]; 78 | 79 | extern dirctionT*** directions3D; 80 | extern int*** corrEdge3D; 81 | extern parent3D*** pr3D; 82 | 83 | extern int mazeedge_Threshold; 84 | extern bool inRegion[YRANGE][XRANGE]; 85 | 86 | extern bool heapVisited[MAXNETDEG]; 87 | // int heapQueue[MAXNETDEG]; //Michael 88 | 89 | extern int gridHV, gridH, gridV, gridHs[MAXLAYER], gridVs[MAXLAYER]; 90 | 91 | extern int** heap13D; 92 | extern short** heap23D; 93 | 94 | extern float *h_costTable, *v_costTable; 95 | extern bool stopDEC, errorPRONE; 96 | // OrderNetEdge netEO[2000]; //Michael 97 | extern int xcor[MAXD * 2 - 3], ycor[MAXD * 2 - 3], dcor[MAXD * 2 - 3]; 98 | 99 | extern StTree* sttreesBK; 100 | 101 | extern short **parentX1, **parentY1, **parentX3, **parentY3; 102 | 103 | /*float **heap2,**heap1; //Michael 104 | 105 | Bool *pop_heap2;*/ 106 | 107 | // Michael: 108 | extern int LOCK; 109 | 110 | extern int max_heap_size; 111 | 112 | } 113 | 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /include/grGen.h: -------------------------------------------------------------------------------- 1 | #ifndef GRGEN_H 2 | #define GRGEN_H 3 | 4 | #include "header.h" 5 | #include "sprouteDataType.h" 6 | #include "defDataBase.h" 7 | #include "sproute.h" 8 | 9 | namespace sproute_db 10 | { 11 | 12 | 13 | 14 | class CongestionMap { 15 | float* hCongestion; 16 | float* vCongestion; 17 | int xGrid; 18 | int yGrid; 19 | int numLayers; 20 | public: 21 | CongestionMap(int numLayers, int xGrid, int yGrid) { 22 | this->xGrid = xGrid; 23 | this->yGrid = yGrid; 24 | this->numLayers = numLayers; 25 | hCongestion = new float [numLayers * (xGrid - 1) * yGrid]; 26 | vCongestion = new float [numLayers * xGrid * (yGrid - 1)]; 27 | 28 | }; 29 | 30 | float getCongestion(int layer, int x, int y, bool horizontal) { 31 | if(horizontal) { 32 | int grid = y*(xGrid-1) + x + layer*(xGrid-1)*yGrid; 33 | return hCongestion[grid]; 34 | } 35 | else { 36 | int grid = y*xGrid + x + layer*xGrid*(yGrid - 1); 37 | return vCongestion[grid]; 38 | } 39 | } 40 | 41 | void setCongestion(int layer, int x, int y, bool horizontal, float cong) { 42 | if(horizontal) { 43 | int grid = y*(xGrid-1) + x + layer*(xGrid-1)*yGrid; 44 | //cout << x << " " << y << " " << layer << " " << cong << endl; 45 | hCongestion[grid] = cong; 46 | } 47 | else { 48 | int grid = y*xGrid + x + layer*xGrid*(yGrid - 1); 49 | vCongestion[grid] = cong; 50 | } 51 | } 52 | }; 53 | 54 | class grNet 55 | { 56 | public: 57 | string name; 58 | int idx; 59 | int numPins; 60 | int minWidth; 61 | std::vector> pins; 62 | std::set> pinRegion; 63 | grNet() { 64 | minWidth = 1; 65 | } 66 | 67 | void clear() 68 | { 69 | name = ""; 70 | idx = -1; 71 | numPins = 0; 72 | minWidth = 1; 73 | } 74 | 75 | }; 76 | 77 | class grGenerator 78 | { 79 | public: 80 | Point3D grid; 81 | std::vector vCap; 82 | std::vector hCap; 83 | 84 | Point2D gcellBegin; 85 | Point2D gcellSize; 86 | 87 | int numNets; 88 | std::vector grnets; 89 | std::map netName2grnetidx; 90 | 91 | int minWidth; 92 | int minSpacing; 93 | int viaSpacing; 94 | 95 | int numAdjust; 96 | galois::InsertBag* capReductions_p; 97 | 98 | grGenerator() {} 99 | 100 | grGenerator(lefDataBase& lefDB, defDataBase& defDB, galois::InsertBag& capReductions) 101 | { 102 | capReductions_p = &capReductions; 103 | minWidth = 1; 104 | minSpacing = 1; 105 | viaSpacing = 1; 106 | gcellBegin.set(defDB.xGcellBoundaries.front(), defDB.yGcellBoundaries.front()); 107 | numAdjust = 0; 108 | 109 | int numLayers = 0; 110 | for(auto layer : lefDB.layers) 111 | { 112 | if(layer.type == "ROUTING") 113 | numLayers++; 114 | } 115 | 116 | grid.x = 0; 117 | grid.y = 0; 118 | grid.z = numLayers; 119 | int maxGcellCnt_x = 0, maxGcellCnt_y = 0; 120 | for(auto gcellGrid : defDB.gcellGrids) 121 | { 122 | if(gcellGrid.direction == "X") 123 | { 124 | grid.x += (gcellGrid.numBoundaries - 1); 125 | if(gcellGrid.numBoundaries > maxGcellCnt_x) { 126 | maxGcellCnt_x = gcellGrid.numBoundaries; 127 | gcellSize.x = gcellGrid.step; 128 | } 129 | } 130 | else if(gcellGrid.direction == "Y") 131 | { 132 | grid.y += (gcellGrid.numBoundaries - 1); 133 | if(gcellGrid.numBoundaries > maxGcellCnt_y) { 134 | maxGcellCnt_y = gcellGrid.numBoundaries; 135 | gcellSize.y = gcellGrid.step; 136 | } 137 | } 138 | else 139 | { 140 | cout << "unknown gcell direction: " << gcellGrid.direction << endl; 141 | exit(1); 142 | } 143 | } 144 | cout << grid.x << " " << grid.y << " " << grid.z << endl; 145 | 146 | cout << "gcellbegin: " << gcellBegin.x << " " << gcellBegin.y < 1000) 234 | cout << "large net: " << net.name << " " << numPins << endl; 235 | tmpGRnet.numPins = numPins; 236 | for(int i = 0; i < numPins; i++) 237 | { 238 | int x, y, z; 239 | string compName = net.componentNames.at(i); 240 | string pinName = net.pinNames.at(i); 241 | 242 | 243 | if(compName == "PIN") // pin is an IO pin 244 | { 245 | int IOPinIdx = defDB.iopin2idx.find(pinName)->second; 246 | IOPin iopin = defDB.iopins.at(IOPinIdx); 247 | 248 | x = iopin.location.x; 249 | y = iopin.location.y; 250 | int pinx = find_Gcell(x, defDB.xGcellBoundaries); 251 | int piny = find_Gcell(y, defDB.yGcellBoundaries); 252 | z = lefDB.layer2idx[iopin.layerName] / 2 + 1; 253 | 254 | int xmin = (pinx < 1)? 0 : pinx - 1; 255 | int ymin = (piny < 1)? 0 : piny - 1; 256 | int xmax = (pinx >= grid.x - 1)? grid.x - 1: pinx + 1; 257 | int ymax = (piny >= grid.y - 1)? grid.y - 1: piny + 1; 258 | 259 | for(int pinRegionx = xmin; pinRegionx <= xmax; pinRegionx++) 260 | { 261 | for(int pinRegiony = ymin; pinRegiony <= ymax; pinRegiony++) 262 | tmpGRnet.pinRegion.insert(Point3D(pinRegionx, pinRegiony, z)); 263 | } 264 | } 265 | else 266 | { 267 | int compIdx = defDB.component2idx.find(compName)->second; 268 | Component& component = defDB.components.at(compIdx); 269 | bool found = false; 270 | for(auto& pin : component.macro.pins) 271 | { 272 | if(pinName == pin.name) 273 | { 274 | x = pin.layerRects.at(0).rects.at(0).lowerLeft.x; 275 | y = pin.layerRects.at(0).rects.at(0).lowerLeft.y; 276 | string layerName = pin.layerRects.at(0).layerName; 277 | z = lefDB.layer2idx.find(layerName)->second / 2 + 1; 278 | found = true; 279 | 280 | for(auto layerRects : pin.layerRects) 281 | { 282 | int layerIdx = lefDB.layer2idx[layerRects.layerName]; 283 | if(lefDB.layers[layerIdx].type != "ROUTING") 284 | continue; 285 | int pinRegionz = layerIdx / 2 + 1; 286 | int trackIdx = defDB.layeridx2trackidx[layerIdx]; 287 | int trackStep = defDB.tracks.at(trackIdx).step; 288 | for(auto rect: layerRects.rects) 289 | { 290 | int xmin = find_Gcell(rect.lowerLeft.x, defDB.xGcellBoundaries); 291 | int ymin = find_Gcell(rect.lowerLeft.y, defDB.yGcellBoundaries); 292 | int xmax = find_Gcell(rect.upperRight.x, defDB.xGcellBoundaries); 293 | int ymax = find_Gcell(rect.upperRight.y, defDB.yGcellBoundaries); 294 | 295 | xmin = (xmin < 0)? 0 : xmin; 296 | ymin = (ymin < 0)? 0 : ymin; 297 | xmax = (xmax >= grid.x)? grid.x - 1: xmax; 298 | ymax = (ymax >= grid.y)? grid.y - 1: ymax; 299 | 300 | for(int pinRegionx = xmin; pinRegionx <= xmax; pinRegionx++) 301 | { 302 | for(int pinRegiony = ymin; pinRegiony <= ymax; pinRegiony++) 303 | tmpGRnet.pinRegion.insert(Point3D(pinRegionx, pinRegiony, pinRegionz)); 304 | } 305 | } 306 | } 307 | break; 308 | } 309 | } 310 | assert(found == true); 311 | } 312 | Point3D grpin(x, y, z); 313 | tmpGRnet.pins.push_back(grpin); 314 | //cout << x << " " << y << " " << z << endl; 315 | } 316 | grnets[idx] = tmpGRnet; 317 | // cnt1++; 318 | //grnets.push_back(tmpGRnet); 319 | //netName2grnetidx.insert( pair< string, int> (tmpGRnet.name, tmpGRnet.idx)); 320 | 321 | // tmpGRnet.pinRegion.clear(); 322 | //tmpGRnet.clear(); 323 | 324 | }, galois::steal()); 325 | 326 | cout << "out here? " << endl; 327 | std::cout << "numnets: " << numNets << endl; 328 | cout << "cnt1: " << cnt1 << endl; 329 | 330 | // for(auto i=0;icapReductions_p)) 384 | outfile << capReduction.x << " " << capReduction.y << " " << capReduction.z << " " << capReduction.newCap << endl; 385 | } 386 | }; 387 | 388 | } 389 | 390 | #endif 391 | -------------------------------------------------------------------------------- /include/header.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef HEADER_H 3 | #define HEADER_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | //#include "defrReader.hpp" 20 | //#include "defwWriter.hpp" 21 | //#include "lefrReader.hpp" 22 | 23 | #include "galois/Bag.h" 24 | #include "galois/Galois.h" 25 | 26 | /*#ifdef OPENDB 27 | #include "db.h" 28 | #include "defin.h" 29 | #include "lefin.h" 30 | #endif*/ 31 | 32 | using namespace std; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/heap.h: -------------------------------------------------------------------------------- 1 | #ifndef _HEAP_H_ 2 | #define _HEAP_H_ 3 | 4 | #include "fr_global.h" 5 | 6 | struct heap_info { 7 | long key; 8 | long idx; 9 | long elt; 10 | }; 11 | 12 | typedef struct heap_info Heap; 13 | 14 | extern Heap* _heap; 15 | 16 | #define heap_key(p) (_heap[p].key) 17 | #define heap_idx(p) (_heap[p].idx) 18 | #define heap_elt(k) (_heap[k].elt) 19 | 20 | #define in_heap(p) (heap_idx(p) > 0) 21 | #define never_seen(p) (heap_idx(p) == 0) 22 | 23 | void allocate_heap(long n); 24 | void deallocate_heap(); 25 | void heap_init(long n); 26 | void heap_insert(long p, long key); 27 | void heap_decrease_key(long p, long new_key); 28 | long heap_delete_min(); 29 | 30 | #endif /* _HEAP_H_ */ 31 | -------------------------------------------------------------------------------- /include/lefDataBase.h: -------------------------------------------------------------------------------- 1 | #ifndef LEFDATABASE_H 2 | #define LEFDATABASE_H 3 | 4 | #include "header.h" 5 | #include "sprouteDataType.h" 6 | 7 | namespace sproute_db 8 | { 9 | 10 | class ViaRuleGenerateLayer 11 | { 12 | public: 13 | string layerName; 14 | Rect2D rect; 15 | Size2D spacing; 16 | Size2D enclosureOverhang; 17 | 18 | ViaRuleGenerateLayer( ) { } 19 | void print() 20 | { 21 | cout << " layer: " << layerName << endl; 22 | if(!rect.empty()) 23 | { 24 | cout << " RECT:"; 25 | rect.print(); 26 | } 27 | if(!spacing.empty()) 28 | { 29 | cout << " SPACING: "; 30 | spacing.print(); 31 | } 32 | if(!enclosureOverhang.empty()) 33 | { 34 | cout << " ENC: "; 35 | enclosureOverhang.print(); 36 | } 37 | } 38 | 39 | }; 40 | 41 | class ViaRuleGenerate 42 | { 43 | public: 44 | string name; 45 | bool isDefault; 46 | ViaRuleGenerateLayer layers[3]; 47 | 48 | ViaRuleGenerate() { 49 | isDefault = true; 50 | } 51 | void print() 52 | { 53 | cout << "VIARULE: " << name << endl; 54 | for(int i = 0; i < 3; i++) 55 | { 56 | layers[i].print(); 57 | } 58 | } 59 | }; 60 | 61 | class PropertyDef 62 | { 63 | public: 64 | string objectType; 65 | string propName; 66 | string propType; 67 | 68 | PropertyDef() { } 69 | PropertyDef(string objType, string propName, string propType) { 70 | this->objectType = objType; 71 | this->propName = propName; 72 | this->propType = propType; 73 | } 74 | }; 75 | 76 | class SpacingTable 77 | { 78 | public: 79 | int numCols; 80 | int numRows; 81 | std::vector parallelRunLength; 82 | std::vector width; 83 | std::vector spacing; 84 | 85 | SpacingTable() { } 86 | SpacingTable(int numCols, int numRows) { 87 | this->numCols = numCols; 88 | this->numRows = numRows; 89 | } 90 | 91 | void setSize(int numCols, int numRows) { 92 | this->numCols = numCols; 93 | this->numRows = numRows; 94 | } 95 | void reset() 96 | { 97 | numCols = 0; 98 | numRows = 0; 99 | parallelRunLength.clear(); 100 | width.clear(); 101 | spacing.clear(); 102 | } 103 | void print() 104 | { 105 | cout << "numCols: " << numCols << " numRows: " << numRows << endl; 106 | cout << " parallelRunLength:" ; 107 | for(auto p : parallelRunLength) 108 | { 109 | cout << p << " "; 110 | } 111 | cout << endl; 112 | cout << " width:" ; 113 | for(auto w : width) 114 | { 115 | cout << w << " "; 116 | } 117 | cout << endl; 118 | cout << " spacing:" ; 119 | for(auto s : spacing) 120 | { 121 | cout << s << " "; 122 | } 123 | cout << endl; 124 | } 125 | float getSpacing(int col, int row) 126 | { 127 | return spacing.at(col + row*numCols); 128 | } 129 | }; 130 | 131 | class Spacing //only EOL spacing for now 132 | { 133 | public: 134 | //metal layer 135 | float spacing; 136 | float eolWidth; 137 | float eolWithin; 138 | float parEdge; 139 | float parWithin; 140 | 141 | //cut layer 142 | int adjacentCuts; 143 | float cutWithin; 144 | Spacing () 145 | { 146 | spacing = 0; 147 | eolWidth = 0; 148 | eolWithin = 0; 149 | parEdge = 0; 150 | parWithin = 0; 151 | adjacentCuts = 0; 152 | cutWithin = 0; 153 | } 154 | void reset() 155 | { 156 | spacing = 0; 157 | eolWidth = 0; 158 | eolWithin = 0; 159 | parEdge = 0; 160 | parWithin = 0; 161 | adjacentCuts = 0; 162 | cutWithin = 0; 163 | } 164 | void print() 165 | { 166 | cout << " spacing: " << spacing << " eolWidth: " << eolWidth << " eolWithin: " << eolWithin << endl; 167 | cout << " parEdge: " << parEdge << " parWithin: " << parWithin << endl; 168 | cout << " adjacentCuts: " << adjacentCuts << " cutWithin: " << cutWithin << endl; 169 | } 170 | }; 171 | 172 | class Property 173 | { 174 | public: 175 | string propName; 176 | string propString; 177 | }; 178 | 179 | class CornerSpacing 180 | { 181 | public: 182 | float eolWidth; 183 | std::vector width; 184 | std::vector spacing; 185 | 186 | CornerSpacing() { 187 | eolWidth = 0; 188 | } 189 | void reset() 190 | { 191 | eolWidth = 0; 192 | width.clear(); 193 | spacing.clear(); 194 | } 195 | void print() 196 | { 197 | cout << "cornerSpacing eolWidth: " << eolWidth << endl; 198 | cout << "width: "; 199 | for(auto w : width) 200 | { 201 | cout << " " << w; 202 | } 203 | cout << endl; 204 | cout << "spacing: "; 205 | for(auto s : spacing) 206 | { 207 | cout << " " << s; 208 | } 209 | cout << endl; 210 | } 211 | 212 | }; 213 | 214 | class Layer 215 | { 216 | public: 217 | string name; 218 | string type; 219 | int idx; 220 | //metal layer 221 | string direction; 222 | float pitchx; 223 | float pitchy; 224 | float width; 225 | float area; 226 | float minWidth; 227 | float offset; 228 | 229 | SpacingTable spacingTable; 230 | std::vector spacings; 231 | Spacing maxEOLSpacing; 232 | CornerSpacing cornerSpacing; 233 | 234 | //cut layer 235 | float spacing; 236 | void reset() 237 | { 238 | name = ""; 239 | type = ""; 240 | idx = 0; 241 | direction = ""; 242 | pitchx = 0; 243 | pitchy = 0; 244 | width = 0; 245 | area = 0; 246 | minWidth = 0; 247 | offset = 0; 248 | spacingTable.reset(); 249 | spacings.clear(); 250 | cornerSpacing.reset(); 251 | spacing = 0; 252 | } 253 | void print() 254 | { 255 | cout << "------------------------------" << endl; 256 | cout << "Layer: " << name << " type: " << type << " direction: " << direction << " idx: " << idx << endl; 257 | cout << "pitch: " << pitchx << " " << pitchy << " width:" << width << " area: " << area << endl; 258 | cout << "minWidth: " << minWidth << " offset: " << offset << " spacing: " << spacing << endl; 259 | if(spacingTable.parallelRunLength.size()) 260 | spacingTable.print(); 261 | for(auto spacing : spacings) 262 | { 263 | spacing.print(); 264 | } 265 | if(cornerSpacing.width.size()) 266 | cornerSpacing.print(); 267 | 268 | } 269 | }; 270 | 271 | 272 | 273 | class LayerRect 274 | { 275 | public: 276 | string layerName; 277 | std::vector> rects; 278 | 279 | void print() 280 | { 281 | cout << " layer rect : layer " << layerName << endl; 282 | for(auto rect : rects) 283 | rect.print(); 284 | } 285 | void reset() 286 | { 287 | layerName = ""; 288 | rects.clear(); 289 | } 290 | }; 291 | 292 | class lefVia 293 | { 294 | public: 295 | string name; 296 | bool isDefault; 297 | std::vector layerRects; 298 | void reset() 299 | { 300 | name = ""; 301 | isDefault = false; 302 | layerRects.clear(); 303 | } 304 | void print() 305 | { 306 | cout << " Via name: " << name << endl; 307 | for(auto l : layerRects) 308 | l.print(); 309 | } 310 | }; 311 | 312 | class Site 313 | { 314 | public: 315 | string name; 316 | string className; 317 | float width; 318 | float height; 319 | void print() 320 | { 321 | cout << name << " " << className << " " << width << " " << height << endl; 322 | } 323 | }; 324 | 325 | class Pin 326 | { 327 | public: 328 | string name; 329 | string direction; 330 | string output_tristate; 331 | string use; 332 | string shape; 333 | float antennaDiffArea; 334 | string antennaDiffAreaLayer; 335 | 336 | 337 | std::vector netExpr; 338 | std::vector layerRects; // one layer is an element in the vector 339 | void print() 340 | { 341 | cout << "pin name: " << name << " direction: " << direction << endl; 342 | for(auto layerRect : layerRects) 343 | layerRect.print(); 344 | } 345 | }; 346 | 347 | class Obstacle 348 | { 349 | public: 350 | std::vector layerRects; // one layer is an element in the vector 351 | 352 | void reset() 353 | { 354 | layerRects.clear(); 355 | } 356 | void print() 357 | { 358 | for(auto layerRect : layerRects) 359 | layerRect.print(); 360 | } 361 | }; 362 | 363 | class Macro 364 | { 365 | public: 366 | string name; 367 | 368 | Point2D origin; 369 | Point2D size; 370 | 371 | std::vector pins; 372 | Obstacle obs; 373 | Macro() {} 374 | 375 | void reset() 376 | { 377 | name = ""; 378 | origin.reset(); 379 | size.reset(); 380 | pins.clear(); 381 | obs.reset(); 382 | } 383 | 384 | void setOrigin(float x, float y) 385 | { 386 | origin.x = x; 387 | origin.y = y; 388 | } 389 | 390 | void setSize(float x, float y) 391 | { 392 | size.x = x; 393 | size.y = y; 394 | } 395 | 396 | void print() 397 | { 398 | cout << "macro name: " << name << endl; 399 | 400 | cout << "origin point: " << endl; 401 | origin.print(); 402 | cout << "size: " << endl; 403 | size.print(); 404 | cout << "width: " << size.x << "height: " << size.y << endl; 405 | 406 | cout << "Pins: "; 407 | for(auto pin : pins) 408 | pin.print(); 409 | } 410 | }; 411 | 412 | class Unit 413 | { 414 | public: 415 | string types; 416 | string unit; 417 | int factors; 418 | Unit() {} 419 | Unit(string types, string unit, int factors): 420 | types(types), unit(unit), factors(factors) {} 421 | }; 422 | 423 | class lefDataBase 424 | { 425 | public: 426 | std::vector units; 427 | std::vector properties; 428 | std::vector layers; 429 | std::vector vias; 430 | std::vector sites; 431 | std::vector macros; 432 | std::vector viaRuleGenerates; 433 | 434 | string version; 435 | string busBitChars; 436 | string dividerChar; 437 | 438 | int dbuPerMicron; 439 | 440 | double manufacturingGrid; 441 | 442 | std::map layer2idx; 443 | std::map macro2idx; 444 | std::map lefVia2idx; 445 | std::map viaRuleGenerate2idx; 446 | 447 | Macro tmpMacro; 448 | Layer tmpLayer; 449 | }; 450 | 451 | 452 | /*int getLefMacros(lefrCallbackType_e , lefiMacro* , lefiUserData ); 453 | int getLefString(lefrCallbackType_e , const char* , lefiUserData ); 454 | int getLefUnits(lefrCallbackType_e , lefiUnits* , lefiUserData ); 455 | int getLefManufacturingGrid(lefrCallbackType_e , double , lefiUserData ); 456 | int getLefPins(lefrCallbackType_e , lefiPin* , lefiUserData ); 457 | int getLefObs(lefrCallbackType_e , lefiObstruction* , lefiUserData ); 458 | int getLefLayers(lefrCallbackType_e , lefiLayer* , lefiUserData ); 459 | int getLefVias(lefrCallbackType_e , lefiVia* , lefiUserData ); 460 | int getLefViaGenerateRules(lefrCallbackType_e , lefiViaRule* , lefiUserData );*/ 461 | 462 | } //namespace sproute_db 463 | 464 | #endif 465 | 466 | -------------------------------------------------------------------------------- /include/maze.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAZE_H_ 2 | #define _MAZE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "DataType.h" 9 | #include "flute.h" 10 | #include "DataProc.h" 11 | #include "route.h" 12 | #include "ripup.h" 13 | #include "RSMT.h" 14 | 15 | #include "galois/Galois.h" 16 | #include "galois/gstl.h" 17 | #include "galois/PerThreadContainer.h" 18 | #include "galois/Reduction.h" 19 | #include "galois/PriorityQueue.h" 20 | #include "galois/Timer.h" 21 | #include "galois/graphs/Graph.h" 22 | #include "galois/graphs/TypeTraits.h" 23 | #include "galois/substrate/SimpleLock.h" 24 | #include "galois/substrate/NumaMem.h" 25 | #include "galois/AtomicHelpers.h" 26 | #include "galois/runtime/Profile.h" 27 | 28 | #include "galois/LargeArray.h" 29 | 30 | // using namespace std; 31 | 32 | namespace sproute { 33 | 34 | #define PARENT(i) (i - 1) / 2 35 | //#define PARENT(i) ((i-1)>>1) 36 | #define LEFT(i) 2 * i + 1 37 | #define RIGHT(i) 2 * i + 2 38 | 39 | #define NET_PARALLEL 0 40 | 41 | struct maze_greater { 42 | bool operator()(float* left, float* right) { return (*left) > (*right); } 43 | }; 44 | 45 | class pq_grid { 46 | public: 47 | float* d1_p; 48 | float d1_push; 49 | pq_grid() { 50 | d1_p = NULL; 51 | d1_push = 0; 52 | }; 53 | pq_grid(float* d1_p, float d1_push) { 54 | this->d1_p = d1_p; 55 | this->d1_push = d1_push; 56 | } 57 | }; 58 | 59 | class lateUpdateReq { 60 | public: 61 | std::atomic* d1_p; 62 | float d1_push; 63 | short parentX; 64 | short parentY; 65 | bool HV; 66 | lateUpdateReq() { 67 | d1_p = NULL; 68 | d1_push = 0; 69 | parentX = 0; 70 | parentY = 0; 71 | HV = false; // 1 == true, 3 == false 72 | }; 73 | lateUpdateReq(std::atomic* d1_p, float d1_push, short parentX, 74 | short parentY, bool HV) { 75 | this->d1_p = d1_p; 76 | this->d1_push = d1_push; 77 | this->parentX = parentX; 78 | this->parentY = parentY; 79 | this->HV = HV; 80 | } 81 | }; 82 | 83 | struct pq_less { 84 | bool operator()(const pq_grid& left, const pq_grid& right) const { 85 | return left.d1_push < right.d1_push; 86 | } 87 | }; 88 | 89 | /*typedef galois::PerThreadDeque< float* > PerThread_PQ; 90 | typedef galois::gstl::Deque< float* > local_pq;*/ //FIFO TRIAL 91 | 92 | typedef galois::PerThreadMinHeap PerThread_PQ; 93 | typedef galois::gstl::PQ local_pq; 94 | 95 | typedef galois::PerThreadVector PerThread_Vec; 96 | typedef galois::gstl::Vector local_vec; 97 | 98 | typedef struct { 99 | int x; // x position 100 | int y; // y position 101 | } Pos; 102 | 103 | #define FIFO_CHUNK_SIZE 4 104 | #define OBIM_delta 20 105 | 106 | namespace { 107 | 108 | auto RequestIndexer = [](const pq_grid& top) { 109 | return (unsigned int)(top.d1_push) / 110 | max(OBIM_delta, (int)(costheight / (2 * slope))); 111 | }; 112 | 113 | auto RequestIndexerLate = [](const lateUpdateReq& top) { 114 | return (unsigned int)(top.d1_push) / OBIM_delta; 115 | }; 116 | 117 | } 118 | 119 | /*auto RequestIndexerConcurrent = [&](const concurrent_pq_grid& top) { 120 | return (unsigned int)(top.d1_push) / OBIM_delta; 121 | };*/ 122 | 123 | namespace gwl = galois::worklists; 124 | using PSChunk = gwl::PerThreadChunkFIFO; 125 | using OBIM = gwl::OrderedByIntegerMetric; 126 | using OBIM_late = 127 | gwl::OrderedByIntegerMetric; 128 | // using OBIM_concurrent = 129 | // gwl::OrderedByIntegerMetric; 130 | 131 | struct THREAD_LOCAL_STORAGE { 132 | using LAptr = galois::substrate::LAptr; 133 | LAptr pop_heap2_LA; 134 | bool* pop_heap2; 135 | 136 | LAptr d1_p_LA, d1_alloc_LA; 137 | float** d1_p; 138 | float* d1_alloc; 139 | 140 | LAptr HV_p_LA, HV_alloc_LA, hyperV_p_LA, hyperV_alloc_LA, hyperH_p_LA, 141 | hyperH_alloc_LA; 142 | bool **HV_p, **hyperV_p, **hyperH_p; 143 | bool *HV_alloc, *hyperV_alloc, *hyperH_alloc; 144 | 145 | LAptr parentX1_p_LA, parentX1_alloc_LA, parentY1_p_LA, parentY1_alloc_LA, 146 | parentX3_p_LA, parentX3_alloc_LA, parentY3_p_LA, parentY3_alloc_LA; 147 | short **parentX1_p, **parentY1_p, **parentX3_p, **parentY3_p; 148 | short *parentX1_alloc, *parentY1_alloc, *parentX3_alloc, *parentY3_alloc; 149 | 150 | LAptr corrEdge_p_LA, corrEdge_alloc_LA; 151 | int** corrEdge_p; 152 | int* corrEdge_alloc; 153 | 154 | LAptr inRegion_p_LA, inRegion_alloc_LA; 155 | bool** inRegion_p; 156 | bool* inRegion_alloc; 157 | 158 | LAptr netEO_p_LA; 159 | OrderNetEdge* netEO_p; 160 | 161 | int* v_local_usage; 162 | int* h_local_usage; 163 | 164 | // maze_pq pq1; 165 | // std::vector v2; 166 | THREAD_LOCAL_STORAGE() { 167 | using namespace galois::substrate; 168 | 169 | if (NET_PARALLEL) { 170 | pop_heap2_LA = largeMallocLocal(yGrid * xGrid * sizeof(bool)); 171 | pop_heap2 = reinterpret_cast(pop_heap2_LA.get()); 172 | 173 | d1_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(float)); 174 | d1_alloc = reinterpret_cast(d1_alloc_LA.get()); 175 | d1_p_LA = largeMallocLocal(yGrid * sizeof(float*)); 176 | d1_p = reinterpret_cast(d1_p_LA.get()); 177 | 178 | HV_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(bool)); 179 | HV_alloc = reinterpret_cast(HV_alloc_LA.get()); 180 | hyperV_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(bool)); 181 | hyperV_alloc = reinterpret_cast(hyperV_alloc_LA.get()); 182 | hyperH_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(bool)); 183 | hyperH_alloc = reinterpret_cast(hyperH_alloc_LA.get()); 184 | 185 | HV_p_LA = largeMallocLocal(yGrid * sizeof(bool*)); 186 | HV_p = reinterpret_cast(HV_p_LA.get()); 187 | hyperV_p_LA = largeMallocLocal(yGrid * sizeof(bool*)); 188 | hyperV_p = reinterpret_cast(hyperV_p_LA.get()); 189 | hyperH_p_LA = largeMallocLocal(yGrid * sizeof(bool*)); 190 | hyperH_p = reinterpret_cast(hyperH_p_LA.get()); 191 | 192 | parentX1_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(short)); 193 | parentX1_alloc = reinterpret_cast(parentX1_alloc_LA.get()); 194 | parentX3_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(short)); 195 | parentX3_alloc = reinterpret_cast(parentX3_alloc_LA.get()); 196 | parentY1_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(short)); 197 | parentY1_alloc = reinterpret_cast(parentY1_alloc_LA.get()); 198 | parentY3_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(short)); 199 | parentY3_alloc = reinterpret_cast(parentY1_alloc_LA.get()); 200 | 201 | parentX1_p_LA = largeMallocLocal(yGrid * sizeof(short*)); 202 | parentX1_p = reinterpret_cast(parentX1_p_LA.get()); 203 | parentX3_p_LA = largeMallocLocal(yGrid * sizeof(short*)); 204 | parentX3_p = reinterpret_cast(parentX3_p_LA.get()); 205 | parentY1_p_LA = largeMallocLocal(yGrid * sizeof(short*)); 206 | parentY1_p = reinterpret_cast(parentY1_p_LA.get()); 207 | parentY3_p_LA = largeMallocLocal(yGrid * sizeof(short*)); 208 | parentY3_p = reinterpret_cast(parentY3_p_LA.get()); 209 | 210 | corrEdge_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(int)); 211 | corrEdge_alloc = reinterpret_cast(corrEdge_alloc_LA.get()); 212 | corrEdge_p_LA = largeMallocLocal(yGrid * sizeof(int*)); 213 | corrEdge_p = reinterpret_cast(corrEdge_p_LA.get()); 214 | 215 | inRegion_alloc_LA = largeMallocLocal(yGrid * xGrid * sizeof(bool)); 216 | inRegion_alloc = reinterpret_cast(inRegion_alloc_LA.get()); 217 | inRegion_p_LA = largeMallocLocal(yGrid * sizeof(bool*)); 218 | inRegion_p = reinterpret_cast(inRegion_p_LA.get()); 219 | 220 | netEO_p_LA = largeMallocLocal(MAXNETDEG * 2 * sizeof(OrderNetEdge)); 221 | netEO_p = reinterpret_cast(netEO_p_LA.get()); 222 | 223 | 224 | } else { 225 | pop_heap2 = (bool*)calloc(yGrid * xGrid, sizeof(bool)); 226 | 227 | d1_alloc = (float*)calloc(yGrid * xGrid, sizeof(float)); 228 | d1_p = (float**)calloc(yGrid, sizeof(float*)); 229 | 230 | HV_alloc = (bool*)calloc(yGrid * xGrid, sizeof(bool)); 231 | hyperV_alloc = (bool*)calloc(yGrid * xGrid, sizeof(bool)); 232 | hyperH_alloc = (bool*)calloc(yGrid * xGrid, sizeof(bool)); 233 | HV_p = (bool**)calloc(yGrid, sizeof(bool*)); 234 | hyperV_p = (bool**)calloc(yGrid, sizeof(bool*)); 235 | hyperH_p = (bool**)calloc(yGrid, sizeof(bool*)); 236 | 237 | parentX1_alloc = (short*)calloc(yGrid * xGrid, sizeof(short)); 238 | parentX3_alloc = (short*)calloc(yGrid * xGrid, sizeof(short)); 239 | parentY1_alloc = (short*)calloc(yGrid * xGrid, sizeof(short)); 240 | parentY3_alloc = (short*)calloc(yGrid * xGrid, sizeof(short)); 241 | parentX1_p = (short**)calloc(yGrid, sizeof(short*)); 242 | parentX3_p = (short**)calloc(yGrid, sizeof(short*)); 243 | parentY1_p = (short**)calloc(yGrid, sizeof(short*)); 244 | parentY3_p = (short**)calloc(yGrid, sizeof(short*)); 245 | 246 | corrEdge_alloc = (int*)calloc(yGrid * xGrid, sizeof(int)); 247 | corrEdge_p = (int**)calloc(yGrid, sizeof(int*)); 248 | 249 | inRegion_alloc = (bool*)calloc(yGrid * xGrid, sizeof(bool)); 250 | inRegion_p = (bool**)calloc(yGrid, sizeof(bool*)); 251 | 252 | netEO_p = (OrderNetEdge*)calloc(MAXNETDEG * 2, sizeof(OrderNetEdge)); 253 | 254 | v_local_usage = (int*)calloc(xGrid * (yGrid - 1), sizeof(int)); 255 | h_local_usage = (int*)calloc((xGrid - 1) * yGrid, sizeof(int)); 256 | } 257 | // printf("allocation success\n"); 258 | for (int i = 0; i < yGrid; i++) { 259 | d1_p[i] = &(d1_alloc[i * xGrid]); 260 | 261 | HV_p[i] = &(HV_alloc[i * xGrid]); 262 | hyperV_p[i] = &(hyperV_alloc[i * xGrid]); 263 | hyperH_p[i] = &(hyperH_alloc[i * xGrid]); 264 | 265 | corrEdge_p[i] = &(corrEdge_alloc[i * xGrid]); 266 | 267 | inRegion_p[i] = &(inRegion_alloc[i * xGrid]); 268 | } 269 | 270 | for (int i = 0; i < yGrid; i++) { 271 | parentX1_p[i] = &(parentX1_alloc[i * xGrid]); 272 | parentX3_p[i] = &(parentX3_alloc[i * xGrid]); 273 | parentY1_p[i] = &(parentY1_alloc[i * xGrid]); 274 | parentY3_p[i] = &(parentY3_alloc[i * xGrid]); 275 | } 276 | } 277 | void reset_heap() { memset(pop_heap2, 0, yGrid * xGrid * sizeof(bool)); } 278 | 279 | ~THREAD_LOCAL_STORAGE() { 280 | free(pop_heap2); 281 | 282 | free(d1_p); 283 | free(d1_alloc); 284 | 285 | free(HV_p); 286 | free(hyperV_p); 287 | free(hyperH_p); 288 | free(HV_alloc); 289 | free(hyperV_alloc); 290 | free(hyperH_alloc); 291 | 292 | free(parentX1_p); 293 | free(parentY1_p); 294 | free(parentX3_p); 295 | free(parentY3_p); 296 | 297 | free(parentX1_alloc); 298 | free(parentY1_alloc); 299 | free(parentX3_alloc); 300 | free(parentY3_alloc); 301 | 302 | free(corrEdge_alloc); 303 | free(corrEdge_p); 304 | 305 | free(inRegion_alloc); 306 | free(inRegion_p); 307 | 308 | free(netEO_p); 309 | 310 | free(h_local_usage); 311 | free(v_local_usage); 312 | } 313 | }; 314 | 315 | void convertToMazerouteNet(int netID); 316 | 317 | void convertToMazeroute(); 318 | 319 | // non recursive version of heapify 320 | void heapify(float** array, int heapSize, int i); 321 | // build heap for an list of grid 322 | /*void buildHeap(float **array, int arrayLen) 323 | { 324 | int i; 325 | 326 | for (i=arrayLen/2-1; i>=0; i--) 327 | heapify(array, arrayLen, i); 328 | }*/ 329 | 330 | void updateHeap(float** array, int i); 331 | 332 | // extract the entry with minimum distance from Priority queue 333 | void extractMin(float** array, int arrayLen); 334 | /* 335 | * num_iteration : the total number of iterations for maze route to run 336 | * round : the number of maze route stages runned 337 | */ 338 | 339 | void updateCongestionHistory(int upType); 340 | 341 | // ripup a tree edge according to its ripup type and Z-route it 342 | // put all the nodes in the subtree t1 and t2 into heap1 and heap2 343 | // netID - the ID for the net 344 | // edgeID - the ID for the tree edge to route 345 | // d1 - the distance of any grid from the source subtree t1 346 | // d2 - the distance of any grid from the destination subtree t2 347 | // heap1 - the heap storing the addresses for d1[][] 348 | // heap2 - the heap storing the addresses for d2[][] 349 | void setupHeap(int netID, int edgeID, local_pq& pq1, local_vec& v2, 350 | int regionX1, int regionX2, int regionY1, int regionY2, 351 | float** d1, int** corrEdge, bool** inRegion); 352 | 353 | int copyGrids(TreeNode* treenodes, int n1, TreeEdge* treeedges, int edge_n1n2, 354 | int* gridsX_n1n2, int* gridsY_n1n2); 355 | 356 | void updateRouteType1(TreeNode* treenodes, int n1, int A1, int A2, int E1x, 357 | int E1y, TreeEdge* treeedges, int edge_n1A1, 358 | int edge_n1A2); 359 | 360 | void updateRouteType2(TreeNode* treenodes, int n1, int A1, int A2, int C1, 361 | int C2, int E1x, int E1y, TreeEdge* treeedges, 362 | int edge_n1A1, int edge_n1A2, int edge_C1C2); 363 | 364 | void reInitTree(int netID); 365 | 366 | int getOverflow2Dmaze(int* maxOverflow, int* tUsage, bool after_maze = true); 367 | void checkUsageCorrectness(); 368 | 369 | int getOverflow2D(int* maxOverflow); 370 | int getOverflow3D(void); 371 | 372 | void InitEstUsage(); 373 | 374 | void str_accu(int rnd); 375 | 376 | void InitLastUsage(int upType); 377 | 378 | } //namespace sproute 379 | 380 | #endif 381 | -------------------------------------------------------------------------------- /include/memAlloc.h: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Public domain memory allocation and de-allocation routine header file. 3 | Taken from Appendix B of: 4 | Numerical Recipes in C: The Art of Scientific Computing, Second Edition, 5 | Cambridge University Press, 1992 6 | ----------------------------------------------------------------------------*/ 7 | #ifndef _MEMALLOC_H_ 8 | #define _MEMALLOC_H_ 9 | 10 | static float sqrarg; 11 | #define SQR(a) ((sqrarg = (a)) == 0.0 ? 0.0 : sqrarg * sqrarg) 12 | 13 | static double dsqrarg; 14 | #define DSQR(a) ((dsqrarg = (a)) == 0.0 ? 0.0 : dsqrarg * dsqrarg) 15 | 16 | static double dmaxarg1, dmaxarg2; 17 | #define DMAX(a, b) \ 18 | (dmaxarg1 = (a), dmaxarg2 = (b), \ 19 | (dmaxarg1) > (dmaxarg2) ? (dmaxarg1) : (dmaxarg2)) 20 | 21 | static double dminarg1, dminarg2; 22 | #define DMIN(a, b) \ 23 | (dminarg1 = (a), dminarg2 = (b), \ 24 | (dminarg1) < (dminarg2) ? (dminarg1) : (dminarg2)) 25 | 26 | static float maxarg1, maxarg2; 27 | #define FMAX(a, b) \ 28 | (maxarg1 = (a), maxarg2 = (b), (maxarg1) > (maxarg2) ? (maxarg1) : (maxarg2)) 29 | 30 | static float minarg1, minarg2; 31 | #define FMIN(a, b) \ 32 | (minarg1 = (a), minarg2 = (b), (minarg1) < (minarg2) ? (minarg1) : (minarg2)) 33 | 34 | static long lmaxarg1, lmaxarg2; 35 | #define LMAX(a, b) \ 36 | (lmaxarg1 = (a), lmaxarg2 = (b), \ 37 | (lmaxarg1) > (lmaxarg2) ? (lmaxarg1) : (lmaxarg2)) 38 | 39 | static long lminarg1, lminarg2; 40 | #define LMIN(a, b) \ 41 | (lminarg1 = (a), lminarg2 = (b), \ 42 | (lminarg1) < (lminarg2) ? (lminarg1) : (lminarg2)) 43 | 44 | static int imaxarg1, imaxarg2; 45 | #define IMAX(a, b) \ 46 | (imaxarg1 = (a), imaxarg2 = (b), \ 47 | (imaxarg1) > (imaxarg2) ? (imaxarg1) : (imaxarg2)) 48 | 49 | static int iminarg1, iminarg2; 50 | #define IMIN(a, b) \ 51 | (iminarg1 = (a), iminarg2 = (b), \ 52 | (iminarg1) < (iminarg2) ? (iminarg1) : (iminarg2)) 53 | 54 | #define SIGN(a, b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) 55 | 56 | void runTimeError(char error_text[]); 57 | float* vector(long nl, long nh); 58 | int* ivector(long nl, long nh); 59 | unsigned char* cvector(long nl, long nh); 60 | unsigned long* lvector(long nl, long nh); 61 | double* dvector(long nl, long nh); 62 | float** matrix(long nrl, long nrh, long ncl, long nch); 63 | double** dmatrix(long nrl, long nrh, long ncl, long nch); 64 | int** imatrix(long nrl, long nrh, long ncl, long nch); 65 | char** cmatrix(long nrl, long nrh, long ncl, long nch); 66 | unsigned long** lmatrix(long nrl, long nrh, long ncl, long nch); 67 | float** submatrix(float** a, long oldrl, long oldrh, long oldcl, long oldch, 68 | long newrl, long newcl); 69 | float** convert_matrix(float* a, long nrl, long nrh, long ncl, long nch); 70 | float*** f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); 71 | unsigned long*** lmatrix3D(long nrl, long nrh, long ncl, long nch, long ndl, 72 | long ndh); 73 | int*** imatrix3D(int nrl, int nrh, int ncl, int nch, int ndl, int ndh); 74 | 75 | void free_vector(float* v, long nl, long nh); 76 | void free_ivector(int* v, long nl, long nh); 77 | void free_cvector(unsigned char* v, long nl, long nh); 78 | void free_lvector(unsigned long* v, long nl, long nh); 79 | void free_dvector(double* v, long nl, long nh); 80 | void free_matrix(float** m, long nrl, long nrh, long ncl, long nch); 81 | void free_dmatrix(double** m, long nrl, long nrh, long ncl, long nch); 82 | void free_imatrix(int** m, long nrl, long nrh, long ncl, long nch); 83 | void free_cmatrix(char** m, long nrl, long nrh, long ncl, long nch); 84 | void free_lmatrix(unsigned long** m, long nrl, long nrh, long ncl, long nch); 85 | void free_submatrix(float** b, long nrl, long nrh, long ncl, long nch); 86 | void free_convert_matrix(float** b, long nrl, long nrh, long ncl, long nch); 87 | void free_f3tensor(float*** t, long nrl, long nrh, long ncl, long nch, long ndl, 88 | long ndh); 89 | void free_lmatrix3D(unsigned long*** t, long nrl, long nrh, long ncl, long nch, 90 | long ndl, long ndh); 91 | void free_imatrix3D(int*** t, int nrl, int nrh, int ncl, int nch, int ndl, 92 | int ndh); 93 | 94 | #endif /* _MEMALLOC_H_ */ 95 | -------------------------------------------------------------------------------- /include/mst2.h: -------------------------------------------------------------------------------- 1 | #ifndef _MST2_H_ 2 | #define _MST2_H_ 3 | 4 | #include "fr_global.h" 5 | 6 | void mst2_package_init(long n); 7 | void mst2_package_done(); 8 | void mst2(long n, Point* pt, long* parent); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/neighbors.h: -------------------------------------------------------------------------------- 1 | #include "fr_global.h" 2 | 3 | void allocate_nn_arrays(long n); 4 | void deallocate_nn_arrays(); 5 | 6 | void brute_force_nearest_neighbors(long n, Point* pt, nn_array* nn); 7 | 8 | void dq_nearest_neighbors(long n, Point* pt, nn_array* nn); 9 | -------------------------------------------------------------------------------- /include/ripup.h: -------------------------------------------------------------------------------- 1 | #ifndef _RIPUP_H_ 2 | #define _RIPUP_H_ 3 | 4 | #include "DataType.h" 5 | #include "utility.h" 6 | 7 | namespace sproute { 8 | // rip-up a L segment 9 | void ripupSegL(Segment* seg); 10 | 11 | void ripupSegZ(Segment* seg); 12 | 13 | void newRipup(TreeEdge* treeedge, int x1, int y1, int x2, int y2); 14 | 15 | bool newRipupType2(TreeEdge* treeedge, TreeNode* treenodes, int x1, int y1, 16 | int x2, int y2, int deg); 17 | 18 | void printEdgeVEC(TreeEdge* treeedge); 19 | 20 | bool newRipupCheckProb(TreeEdge* treeedge, int ripup_threshold, int netID, 21 | int edgeID); 22 | 23 | bool newRipupCheck(TreeEdge* treeedge, int ripup_threshold, int netID, 24 | int edgeID); 25 | 26 | bool newRipupCheck_atomic(TreeEdge* treeedge, int ripup_threshold, int netID, 27 | int edgeID); 28 | 29 | bool newRipupCheck_sort(TreeEdge* treeedge, int ripup_threshold, int netID, 30 | int edgeID, bool& is_horizontal, int& grid_pos); 31 | 32 | bool newRipupCheck_nosub(TreeEdge* treeedge, int ripup_threshold, int netID, 33 | int edgeID); 34 | bool newRipup3DType3(int netID, int edgeID); 35 | 36 | void newRipupNet(int netID); 37 | }// namespace sproute 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/route.h: -------------------------------------------------------------------------------- 1 | #ifndef _ROUTE_H_ 2 | #define _ROUTE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "DataType.h" 9 | #include "flute.h" 10 | #include "DataProc.h" 11 | #include "ripup.h" 12 | #include "global_variable_extern.h" 13 | 14 | namespace sproute { 15 | 16 | #define SAMEX 0 17 | #define SAMEY 1 18 | 19 | extern float costHVH[XRANGE]; // Horizontal first Z 20 | extern float costVHV[YRANGE]; // Vertical first Z 21 | extern float costH[YRANGE]; // Horizontal segment cost 22 | extern float costV[XRANGE]; // Vertical segment cost 23 | extern float costLR[YRANGE]; // Left and right boundary cost 24 | extern float costTB[XRANGE]; // Top and bottom boundary cost 25 | 26 | extern float costHVHtest[YRANGE]; // Vertical first Z 27 | extern float costVtest[XRANGE]; // Vertical segment cost 28 | extern float costTBtest[XRANGE]; // Top and bottom boundary cost 29 | 30 | #define HCOST 5000; 31 | 32 | // estimate the routing by assigning 1 for H and V segments, 0.5 to both 33 | // possible L for L segments 34 | void estimateOneSeg(Segment* seg); 35 | 36 | void routeSegV(Segment* seg); 37 | // L-route, based on previous L route 38 | void routeSegL(Segment* seg); 39 | // First time L-route, based on 0.5-0.5 estimation 40 | void routeSegLFirstTime(Segment* seg); 41 | // route all segments with L, firstTime: true, no previous route, false - 42 | // previous is L-route 43 | void routeLAll(bool firstTime); 44 | // L-route, rip-up the previous route according to the ripuptype 45 | // L-route, rip-up the previous route according to the ripuptype 46 | void newrouteL(int netID, RouteType ripuptype, bool viaGuided); 47 | 48 | // route all segments with L, firstTime: true, first newrouteLAll, false - not 49 | // first 50 | void newrouteLAll(bool firstTime, bool viaGuided); 51 | 52 | void newrouteZ_edge(int netID, int edgeID); 53 | // Z-route, rip-up the previous route according to the ripuptype 54 | void newrouteZ(int netID, int threshold); 55 | // ripup a tree edge according to its ripup type and Z-route it 56 | // route all segments with L, firstTime: true, first newrouteLAll, false - not 57 | // first 58 | void newrouteZAll(int threshold); 59 | 60 | // Ripup the original route and do Monotonic routing within bounding box 61 | void routeMonotonic(int netID, int edgeID, int threshold); 62 | void routeMonotonicAll(int threshold); 63 | 64 | void spiralRoute(int netID, int edgeID); 65 | void spiralRouteAll(); 66 | void routeLVEnew(int netID, int edgeID, int threshold, int enlarge); 67 | void routeLVAll(int threshold, int expand); 68 | void newrouteLInMaze(int netID); 69 | 70 | } //namespace sproute 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/setup_heap.h: -------------------------------------------------------------------------------- 1 | #ifndef SETUP_HEAP_H 2 | #define SETUP_HEAP_H 3 | 4 | #include 5 | #include "galois/LargeArray.h" 6 | #include "a_star.h" 7 | 8 | namespace sproute { 9 | 10 | void setupHeap_astar_swap(int netID, int edgeID, astar_local_pq& pq1, local_vec& v2, 11 | int regionX1, int regionX2, int regionY1, int regionY2, 12 | float** d1, int** corrEdge, bool** inRegion, float astar_weight); 13 | 14 | 15 | void setupHeap_steiner(int netID, int edgeID, astar_local_pq& pq1, local_vec& v2, 16 | int regionX1, int regionX2, int regionY1, int regionY2, 17 | float** d1, int** corrEdge, bool** inRegion, float astar_weight); 18 | 19 | } //namespace sproute 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/soft_cap.h: -------------------------------------------------------------------------------- 1 | #ifndef SOFT_CAP_H 2 | #define SOFT_CAP_H 3 | 4 | #define OBS_NO_STOP 0 // 1 == go through OBS, 0 == hard stop 5 | 6 | #define GLOBAL_CAP_REDUCTION 4 7 | #define CAP_ADJ_FACTOR 1.0 8 | 9 | #define M2_ADJ_MIN 0.45 10 | #define M2_ADJ_MAX 0.9 11 | #define M2_ADJ_MID 3.5 12 | #define M2_ADJ_K 2.0 13 | 14 | #define M3_ADJ_MIN 0.45 15 | #define M3_ADJ_MAX 0.9 16 | #define M3_ADJ_MID 3.5 17 | #define M3_ADJ_K 2.0 18 | 19 | #define MID_ADJ_MIN 0.9 20 | #define MID_ADJ_MAX 0.9 21 | #define MID_ADJ_MID 5.0 22 | #define MID_ADJ_K 2.0 23 | 24 | #define HIGH_ADJ 0.7 25 | 26 | #define DEFAULT_RUDY_WEIGHT 0.1 27 | #define DEFAULT_PIN_DENSITY_WEIGHT 1.0 28 | 29 | #define SMALL_NET_THRSHD 30 // small nets are filtered out in first iteration 30 | 31 | int GLOBAL_CAP_ADJ(int x, float rudy, int layerID); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/sproute.h: -------------------------------------------------------------------------------- 1 | #ifndef SPROUTE_H 2 | #define SPROUTE_H 3 | 4 | 5 | #include "defDataBase.h" 6 | #include "lefDataBase.h" 7 | #include "grGen.h" 8 | #include "algo.h" 9 | #include "maze.h" 10 | #include "verbose.h" 11 | 12 | #include "galois/LargeArray.h" 13 | #include 14 | 15 | namespace sproute { 16 | 17 | class SPRoute { 18 | private: 19 | phydb::PhyDB* db_ptr_; 20 | 21 | sproute_db::defDataBase defDB; 22 | sproute_db::lefDataBase lefDB; 23 | 24 | sproute_db::grGenerator grGen; 25 | galois::InsertBag capReductions; 26 | 27 | Algo algo; 28 | 29 | int acc_count; 30 | int numThreads; 31 | int max_iteration; 32 | 33 | int n_small_undone; 34 | float max_rudy; 35 | 36 | int verbose_ = 0; 37 | bool double_patch_guide_ = true; 38 | 39 | void LinkTrackToLayer(); 40 | void PreprocessSpacingTable(); 41 | void PreprocessComponent(); 42 | void InitGcell(); 43 | 44 | void PreprocessSNet(); 45 | 46 | void PreprocessDesignRule(); 47 | void PreprocessDesignRuleOBS(); 48 | void AdjustGcellCap(); 49 | void InitGrGen(); 50 | 51 | void ComputePinLocation(sproute_db::Component& component); 52 | void ComputeOBSLocation(sproute_db::Component& component); 53 | void GenerateGcellGrid(); 54 | void UpdateGcellGrid(int xstep, int ystep); 55 | void GcellInsertOBS(int x, int y, int z, sproute_db::Rect2D rect, int OBSIdx); 56 | 57 | sproute_db::Range GetTrackRange(int layerIdx, sproute_db::Rect2D rect, bool expand); 58 | sproute_db::Range GetTrackRange(int layerIdx, sproute_db::Rect2D rect, bool expand); 59 | 60 | sproute_db::Range RangeIntersection(sproute_db::Range r1, sproute_db::Range r2); 61 | sproute_db::Range RangeIntersection(sproute_db::Range r1, sproute_db::Range r2); 62 | 63 | void LoadPhyDB(phydb::PhyDB* p); 64 | void LoadPhyDBToLefDB(); 65 | void LoadPhyDBToDefDB(); 66 | 67 | void LoadPhyDBMacros(); 68 | void LoadPhyDBLefVias(); 69 | void LoadPhyDBLayers(); 70 | 71 | void LoadPhyDBDieArea(); 72 | void LoadPhyDBComponents(); 73 | void LoadPhyDBTracks(); 74 | void LoadPhyDBIOPins(); 75 | void LoadPhyDBSNets(); 76 | void LoadPhyDBNets(); 77 | void LoadPhyDBGcellGrids(); 78 | void LoadPhyDBDefVias(); 79 | 80 | void WriteGuideToPhydb(); 81 | void WriteGcellGridToPhydb(); 82 | void WriteRoutedGridToPhydb(int netID, std::set& routedGrid); 83 | 84 | void WriteGuideToFile(string guideFileName); 85 | void WriteRoutedGrid(FILE* fp, std::set>& routedGrid); 86 | void WriteOverflow(string overflowFile); 87 | 88 | int InvalidNetsAdjLayer(int x, int y, int l, int xGrid, int yGrid); 89 | void InvalidNetsAdj(Net** invalid_nets, int xGrid, int yGrid); 90 | 91 | void MemPinAdj(int xGrid, int yGrid); 92 | 93 | void ReadGR(sproute_db::grGenerator& grGen, Algo algo); 94 | void RunGlobalRoute(string OutFileName, int maxMazeRound = 500, Algo algo = Algo::NonDet); 95 | 96 | void mazeRouteMSMD(int iter, int expand, float costHeight, int ripup_threshold, 97 | int mazeedge_Threshold, bool Ordering, int cost_type, galois::LargeArray& done, 98 | galois::substrate::PerThreadStorage& thread_local_storage); 99 | 100 | void mazeRouteMSMDDetPart_Astar_Local(int iter, int expand, float costHeight, 101 | int ripup_threshold, int mazeedge_Threshold, 102 | bool Ordering, int cost_type, int parts, 103 | std::vector>& vecParts, galois::LargeArray &done, 104 | galois::substrate::PerThreadStorage& thread_local_storage); 105 | 106 | void mazeRouteMSMD_astar(int iter, int expand, float costHeight, int ripup_threshold, 107 | int mazeedge_Threshold, bool Ordering, int cost_type, float astar_weight, galois::LargeArray& done); 108 | 109 | float ComputeRudy(float* rudy, Algo algo); 110 | float ComputePinDensity(float* pin_density, Algo algo); 111 | void PlotDrcMap(); 112 | void UndoneFilter(galois::LargeArray &done, bool small_filter = false); 113 | void RUDY_scheduler(int iter, int max_overflow, int counted_num_part, std::vector>& vecParts, galois::LargeArray &done); 114 | 115 | void gen_brk_RSMT(bool congestionDriven, bool reRoute, bool genTree, bool newType, bool noADJ); 116 | int getOverflow2D(int* maxOverflow); 117 | int getOverflow2Dmaze(int* maxOverflow, int* tUsage, bool after_maze = false); 118 | int getOverflow3D(); 119 | void copyBR(); 120 | void fillVIA(); 121 | void newLA(); 122 | void newLayerAssignmentV4(); 123 | void checkUsage(); 124 | bool checkIfDone(TreeEdge* treeedge); 125 | int UndoneNetOrderX(galois::LargeArray &done); 126 | int UndoneNetOrderY(galois::LargeArray &done); 127 | void RCEstimate(); 128 | void updateCongestionHistory(int upType); 129 | void routeLVAll(int threshold, int expand); 130 | 131 | public: 132 | ~SPRoute() {} 133 | SPRoute() { 134 | acc_count = 0; 135 | max_iteration = 30; 136 | numThreads = 1; 137 | algo = Det; 138 | 139 | galois::preAlloc(numThreads * 2); 140 | galois::setActiveThreads(numThreads); 141 | } 142 | 143 | SPRoute(phydb::PhyDB* p) { 144 | this->LoadPhyDB(p); 145 | acc_count = 0; 146 | max_iteration = 30; 147 | numThreads = 1; 148 | algo = Det; 149 | 150 | galois::preAlloc(numThreads * 2); 151 | galois::setActiveThreads(numThreads); 152 | } 153 | 154 | SPRoute(phydb::PhyDB* p, int v) { 155 | this->LoadPhyDB(p); 156 | acc_count = 0; 157 | max_iteration = 30; 158 | numThreads = 1; 159 | algo = Det; 160 | verbose_ = v; 161 | 162 | galois::preAlloc(numThreads * 2); 163 | galois::setActiveThreads(numThreads); 164 | } 165 | 166 | SPRoute(phydb::PhyDB* p, int numT, std::string algo_str) { 167 | this->LoadPhyDB(p); 168 | acc_count = 0; 169 | max_iteration = 30; 170 | numThreads = numT; 171 | algo = sproute::StrToAlgo(algo_str); 172 | verbose_ = 0; 173 | 174 | galois::preAlloc(numThreads * 2); 175 | galois::setActiveThreads(numThreads); 176 | } 177 | 178 | void SetDoublePatchGuide(int double_patch) { 179 | double_patch_guide_ = double_patch; 180 | } 181 | 182 | void SetAlgo(std::string algo_str) { 183 | algo = sproute::StrToAlgo(algo_str); 184 | } 185 | 186 | void SetNumThreads(int numT) { 187 | numThreads = numT; 188 | } 189 | 190 | void SetMaxIteration(int max_iter) { 191 | max_iteration = max_iter; 192 | } 193 | 194 | void Run(); 195 | 196 | 197 | }; 198 | 199 | 200 | } //namespace sproute 201 | 202 | 203 | #endif -------------------------------------------------------------------------------- /include/sprouteDataType.h: -------------------------------------------------------------------------------- 1 | #ifndef SPROUTE_DATATYPE_H 2 | #define SPROUTE_DATATYPE_H 3 | 4 | #include "header.h" 5 | 6 | namespace sproute_db 7 | { 8 | 9 | template 10 | class Point2D 11 | { 12 | public: 13 | T x; 14 | T y; 15 | Point2D() { 16 | x = 0; 17 | y = 0; 18 | } 19 | Point2D(T x, T y): x(x), y(y) { } 20 | bool empty() 21 | { 22 | return ((x == 0) && (y == 0)); 23 | } 24 | void set(T x_new, T y_new) 25 | { 26 | this->x = x_new; 27 | this->y = y_new; 28 | } 29 | void clear() 30 | { 31 | x = 0; 32 | y = 0; 33 | } 34 | void reset() 35 | { 36 | x = 0; 37 | y = 0; 38 | } 39 | void print() 40 | { 41 | cout << x << " " << y << endl; 42 | } 43 | bool operator< (const Point2D p) const 44 | { 45 | if(x < p.x) 46 | return true; 47 | else if(x > p.x) 48 | return false; 49 | else 50 | return (y < p.y); 51 | } 52 | bool operator> (const Point2D p) const 53 | { 54 | if(x > p.x) 55 | return true; 56 | else if(x < p.x) 57 | return false; 58 | else 59 | return (y > p.y); 60 | } 61 | 62 | }; 63 | 64 | template 65 | using Size2D = Point2D; 66 | 67 | template 68 | class Point3D 69 | { 70 | public: 71 | T x; 72 | T y; 73 | int z; 74 | Point3D() { } 75 | Point3D(T x, T y, int z): x(x), y(y), z(z) { } 76 | void set(T x_new, T y_new, int z_new) 77 | { 78 | this->x = x_new; 79 | this->y = y_new; 80 | this->z = z_new; 81 | } 82 | void print() 83 | { 84 | cout << x << " " << y << " " << z << endl; 85 | } 86 | 87 | bool operator< (const Point3D p) const 88 | { 89 | if(Point2D(x, y) < Point2D(p.x, p.y)) 90 | return true; 91 | else if(Point2D(x, y) > Point2D(p.x, p.y)) 92 | return false; 93 | else 94 | { 95 | return (z < p.z); 96 | } 97 | } 98 | 99 | bool operator> (const Point3D p) const 100 | { 101 | if(Point2D(x, y) > Point2D(p.x, p.y)) 102 | return true; 103 | else if(Point2D(x, y) < Point2D(p.x, p.y)) 104 | return false; 105 | else 106 | { 107 | return (z > p.z); 108 | } 109 | } 110 | 111 | }; 112 | 113 | template 114 | class Rect2D 115 | { 116 | public: 117 | Point2D lowerLeft; 118 | Point2D upperRight; 119 | Rect2D() { } 120 | Rect2D(Point2D lowerLeft, Point2D upperRight): lowerLeft(lowerLeft), upperRight(upperRight) { } 121 | Rect2D(T llx, T lly, T urx, T ury): lowerLeft(llx, lly), upperRight(urx, ury) { } 122 | bool empty() 123 | { 124 | return (lowerLeft.empty() && upperRight.empty()); 125 | } 126 | void set(T llx, T lly, T urx, T ury) 127 | { 128 | lowerLeft.set(llx, lly); 129 | upperRight.set(urx, ury); 130 | } 131 | void print() 132 | { 133 | cout << "rect: " ; 134 | lowerLeft.print(); 135 | upperRight.print(); 136 | } 137 | bool cover(Point2D p) 138 | { 139 | return (lowerLeft.x <= p.x && lowerLeft.y <= p.y && upperRight.x >= p.x && upperRight.y >= p.y); 140 | } 141 | }; 142 | 143 | template 144 | class Rect2DLayer : public Rect2D 145 | { 146 | public: 147 | string layer; 148 | Rect2DLayer(): Rect2D() {} 149 | void set(string layer, T llx, T lly, T urx, T ury) 150 | { 151 | this->layer = layer; 152 | this->lowerLeft.set(llx, lly); 153 | this->upperRight.set(urx, ury); 154 | } 155 | }; 156 | 157 | 158 | 159 | template 160 | class Rect3D 161 | { 162 | public: 163 | Point3D lowerLeft; 164 | Point3D upperRight; 165 | Rect3D() { } 166 | Rect3D(T llx, T lly, int llz, T urx, T ury, int urz): lowerLeft(llx, lly, llz), upperRight(urx, ury, urz) { } 167 | void set(T llx, T lly, int llz, T urx, T ury, int urz) 168 | { 169 | lowerLeft.set(llx, lly, llz); 170 | upperRight.set(urx, ury, urz); 171 | } 172 | void print() 173 | { 174 | lowerLeft.print(); 175 | upperRight.print(); 176 | } 177 | }; 178 | 179 | template 180 | class Range 181 | { 182 | public: 183 | T start; 184 | T end; 185 | Range() { } 186 | Range(T s, T e) { 187 | start = s; 188 | end = e; 189 | } 190 | }; 191 | 192 | 193 | 194 | template 195 | std::ostream& operator<< (std::ostream& os, const Point2D &p) { 196 | std::cout << " ( " << p.x << ", " << p.y << ") "; 197 | return os; 198 | } 199 | 200 | template 201 | std::ostream& operator<< (std::ostream& os, const Rect2D &r) { 202 | std::cout << "Rect: "; 203 | std::cout << r.lowerLeft << r.upperRight; 204 | return os; 205 | } 206 | 207 | } 208 | 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /include/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILITY_H_ 2 | #define _UTILITY_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "DataType.h" 8 | #include "flute.h" 9 | #include "DataProc.h" 10 | #include "global_variable_extern.h" 11 | 12 | namespace sproute { 13 | 14 | void printEdge(int netID, int edgeID); 15 | void plotTree(int netID); 16 | void getlen(); 17 | void ConvertToFull3DType2 (); 18 | 19 | static int comparePVMINX (const void *a, const void *b) 20 | { 21 | if (((OrderNetPin*)a)->minX > ((OrderNetPin*)b)->minX) return 1; 22 | else if (((OrderNetPin*)a)->minX == ((OrderNetPin*)b)->minX) return 0; 23 | else return -1; 24 | } 25 | 26 | static int comparePVPV (const void *a, const void *b) 27 | { 28 | if (((OrderNetPin*)a)->npv > ((OrderNetPin*)b)->npv) return 1; 29 | else if (((OrderNetPin*)a)->npv == ((OrderNetPin*)b)->npv) return 0; 30 | else return -1; 31 | } 32 | 33 | void netpinOrderInc(); 34 | void fillVIA(); 35 | int threeDVIA(); 36 | void assignEdge(int netID, int edgeID, bool processDIR); 37 | void newLayerAssignmentV4(); 38 | int findLayer(int netID, TreeNode treenode); 39 | void newLA (); 40 | void printEdge3D(int netID, int edgeID); 41 | 42 | void printTree3D(int netID); 43 | void checkRoute3D(); 44 | void write3D(); 45 | 46 | static int compareTEL (const void *a, const void *b) 47 | { 48 | if (((OrderTree*)a)->xmin < ((OrderTree*)b)->xmin) return 1; 49 | else if (((OrderTree*)a)->xmin == ((OrderTree*)b)->xmin) { 50 | if(a < b) 51 | return 1; 52 | else if(a > b) 53 | return -1; 54 | else { 55 | cout << "same pointer: error!" << endl; 56 | exit(1); 57 | } 58 | } //TODO: use this after fixing bug of ispd19_test8_metal5 59 | else return -1; 60 | } 61 | 62 | void StNetOrder(); 63 | void recoverEdge(int netID, int edgeID); 64 | void checkUsage(); 65 | 66 | static int compareEdgeLen (const void *a, const void *b) 67 | { 68 | if (((OrderNetEdge*)a)->length < ((OrderNetEdge*)b)->length) return 1; 69 | else if (((OrderNetEdge*)a)->length == ((OrderNetEdge*)b)->length) { 70 | if(a < b) 71 | return 1; 72 | else if(a > b) 73 | return -1; 74 | else { 75 | cout << "ERROR: two same edge pointer! " << endl; 76 | exit(1); 77 | } 78 | 79 | } 80 | else return -1; 81 | } 82 | 83 | 84 | 85 | void netedgeOrderDec(int netID, OrderNetEdge* netEO); 86 | void printEdge2D(int netID, int edgeID); 87 | void printTree2D(int netID); 88 | bool checkRoute2DTree(int netID); 89 | 90 | 91 | struct TD{ 92 | int id; 93 | float cost; 94 | }; 95 | 96 | struct BBox{ 97 | int xmin; 98 | int ymin; 99 | int xmax; 100 | int ymax; 101 | int hSpan; 102 | int vSpan; 103 | };//lower_left corner and upper_right corner 104 | 105 | 106 | 107 | struct wire 108 | { 109 | int x1,y1,x2,y2; 110 | int netID; 111 | }; 112 | 113 | 114 | static int ordercost(const void *a, const void *b) 115 | { 116 | struct TD *pa, *pb; 117 | 118 | pa = *(struct TD**)a; 119 | pb = *(struct TD**)b; 120 | 121 | if (pa->cost < pb->cost) return 1; 122 | if (pa->cost > pb->cost) return -1; 123 | return 0; 124 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 125 | }//decreasing order 126 | 127 | static int ordervSpan(const void *a, const void *b) 128 | { 129 | struct BBox *pa, *pb; 130 | 131 | pa = *(struct BBox**)a; 132 | pb = *(struct BBox**)b; 133 | 134 | if (pa->vSpan < pb->vSpan) return -1; 135 | if (pa->vSpan > pb->vSpan) return 1; 136 | return 0; 137 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 138 | } 139 | 140 | static int orderhSpan(const void *a, const void *b) 141 | { 142 | struct BBox *pa, *pb; 143 | 144 | pa = *(struct BBox**)a; 145 | pb = *(struct BBox**)b; 146 | 147 | if (pa->hSpan < pb->hSpan) return -1; 148 | if (pa->hSpan > pb->hSpan) return 1; 149 | return 0; 150 | // return ((struct Segment*)a->x1-(struct Segment*)b->x1); 151 | } 152 | 153 | // binary search to map the new coordinates to original coordinates 154 | 155 | 156 | 157 | 158 | // Copy Routing Solution for the best routing solution so far 159 | void copyRS (void); 160 | void copyBR (); 161 | void freeRR (void); 162 | 163 | } //namespace sproute 164 | 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /include/verbose.h: -------------------------------------------------------------------------------- 1 | 2 | namespace sproute { 3 | 4 | enum VERBOSE { 5 | none = 0, 6 | info, 7 | debug 8 | }; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /include/writeFile.h: -------------------------------------------------------------------------------- 1 | #ifndef WRITEFILE_H 2 | #define WRITEFILE_H 3 | 4 | namespace sproute_db 5 | { 6 | 7 | class Routed3DPoint 8 | { 9 | public: 10 | int x, y, z; 11 | bool horizontal; 12 | Routed3DPoint() { 13 | x = 0; 14 | y = 0; 15 | z = 0; 16 | horizontal = false; 17 | } 18 | Routed3DPoint(int x, int y, int z, bool h): x(x), y(y), z(z), horizontal(h) { } 19 | 20 | bool operator< (const Routed3DPoint p) const 21 | { 22 | if(z < p.z) { 23 | return true; 24 | } 25 | else if(z > p.z) 26 | return false; 27 | else { //z == p.z 28 | if(horizontal) { 29 | if(y < p.y) 30 | return true; 31 | else if(y > p.y) 32 | return false; 33 | else { 34 | if(x < p.x) 35 | return true; 36 | else 37 | return false; 38 | } 39 | } 40 | else { //vertical 41 | if(x < p.x) 42 | return true; 43 | else if(x > p.x) 44 | return false; 45 | else { 46 | if(y < p.y) 47 | return true; 48 | else 49 | return false; 50 | } 51 | } 52 | } 53 | } 54 | }; 55 | 56 | } 57 | 58 | 59 | #endif -------------------------------------------------------------------------------- /lib/POST9.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncvlsi/SPRoute/2b0e0ff0448115f39b0b303ac4ea9a3c3a2e10f7/lib/POST9.dat -------------------------------------------------------------------------------- /lib/POWV9.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asyncvlsi/SPRoute/2b0e0ff0448115f39b0b303ac4ea9a3c3a2e10f7/lib/POWV9.dat -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | FILE(GLOB CPP_SOURCES "*.cpp") 4 | FILE(GLOB C_SOURCES "*.c") 5 | add_library(sproute ${CPP_SOURCES} ${c_SOURCES}) 6 | -------------------------------------------------------------------------------- /src/defDataBase.cpp: -------------------------------------------------------------------------------- 1 | #include "defDataBase.h" 2 | 3 | namespace sproute_db 4 | { 5 | 6 | Gcell& defDataBase::getGcell(int x, int y, int z) 7 | { 8 | int loc = z * (gcellGridDim.x * gcellGridDim.y) + y * gcellGridDim.x + x; 9 | return gcells.at(loc); 10 | } 11 | 12 | int find_Gcell(int pin_in, std::vector GcellBoundaries) 13 | { 14 | auto it = std::upper_bound(GcellBoundaries.begin(), GcellBoundaries.end(), pin_in); 15 | int x = std::distance(GcellBoundaries.begin(), it) - 1; 16 | 17 | if(x == -1) 18 | x++; 19 | else if(it == GcellBoundaries.end()) 20 | x--; 21 | 22 | return x; 23 | } 24 | 25 | }//namespace sproute_db 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/dist.c: -------------------------------------------------------------------------------- 1 | #include "fr_global.h" 2 | 3 | /*********************************************************************/ 4 | /* 5 | Return the Manhattan distance between two points 6 | */ 7 | 8 | long dist( 9 | Point p, 10 | Point q 11 | ) 12 | { 13 | long dx, dy; 14 | 15 | dx = (p.x) - (q.x); 16 | if( dx < 0 ) dx = -dx; 17 | dy = (p.y) - (q.y); 18 | if( dy < 0 ) dy = -dy; 19 | 20 | return dx + dy; 21 | } 22 | 23 | /*********************************************************************/ 24 | /* 25 | Return the Manhattan distance between two points 26 | */ 27 | 28 | long dist2( 29 | Point* p, 30 | Point* q 31 | ) 32 | { 33 | long dx, dy; 34 | 35 | dx = (p->x) - (q->x); 36 | if( dx < 0 ) dx = -dx; 37 | dy = (p->y) - (q->y); 38 | if( dy < 0 ) dy = -dy; 39 | 40 | return dx + dy; 41 | } 42 | 43 | /*********************************************************************/ 44 | /*********************************************************************/ 45 | -------------------------------------------------------------------------------- /src/dl.c: -------------------------------------------------------------------------------- 1 | #include "dl.h" 2 | #include 3 | #include 4 | 5 | dl_t dl_alloc() 6 | { 7 | dl_t dl = (dl_t)malloc(sizeof(dl_s)); 8 | if (!dl) { 9 | printf("Out of memory!!\n"); 10 | } else { 11 | dl->first = dl->last = 0; dl->count = 0; 12 | } 13 | return dl; 14 | } 15 | 16 | void dl_delete(dl_t dl, dl_el *el) 17 | { 18 | if (dl->first == el) { 19 | dl->first = el->next; 20 | } 21 | if (dl->last == el) { 22 | dl->last = el->prev; 23 | } 24 | if (el->next) { 25 | el->next->prev = el->prev; 26 | } 27 | if (el->prev) { 28 | el->prev->next = el->next; 29 | } 30 | free(el); dl->count--; 31 | } 32 | 33 | void dl_clear(dl_t dl) 34 | { 35 | dl_el *el, *next; 36 | if (dl->count > 0) { 37 | for (el=dl->first; el; el=next) { 38 | next = el->next; 39 | free(el); 40 | } 41 | } 42 | dl->first = dl->last = 0; 43 | dl->count = 0; 44 | } 45 | 46 | void dl_concat(dl_t first_list, dl_t second_list) 47 | { 48 | if (first_list->count <= 0) { 49 | *first_list = *second_list; 50 | } else if (second_list->count > 0) { 51 | first_list->last->next = second_list->first; 52 | second_list->first->prev = first_list->last; 53 | first_list->last = second_list->last; 54 | first_list->count += second_list->count; 55 | } 56 | 57 | free(second_list); 58 | } 59 | 60 | static void dl_insertion_sort(dl_t dl, size_t el_size, 61 | int(*compar)(void *, void *)) 62 | { 63 | char *buf; 64 | void *curr_d, *srch_d; 65 | dl_el *curr, *srch; 66 | 67 | if (dl_length(dl) <= 1) { 68 | return; 69 | } 70 | 71 | buf = (char*)malloc(el_size); 72 | 73 | for (curr=dl->first; curr!=dl->last; curr=curr->next) { 74 | curr_d = (void*)(((dl_el*)curr)+1); 75 | 76 | for (srch=dl->last; srch!=curr; srch=srch->prev) { 77 | srch_d = (void*)(((dl_el*)srch)+1); 78 | if (compar(curr_d, srch_d) > 0) { 79 | memcpy((void*)buf, curr_d, el_size); 80 | memcpy(curr_d, srch_d, el_size); 81 | memcpy(srch_d, (void*)buf, el_size); 82 | } 83 | } 84 | } 85 | 86 | 87 | free(buf); 88 | } 89 | 90 | void dl_sort(dl_t dl, size_t el_size, int(*compar)(void *, void *)) 91 | { 92 | dl_el *el, *first_head, *second_head; 93 | dl_s first_list, second_list; 94 | void *first_item, *second_item; 95 | int i, len; 96 | 97 | if (dl_length(dl) <= 25) { 98 | dl_insertion_sort(dl, el_size, compar); 99 | return; 100 | } 101 | 102 | len = dl_length(dl)/2; 103 | for (i=0, el=dl->first; inext; 105 | } 106 | 107 | first_list.first = dl->first; 108 | first_list.last = el->prev; 109 | first_list.count = len; 110 | first_list.last->next = 0; 111 | 112 | second_list.first = el; 113 | second_list.last = dl->last; 114 | second_list.count = dl_length(dl)-len; 115 | second_list.first->prev = 0; 116 | 117 | dl_sort(&first_list, el_size, compar); 118 | dl_sort(&second_list, el_size, compar); 119 | 120 | /* in-place merging */ 121 | first_head = first_list.first; 122 | second_head = second_list.first; 123 | 124 | first_item = (void*)(((dl_el*)first_head)+1); 125 | second_item = (void*)(((dl_el*)second_head)+1); 126 | if (compar(first_item, second_item) <= 0) { 127 | dl->first = el = first_head; 128 | first_head = first_head->next; 129 | } else { 130 | dl->first = el = second_head; 131 | second_head = second_head->next; 132 | } 133 | 134 | while (1) { 135 | first_item = (void*)(((dl_el*)first_head)+1); 136 | second_item = (void*)(((dl_el*)second_head)+1); 137 | if (compar(first_item, second_item) <= 0) { 138 | el->next = first_head; 139 | first_head->prev = el; 140 | el = first_head; 141 | first_head = first_head->next; 142 | if (!first_head) { 143 | el->next = second_head; 144 | second_head->prev = el; 145 | dl->last = second_list.last; 146 | break; 147 | } 148 | } else { 149 | el->next = second_head; 150 | second_head->prev = el; 151 | el = second_head; 152 | second_head = second_head->next; 153 | if (!second_head) { 154 | el->next = first_head; 155 | first_head->prev = el; 156 | dl->last = first_list.last; 157 | break; 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/err.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /**************************************************************************/ 5 | /* 6 | print error message and continue 7 | */ 8 | 9 | void err_msg( 10 | char* msg 11 | ) 12 | { 13 | fprintf(stderr, "%s\n", msg); 14 | } 15 | 16 | /**************************************************************************/ 17 | /* 18 | print error message and exit 19 | */ 20 | 21 | void err_exit( 22 | char* msg 23 | ) 24 | { 25 | fprintf(stderr, "%s\n", msg); 26 | exit(1); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/flute-ckt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "bookshelf_IO.h" 4 | #include "memAlloc.h" 5 | #include "flute.h" 6 | #include "string.h" 7 | 8 | float HPwl(); 9 | float flutewl(); 10 | 11 | int main (int argc, char *argv[]) 12 | { 13 | char auxFile[BUFFERSIZE], benchmarkPath[BUFFERSIZE], placefile[BUFFERSIZE]; 14 | 15 | if(argc != 4) { 16 | printf("Usage: %s \n", 17 | argv[0]); 18 | printf(" is the benchmark file directory.\n"); 19 | printf(" is the bookshelf format auxiliary file"); 20 | printf(" (assume in ).\n"); 21 | printf(" is the placement file"); 22 | printf(" (assume in current directory).\n"); 23 | exit(1); 24 | } 25 | 26 | strcpy(benchmarkPath, argv[1]); 27 | strcpy(auxFile, argv[2]); 28 | strcpy(placefile, argv[3]); 29 | 30 | readAuxFile(benchmarkPath, auxFile); 31 | createHash(benchmarkPath, nodesFile); 32 | readNodesFile(benchmarkPath, nodesFile); 33 | readNetsFile(benchmarkPath, netsFile); 34 | readPlFile(".", placefile); 35 | freeHash(); 36 | 37 | readLUT(); 38 | 39 | printf("Half-perimeter wirelength: %.2f\n", HPwl()); 40 | printf("FLUTE wirelength : %.2f\n", flutewl()); 41 | } 42 | 43 | float HPwl() 44 | { 45 | float totx, toty, xu, xl, yu, yl, xOffset, yOffset; 46 | int i, j, k; 47 | 48 | totx = 0.0; toty = 0.0; 49 | for (j=1; j<=numNets; j++) { 50 | xl = yl = 1e9; 51 | xu = yu = -1e9; 52 | for (k=netlistIndex[j]; k 2 | #include 3 | #include "flute.h" 4 | 5 | int main() 6 | { 7 | int d=0; 8 | int x[MAXD], y[MAXD]; 9 | Tree flutetree; 10 | int flutewl; 11 | 12 | while (!feof(stdin)) { 13 | scanf("%d %d\n", &x[d], &y[d]); 14 | d++; 15 | } 16 | readLUT(); 17 | 18 | flutetree = flute(d, x, y, ACCURACY); 19 | printf("FLUTE wirelength = %d\n", flutetree.length); 20 | 21 | flutewl = flute_wl(d, x, y, ACCURACY); 22 | printf("FLUTE wirelength (without RSMT construction) = %d\n", flutewl); 23 | } 24 | -------------------------------------------------------------------------------- /src/heap.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************/ 2 | /* 3 | Binary heap routines for use in Prim's algorithm, 4 | with points are numbered from 0 to n-1 5 | */ 6 | 7 | #include 8 | #include "heap.h" 9 | #include "err.h" 10 | 11 | 12 | Heap* _heap = (Heap*)NULL; 13 | long _max_heap_size = 0; 14 | long _heap_size = 0; 15 | 16 | /****************************************************************************/ 17 | /* 18 | */ 19 | 20 | void allocate_heap( long n ) 21 | { 22 | if( _max_heap_size < n ) 23 | { 24 | _heap = (Heap*)realloc( (void*)_heap, (size_t)(n+1)*sizeof(Heap) ); 25 | if( ! _heap ) 26 | { 27 | err_exit( "Cannot reallocate memory in allocate_heap!" ); 28 | } 29 | _max_heap_size = n; 30 | } 31 | } 32 | /****************************************************************************/ 33 | /* 34 | */ 35 | 36 | void deallocate_heap() 37 | { 38 | _max_heap_size = 0; 39 | if( _heap ) 40 | { 41 | free( (void*)_heap ); 42 | _heap = (Heap*)NULL; 43 | } 44 | } 45 | 46 | /****************************************************************************/ 47 | 48 | void heap_init( long n ) 49 | { 50 | register long p; 51 | 52 | allocate_heap( n ); 53 | _heap_size = 0; 54 | for( p = 0; p < n; p++ ) 55 | { 56 | heap_idx( p ) = 0; 57 | } 58 | 59 | } /* END heap_init() */ 60 | 61 | /****************************************************************************/ 62 | 63 | void heap_insert( 64 | long p, 65 | long key 66 | ) 67 | { 68 | register long k; /* hole in the heap */ 69 | register long j; /* parent of the hole */ 70 | register long q; /* heap_elt(j) */ 71 | 72 | heap_key( p ) = key; 73 | 74 | if( _heap_size == 0 ) 75 | { 76 | _heap_size = 1; 77 | heap_elt( 1 ) = p; 78 | heap_idx( p ) = 1; 79 | return; 80 | } 81 | 82 | k = ++ _heap_size; 83 | j = k >> 1; /* k/2 */ 84 | 85 | while( (j > 0) && (heap_key(q=heap_elt(j)) > key) ) { 86 | 87 | heap_elt( k ) = q; 88 | heap_idx( q ) = k; 89 | k = j; 90 | j = k>>1; /* k/2 */ 91 | 92 | } 93 | 94 | /* store p in the position of the hole */ 95 | heap_elt( k ) = p; 96 | heap_idx( p ) = k; 97 | 98 | } /* END heap_insert() */ 99 | 100 | 101 | /****************************************************************************/ 102 | 103 | void heap_decrease_key 104 | ( 105 | long p, 106 | long new_key 107 | ) 108 | { 109 | register long k; /* hole in the heap */ 110 | register long j; /* parent of the hole */ 111 | register long q; /* heap_elt(j) */ 112 | 113 | heap_key( p ) = new_key; 114 | k = heap_idx( p ); 115 | j = k >> 1; /* k/2 */ 116 | 117 | if( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) ) { /* change is needed */ 118 | do { 119 | 120 | heap_elt( k ) = q; 121 | heap_idx( q ) = k; 122 | k = j; 123 | j = k>>1; /* k/2 */ 124 | 125 | } while( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) ); 126 | 127 | /* store p in the position of the hole */ 128 | heap_elt( k ) = p; 129 | heap_idx( p ) = k; 130 | } 131 | 132 | } /* END heap_decrease_key() */ 133 | 134 | 135 | /****************************************************************************/ 136 | 137 | long heap_delete_min() 138 | { 139 | long min, last; 140 | register long k; /* hole in the heap */ 141 | register long j; /* child of the hole */ 142 | register long l_key; /* key of last point */ 143 | 144 | if( _heap_size == 0 ) /* heap is empty */ 145 | return( -1 ); 146 | 147 | min = heap_elt( 1 ); 148 | last = heap_elt( _heap_size -- ); 149 | l_key = heap_key( last ); 150 | 151 | k = 1; j = 2; 152 | while( j <= _heap_size ) { 153 | 154 | if( heap_key(heap_elt(j)) > heap_key(heap_elt(j+1)) ) 155 | j++; 156 | 157 | if( heap_key(heap_elt(j)) >= l_key) 158 | break; /* found a position to insert 'last' */ 159 | 160 | /* else, sift hole down */ 161 | heap_elt(k) = heap_elt(j); /* Note that j <= _heap_size */ 162 | heap_idx( heap_elt(k) ) = k; 163 | k = j; 164 | j = k << 1; 165 | } 166 | 167 | heap_elt( k ) = last; 168 | heap_idx( last ) = k; 169 | 170 | heap_idx( min ) = -1; /* mark the point visited */ 171 | return( min ); 172 | 173 | } /* END heap_delete_min() */ 174 | 175 | 176 | /****************************************************************************/ 177 | 178 | -------------------------------------------------------------------------------- /src/invalidnets_adj.cpp: -------------------------------------------------------------------------------- 1 | #include "sproute.h" 2 | 3 | namespace sproute { 4 | 5 | int SPRoute::InvalidNetsAdjLayer(int x, int y, int l, int xGrid, int yGrid) { 6 | 7 | int adj = 0; 8 | if (lefDB.layers.at(l * 2).direction == "HORIZONTAL")//horizontal 9 | { 10 | 11 | if(x < xGrid - 1) { //not the right boundary 12 | int grid3D = y*(xGrid-1)+x+l*(xGrid-1)*yGrid; 13 | if(h_edges3D[grid3D].cap > 0) { 14 | h_edges3D[grid3D].cap -= 1; 15 | h_edges3D[grid3D].red += 1; 16 | int grid2D =y*(xGrid-1)+x; 17 | h_edges[grid2D].cap -=1; 18 | h_edges[grid2D].red += 1; 19 | adj++; 20 | } 21 | } 22 | 23 | if(x > 0) { //not the left boundary 24 | x -= 1; 25 | int grid3D = y*(xGrid-1)+x+l*(xGrid-1)*yGrid; 26 | if(h_edges3D[grid3D].cap > 0) { 27 | h_edges3D[grid3D].cap -= 1; 28 | h_edges3D[grid3D].red += 1; 29 | int grid2D =y*(xGrid-1)+x; 30 | h_edges[grid2D].cap -= 1; 31 | h_edges[grid2D].red += 1; 32 | adj++; 33 | } 34 | } 35 | 36 | } 37 | else if (lefDB.layers.at(l * 2).direction == "VERTICAL")//vertical 38 | { 39 | if(y < yGrid - 1) { // not the top boundary 40 | int grid3D = y*xGrid + x + l*xGrid*(yGrid-1); 41 | if(v_edges3D[grid3D].cap > 0) { 42 | v_edges3D[grid3D].cap -= 1; 43 | v_edges3D[grid3D].red += 1; 44 | int grid2D = y * xGrid + x; 45 | v_edges[grid2D].cap -= 1; 46 | v_edges[grid2D].red += 1; 47 | adj++; 48 | } 49 | } 50 | 51 | if(y > 0) { // not the bot boundary 52 | y -= 1; 53 | int grid3D = y*xGrid + x + l*xGrid*(yGrid-1); 54 | if(v_edges3D[grid3D].cap > 0) { 55 | v_edges3D[grid3D].cap -= 1; 56 | v_edges3D[grid3D].red += 1; 57 | int grid2D = y * xGrid + x; 58 | v_edges[grid2D].cap -= 1; 59 | v_edges[grid2D].red += 1; 60 | adj++; 61 | } 62 | } 63 | } 64 | else 65 | { 66 | cout << "unknown layer direction in invalidNetsAdj" << endl; 67 | exit(1); 68 | } 69 | return adj; 70 | 71 | } 72 | 73 | void SPRoute::InvalidNetsAdj(Net** invalid_nets, int xGrid, int yGrid) { 74 | 75 | int num_adj = 0; 76 | for(int i = 0 ; i < numInvalidNets; i++) { 77 | 78 | Net* net= invalid_nets[i]; 79 | int x = net->pinX[0]; 80 | int y = net->pinY[0]; 81 | int l = net->pinL[0]; //starting from 1 82 | 83 | if(net->numPins > 1 && l != 1) { 84 | std::cout << "An invalid nets is not on bottom layer? " << std::endl; 85 | std::cout << net->name << " " << net->numPins << endl; 86 | std::cout << x << " " << y << " " << l << endl; 87 | exit(1); 88 | } 89 | 90 | num_adj += InvalidNetsAdjLayer(x, y, 1, xGrid, yGrid); 91 | num_adj += InvalidNetsAdjLayer(x, y, 2, xGrid, yGrid); 92 | } 93 | if(verbose_ > none) 94 | cout << "num of invalid net : " << numInvalidNets << "adj: " << num_adj << endl; 95 | 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/memAlloc.c: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------- 2 | Public domain memory allocation and de-allocation routines. 3 | Taken from Appendix B of: 4 | Numerical Recipes in C: The Art of Scientific Computing, Second Edition, 5 | Cambridge University Press, 1992 6 | ----------------------------------------------------------------------------*/ 7 | #include 8 | #include 9 | #include 10 | 11 | #include "memAlloc.h" 12 | 13 | #define MEM_END 1 14 | #define FREE_ARG char* 15 | 16 | void runtimeError(char error_text[]) 17 | /* error handler */ 18 | { 19 | fprintf(stderr,"run-time error...\n"); 20 | fprintf(stderr,"%s\n",error_text); 21 | fprintf(stderr,"...now exiting to system...\n"); 22 | exit(1); 23 | } 24 | 25 | float *vector(long nl, long nh) 26 | /* allocate a float vector with subscript range v[nl..nh] */ 27 | { 28 | float *v; 29 | v=(float *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(float))); 30 | if (!v) runtimeError("allocation failure in vector()"); 31 | return v-nl+MEM_END; 32 | } 33 | 34 | int *ivector(long nl, long nh) 35 | /* allocate an int vector with subscript range v[nl..nh] */ 36 | { 37 | int *v; 38 | v=(int *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(int))); 39 | if (!v) runtimeError("allocation failure in ivector()"); 40 | return v-nl+MEM_END; 41 | } 42 | 43 | unsigned char *cvector(long nl, long nh) 44 | /* allocate an unsigned char vector with subscript range v[nl..nh] */ 45 | { 46 | unsigned char *v; 47 | v=(unsigned char *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(unsigned char))); 48 | if (!v) runtimeError("allocation failure in cvector()"); 49 | return v-nl+MEM_END; 50 | } 51 | 52 | unsigned long *lvector(long nl, long nh) 53 | /* allocate an unsigned long vector with subscript range v[nl..nh] */ 54 | { 55 | unsigned long *v; 56 | v=(unsigned long *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(long))); 57 | if (!v) runtimeError("allocation failure in lvector()"); 58 | return v-nl+MEM_END; 59 | } 60 | 61 | double *dvector(long nl, long nh) 62 | /* allocate a double vector with subscript range v[nl..nh] */ 63 | { 64 | double *v; 65 | v=(double *)malloc((size_t) ((nh-nl+1+MEM_END)*sizeof(double))); 66 | if (!v) runtimeError("allocation failure in dvector()"); 67 | return v-nl+MEM_END; 68 | } 69 | 70 | float **matrix(long nrl, long nrh, long ncl, long nch) 71 | /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */ 72 | { 73 | long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 74 | float **m; 75 | 76 | /* allocate pointers to rows */ 77 | m=(float **) malloc((size_t)((nrow+MEM_END)*sizeof(float*))); 78 | if (!m) runtimeError("allocation failure 1 in matrix()"); 79 | m += MEM_END; 80 | m -= nrl; 81 | 82 | /* allocate rows and set pointers to them */ 83 | m[nrl]=(float *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(float))); 84 | if (!m[nrl]) runtimeError("allocation failure 2 in matrix()"); 85 | m[nrl] += MEM_END; 86 | m[nrl] -= ncl; 87 | for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; 88 | /* return pointer to array of pointers to rows */ 89 | return m; 90 | } 91 | 92 | double **dmatrix(long nrl, long nrh, long ncl, long nch) 93 | /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */ 94 | { 95 | long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 96 | double **m; 97 | 98 | /* allocate pointers to rows */ 99 | m=(double **) malloc((size_t)((nrow+MEM_END)*sizeof(double*))); 100 | if (!m) runtimeError("allocation failure 1 in dmatrix()"); 101 | m += MEM_END; 102 | m -= nrl; 103 | 104 | /* allocate rows and set pointers to them */ 105 | m[nrl]=(double *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(double))); 106 | if (!m[nrl]) runtimeError("allocation failure 2 din matrix()"); 107 | m[nrl] += MEM_END; 108 | m[nrl] -= ncl; 109 | 110 | for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; 111 | 112 | /* return pointer to array of pointers to rows */ 113 | return m; 114 | } 115 | 116 | int **imatrix(long nrl, long nrh, long ncl, long nch) 117 | /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */ 118 | { 119 | long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 120 | int **m; 121 | 122 | /* allocate pointers to rows */ 123 | m=(int **) malloc((size_t)((nrow+MEM_END)*sizeof(int*))); 124 | if (!m) runtimeError("allocation failure 1 in imatrix()"); 125 | m += MEM_END; 126 | m -= nrl; 127 | 128 | /* allocate rows and set pointers to them */ 129 | m[nrl]=(int *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(int))); 130 | if (!m[nrl]) runtimeError("allocation failure 2 in imatrix()"); 131 | m[nrl] += MEM_END; 132 | m[nrl] -= ncl; 133 | 134 | for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; 135 | 136 | /* return pointer to array of pointers to rows */ 137 | return m; 138 | } 139 | 140 | 141 | char **cmatrix(long nrl, long nrh, long ncl, long nch) 142 | /* allocate a char matrix with subscript range m[nrl..nrh][ncl..nch] */ 143 | { 144 | long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 145 | char **m; 146 | 147 | /* allocate pointers to rows */ 148 | m=(char **) malloc((size_t)((nrow+MEM_END)*sizeof(char*))); 149 | if (!m) runtimeError("allocation failure 1 in cmatrix()"); 150 | m += MEM_END; 151 | m -= nrl; 152 | 153 | /* allocate rows and set pointers to them */ 154 | m[nrl]=(char *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(char))); 155 | if (!m[nrl]) runtimeError("allocation failure 2 in cmatrix()"); 156 | m[nrl] += MEM_END; 157 | m[nrl] -= ncl; 158 | 159 | for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; 160 | 161 | /* return pointer to array of pointers to rows */ 162 | return m; 163 | } 164 | 165 | 166 | unsigned long **lmatrix(long nrl, long nrh, long ncl, long nch) 167 | /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */ 168 | { 169 | long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; 170 | unsigned long **m; 171 | 172 | /* allocate pointers to rows */ 173 | m=(unsigned long **) malloc((size_t)((nrow+MEM_END)*sizeof(long*))); 174 | if (!m) runtimeError("allocation failure 1 in lmatrix()"); 175 | m += MEM_END; 176 | m -= nrl; 177 | 178 | /* allocate rows and set pointers to them */ 179 | m[nrl]=(unsigned long *) malloc((size_t)((nrow*ncol+MEM_END)*sizeof(long))); 180 | if (!m[nrl]) runtimeError("allocation failure 2 in lmatrix()"); 181 | m[nrl] += MEM_END; 182 | m[nrl] -= ncl; 183 | 184 | for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; 185 | 186 | /* return pointer to array of pointers to rows */ 187 | return m; 188 | } 189 | 190 | 191 | float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, 192 | long newrl, long newcl) 193 | /* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */ 194 | { 195 | long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl; 196 | float **m; 197 | 198 | /* allocate array of pointers to rows */ 199 | m=(float **) malloc((size_t) ((nrow+MEM_END)*sizeof(float*))); 200 | if (!m) runtimeError("allocation failure in submatrix()"); 201 | m += MEM_END; 202 | m -= newrl; 203 | 204 | /* set pointers to rows */ 205 | for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol; 206 | 207 | /* return pointer to array of pointers to rows */ 208 | return m; 209 | } 210 | 211 | float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch) 212 | /* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix 213 | declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1 214 | and ncol=nch-ncl+1. The routine should be called with the address 215 | &a[0][0] as the first argument. */ 216 | { 217 | long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1; 218 | float **m; 219 | 220 | /* allocate pointers to rows */ 221 | m=(float **) malloc((size_t) ((nrow+MEM_END)*sizeof(float*))); 222 | if (!m) runtimeError("allocation failure in convert_matrix()"); 223 | m += MEM_END; 224 | m -= nrl; 225 | 226 | /* set pointers to rows */ 227 | m[nrl]=a-ncl; 228 | for(i=1,j=nrl+1;i 0) 66 | x -= 1; 67 | 68 | int grid3D = y*(xGrid-1)+x+l*(xGrid-1)*yGrid; 69 | if(h_edges3D[grid3D].cap < hCapacity3D[l]) { 70 | h_edges3D[grid3D].cap += 1; 71 | h_edges3D[grid3D].red -= 1; 72 | int grid2D = y * (xGrid - 1) + x; 73 | h_edges[grid2D].cap += 1; 74 | h_edges[grid2D].red -= 1; 75 | if(debug) { 76 | cout << "min h adj: " << x << " " << y << " " << l << endl; 77 | } 78 | } 79 | } 80 | 81 | if(first_rect.lowerLeft.x == xmax && lefDB.layers[layerIdx].direction == "HORIZONTAL" && xmax_cnt != 1) { 82 | int x = sproute_db::find_Gcell(first_rect.lowerLeft.x, defDB.xGcellBoundaries); 83 | int y = sproute_db::find_Gcell(first_rect.lowerLeft.y, defDB.yGcellBoundaries); 84 | 85 | int grid3D = y*(xGrid-1)+x+l*(xGrid-1)*yGrid; 86 | if(h_edges3D[grid3D].cap < hCapacity3D[l]) { 87 | h_edges3D[grid3D].cap += 1; 88 | h_edges3D[grid3D].red -= 1; 89 | int grid2D = y * (xGrid - 1) + x; 90 | h_edges[grid2D].cap += 1; 91 | h_edges[grid2D].red -= 1; 92 | if(debug) { 93 | cout << "max h adj: " << x << " " << y << " " << l << endl; 94 | } 95 | } 96 | } 97 | 98 | if(first_rect.lowerLeft.y == ymin && lefDB.layers[layerIdx].direction == "VERTICAL" && ymin_cnt != 1) { 99 | int x = sproute_db::find_Gcell(first_rect.lowerLeft.x, defDB.xGcellBoundaries); 100 | int y = sproute_db::find_Gcell(first_rect.lowerLeft.y, defDB.yGcellBoundaries); 101 | if(y > 0) 102 | y -= 1; 103 | 104 | int grid3D = y*xGrid + x + l*xGrid*(yGrid-1); 105 | if(v_edges3D[grid3D].cap < vCapacity3D[l]) { 106 | v_edges3D[grid3D].cap += 1; 107 | v_edges3D[grid3D].red -= 1; 108 | int grid2D = y * xGrid + x; 109 | v_edges[grid2D].cap += 1; 110 | v_edges[grid2D].red -= 1; 111 | if(debug) { 112 | cout << "v adj: " << x << " " << y << " " << l << endl; 113 | } 114 | } 115 | } 116 | 117 | if(first_rect.lowerLeft.y == ymax && lefDB.layers[layerIdx].direction == "VERTICAL" && ymax_cnt != 1) { 118 | int x = sproute_db::find_Gcell(first_rect.lowerLeft.x, defDB.xGcellBoundaries); 119 | int y = sproute_db::find_Gcell(first_rect.lowerLeft.y, defDB.yGcellBoundaries); 120 | 121 | int grid3D = y*xGrid + x + l*xGrid*(yGrid-1); 122 | if(v_edges3D[grid3D].cap < vCapacity3D[l]) { 123 | v_edges3D[grid3D].cap += 1; 124 | v_edges3D[grid3D].red -= 1; 125 | int grid2D = y * xGrid + x; 126 | v_edges[grid2D].cap += 1; 127 | v_edges[grid2D].red -= 1; 128 | if(debug) { 129 | cout << "v adj: " << x << " " << y << " " << l << endl; 130 | } 131 | } 132 | } 133 | 134 | } // for layer 135 | } //for pin 136 | } //for component 137 | } 138 | 139 | } -------------------------------------------------------------------------------- /src/mst2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "fr_global.h" 5 | #include "neighbors.h" 6 | #include "dist.h" 7 | #include "heap.h" 8 | #include "err.h" 9 | 10 | 11 | 12 | void mst2_package_init( long n ) 13 | { 14 | allocate_heap( n ); 15 | allocate_nn_arrays( n ); 16 | } 17 | 18 | /****************************************************************************/ 19 | /* 20 | */ 21 | 22 | void mst2_package_done() 23 | { 24 | deallocate_heap(); 25 | deallocate_nn_arrays(); 26 | } 27 | 28 | /****************************************************************************/ 29 | /* 30 | */ 31 | 32 | void mst2 33 | ( 34 | long n, 35 | Point* pt, 36 | long* parent 37 | ) 38 | { 39 | long i, k, nn1; 40 | long d; 41 | long oct; 42 | long root = 0; 43 | extern nn_array* nn; 44 | 45 | // brute_force_nearest_neighbors( n, pt, nn ); 46 | dq_nearest_neighbors( n, pt, nn ); 47 | 48 | /* 49 | Binary heap implementation of Prim's algorithm. 50 | Runs in O(n*log(n)) time since at most 8n edges are considered 51 | */ 52 | 53 | heap_init( n ); 54 | heap_insert( root, 0 ); 55 | parent[root] = root; 56 | 57 | for( k = 0; k < n; k++ ) /* n points to be extracted from heap */ 58 | { 59 | i = heap_delete_min(); 60 | 61 | if (i<0) break; 62 | #ifdef DEBUG 63 | assert( i >= 0 ); 64 | #endif 65 | 66 | /* 67 | pt[i] entered the tree, update heap keys for its neighbors 68 | */ 69 | for( oct = 0; oct < 8; oct++ ) 70 | { 71 | nn1 = nn[i][oct]; 72 | if( nn1 >= 0 ) 73 | { 74 | d = dist( pt[i], pt[nn1] ); 75 | if( in_heap(nn1) && (d < heap_key(nn1)) ) 76 | { 77 | heap_decrease_key( nn1, d ); 78 | parent[nn1] = i; 79 | } 80 | else if( never_seen(nn1) ) 81 | { 82 | heap_insert( nn1, d ); 83 | parent[nn1] = i; 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | /****************************************************************************/ 91 | /****************************************************************************/ 92 | 93 | -------------------------------------------------------------------------------- /src/neighbors.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "fr_global.h" 5 | #include "err.h" 6 | #include "dist.h" 7 | 8 | long octant 9 | ( 10 | Point from, 11 | Point to 12 | ); 13 | 14 | static Point* _pt; 15 | 16 | /***************************************************************************/ 17 | /* 18 | For efficiency purposes auxiliary arrays are allocated as globals 19 | */ 20 | 21 | long max_arrays_size = 0; 22 | nn_array* nn = (nn_array*)NULL; 23 | Point* sheared = (Point*)NULL; 24 | long* sorted = (long*)NULL; 25 | long* aux = (long*)NULL; 26 | 27 | /***************************************************************************/ 28 | /* 29 | resize the auxiliary arrays to fit the specified number of points 30 | */ 31 | 32 | void allocate_nn_arrays( long n ) 33 | { 34 | if( max_arrays_size < n ) 35 | { 36 | nn = (nn_array*)realloc( (void*)nn, (size_t)n*sizeof(nn_array) ); 37 | sheared = (Point*)realloc( (void*)sheared, (size_t)n*sizeof(Point) ); 38 | sorted = (long*)realloc( (void*)sorted, (size_t)n*sizeof(long) ); 39 | aux = (long*)realloc( (void*)aux, (size_t)n*sizeof(long) ); 40 | if( !nn || !sheared || !sorted || !aux ) 41 | { 42 | err_exit( "Cannot allocate memory in allocate_nn_arrays!" ); 43 | } 44 | max_arrays_size = n; 45 | } 46 | } 47 | 48 | /***************************************************************************/ 49 | /* 50 | free memory used by auxiliary arrays 51 | */ 52 | 53 | void deallocate_nn_arrays() 54 | { 55 | max_arrays_size = 0; 56 | if( nn ) 57 | { 58 | free( (void*)nn ); 59 | nn = (nn_array*)NULL; 60 | } 61 | if( sheared ) 62 | { 63 | free( (void*)sheared ); 64 | sheared = (Point*)NULL; 65 | } 66 | if( sorted ) 67 | { 68 | free( (void*)sorted ); 69 | sorted = (long*)NULL; 70 | } 71 | if( aux ) 72 | { 73 | free( (void*)aux ); 74 | aux = (long*)NULL; 75 | } 76 | 77 | } 78 | 79 | /***************************************************************************/ 80 | /* 81 | comparison function for use in quicksort 82 | */ 83 | 84 | static int compare_x 85 | ( 86 | const void* i, 87 | const void* j 88 | ) 89 | { 90 | /* 91 | points with the same x must appear in increasing order of y 92 | */ 93 | if( sheared[*((long*)i)].x == sheared[*((long*)j)].x) 94 | { 95 | return sheared[*((long*)i)].y - sheared[*((long*)j)].y; 96 | } 97 | else 98 | { 99 | return sheared[*((long*)i)].x - sheared[*((long*)j)].x; 100 | } 101 | } 102 | 103 | 104 | /***************************************************************************/ 105 | /* 106 | Combine step of the Guibas-Stolfi divide-and-conquer NE nearest neighbor 107 | algorithm. For efficiency purposes SW nearest neighbors are computed 108 | at the same time. 109 | */ 110 | 111 | void ne_sw_combine 112 | ( 113 | long left, 114 | long mid, 115 | long right, 116 | Point* pt, 117 | long* sorted, 118 | long* aux, 119 | long oct, 120 | nn_array* nn 121 | ) 122 | { 123 | long i, j, k, y2; 124 | long i1; 125 | long i2; 126 | long best_i2; /* index of current best nearest-neighbor */ 127 | long best_dist; /* distance to best nearest-neighbor */ 128 | long d; 129 | 130 | #ifdef DEBUG 131 | assert( right > mid ); 132 | assert( mid > left ); 133 | #endif 134 | 135 | /* 136 | update north-east nearest neighbors accross the mid-line 137 | */ 138 | 139 | i1 = left; 140 | i2 = mid; y2 = pt[ sorted[i2] ].y; 141 | 142 | while( (i1 < mid) && (pt[ sorted[i1] ].y >= y2) ) 143 | { 144 | i1++; 145 | } 146 | 147 | if( i1 < mid ) 148 | { 149 | best_i2 = i2; 150 | best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] ); 151 | i2++; 152 | 153 | while( (i1 < mid) && (i2 < right) ) 154 | { 155 | if( pt[ sorted[i1] ].y < pt[ sorted[i2] ].y ) 156 | { 157 | d = dist2( pt + sorted[i1], pt + sorted[i2] ); 158 | if( d < best_dist ) 159 | { 160 | best_i2 = i2; 161 | best_dist = d; 162 | } 163 | i2++; 164 | } 165 | else 166 | { 167 | if( (nn[ sorted[i1] ][oct] == -1) || 168 | ( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) 169 | ) 170 | { 171 | nn[ sorted[i1] ][oct] = sorted[best_i2]; 172 | } 173 | i1++; 174 | if( i1 < mid ) 175 | { 176 | best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] ); 177 | } 178 | } 179 | } 180 | 181 | while( i1 < mid ) 182 | { 183 | if( (nn[ sorted[i1] ][oct] == -1) || 184 | ( dist2( pt + sorted[i1], pt + sorted[best_i2] ) < 185 | dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) 186 | ) 187 | { 188 | nn[ sorted[i1] ][oct] = sorted[best_i2]; 189 | } 190 | i1++; 191 | } 192 | } 193 | /* 194 | repeat for south-west nearest neighbors 195 | */ 196 | 197 | oct = (oct + 4) % 8; 198 | 199 | i1 = right - 1; 200 | i2 = mid - 1; y2 = pt[ sorted[i2] ].y; 201 | 202 | while( (i1 >= mid) && (pt[ sorted[i1] ].y <= y2) ) 203 | { 204 | i1--; 205 | } 206 | 207 | if( i1 >= mid ) 208 | { 209 | best_i2 = i2; 210 | best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] ); 211 | i2--; 212 | 213 | while( (i1 >= mid) && (i2 >= left) ) 214 | { 215 | if( pt[ sorted[i1] ].y > pt[ sorted[i2] ].y ) 216 | { 217 | d = dist2( pt + sorted[i1], pt + sorted[i2] ); 218 | if( d < best_dist ) 219 | { 220 | best_i2 = i2; 221 | best_dist = d; 222 | } 223 | i2--; 224 | } 225 | else 226 | { 227 | if( (nn[ sorted[i1] ][oct] == -1) || 228 | ( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) 229 | ) 230 | { 231 | nn[ sorted[i1] ][oct] = sorted[best_i2]; 232 | } 233 | i1--; 234 | if( i1 >= mid ) 235 | { 236 | best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] ); 237 | } 238 | } 239 | } 240 | 241 | while( i1 >= mid ) 242 | { 243 | if( (nn[ sorted[i1] ][oct] == -1) || 244 | ( dist2( pt + sorted[i1], pt + sorted[best_i2] ) < 245 | dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) ) 246 | ) 247 | { 248 | nn[ sorted[i1] ][oct] = sorted[best_i2]; 249 | } 250 | i1--; 251 | } 252 | } 253 | 254 | /* 255 | merge sorted[left..mid-1] with sorted[mid..right-1] by y-coordinate 256 | */ 257 | 258 | i = left; /* first unprocessed element in left list */ 259 | j = mid; /* first unprocessed element in right list */ 260 | k = left; /* first free available slot in output list */ 261 | 262 | while( (i < mid) && (j < right) ) 263 | { 264 | if( pt[ sorted[i] ].y >= pt[ sorted[j] ].y ) 265 | { 266 | aux[k++] = sorted[i++]; 267 | } 268 | else 269 | { 270 | aux[k++] = sorted[j++]; 271 | } 272 | } 273 | 274 | /* 275 | copy leftovers 276 | */ 277 | while( i < mid ) { aux[k++] = sorted[i++]; } 278 | while( j < right ) { aux[k++] = sorted[j++]; } 279 | 280 | /* 281 | now copy sorted points from 'aux' to 'sorted' 282 | */ 283 | 284 | for( i = left; i < right; i++ ) { sorted[i] = aux[i]; } 285 | 286 | #if 0 287 | memcpy( (void*)(sorted+left), /* destination */ 288 | (void*)(aux+left), /* source */ 289 | (size_t)(right-left)*sizeof(long) /* number of bytes */ 290 | ); 291 | #endif 292 | 293 | } 294 | 295 | /***************************************************************************/ 296 | /* 297 | compute north-east and south-west nearest neighbors for points indexed 298 | by {sorted[left],...,sorted[right-1]} 299 | */ 300 | 301 | void ne_sw_nearest_neighbors 302 | ( 303 | long left, 304 | long right, 305 | Point* pt, 306 | long* sorted, 307 | long* aux, 308 | long oct, 309 | nn_array* nn 310 | ) 311 | { 312 | long mid; 313 | 314 | #ifdef DEBUG 315 | assert( right > left ); 316 | #endif 317 | 318 | if( right == left + 1 ) 319 | { 320 | nn[ sorted[left] ][oct] = nn[ sorted[left]][(oct+4) % 8] = -1; 321 | } 322 | else 323 | { 324 | mid = (left + right) / 2; 325 | ne_sw_nearest_neighbors( left, mid, pt, sorted, aux, oct, nn ); 326 | ne_sw_nearest_neighbors( mid, right, pt, sorted, aux, oct, nn ); 327 | ne_sw_combine( left, mid, right, pt, sorted, aux, oct, nn ); 328 | } 329 | } 330 | 331 | /***************************************************************************/ 332 | /* 333 | Guibas-Stolfi algorithm for computing nearest NE neighbors 334 | */ 335 | 336 | void dq_nearest_neighbors 337 | ( 338 | long n, 339 | Point* pt, 340 | nn_array* nn 341 | ) 342 | { 343 | long i, oct; 344 | void check_nn( long, Point*, nn_array* ); 345 | 346 | long shear[4][4] = { 347 | {1, -1, 0, 2}, 348 | {2, 0, -1, 1}, 349 | {1, 1, -2, 0}, 350 | {0, 2, -1, -1} 351 | }; 352 | 353 | 354 | 355 | _pt = pt; 356 | 357 | for( oct = 0; oct < 4; oct++ ) 358 | { 359 | for( i = 0; i < n; i++ ) 360 | { 361 | sheared[i].x = shear[oct][0]*pt[i].x + shear[oct][1]*pt[i].y; 362 | sheared[i].y = shear[oct][2]*pt[i].x + shear[oct][3]*pt[i].y; 363 | sorted[i] = i; 364 | } 365 | 366 | qsort( sorted, n, sizeof(long), compare_x ); 367 | ne_sw_nearest_neighbors( 0, n, sheared, sorted, aux, oct, nn ); 368 | } 369 | 370 | #ifdef DEBUG 371 | check_nn( n, pt, nn ); 372 | #endif 373 | 374 | } 375 | 376 | /***************************************************************************/ 377 | /***************************************************************************/ 378 | /* 379 | Brute-force nearest-neighbor computation for debugging purposes 380 | */ 381 | 382 | /***************************************************************************/ 383 | /* 384 | Half-open octants are numbered from 0 to 7 in anti-clockwise order 385 | starting from ( dx >= dy > 0 ). 386 | */ 387 | 388 | #define sgn(x) ( x>0 ? 1 : (x < 0 ? -1 : 0) ) 389 | 390 | long octant 391 | ( 392 | Point from, 393 | Point to 394 | ) 395 | { 396 | long dx = to.x - from.x; 397 | long dy = to.y - from.y; 398 | long sgn1 = sgn(dx)*sgn(dy); 399 | long sgn2 = sgn(dx+dy)*sgn(dx-dy); 400 | long oct = 0x0; 401 | 402 | 403 | if( (dy < 0) || ((dy==0) && (dx>0)) ) oct += 4; 404 | if( (sgn1 < 0) || (dy==0) ) oct += 2; 405 | if( (sgn1*sgn2 < 0) || (dy==0) || (dx==0) ) oct += 1; 406 | 407 | return oct; 408 | } 409 | 410 | /***************************************************************************/ 411 | /* 412 | O(n^2) algorithm for computing all nearest neighbors 413 | */ 414 | 415 | void brute_force_nearest_neighbors 416 | ( 417 | long n, 418 | Point* pt, 419 | nn_array* nn 420 | ) 421 | { 422 | long i, j, oct; 423 | long d; 424 | 425 | /* 426 | compute nearest neighbors by inspecting all pairs of points 427 | */ 428 | for( i = 0; i < n; i++ ) 429 | { 430 | for( oct = 0; oct < 8; oct++ ) 431 | { 432 | nn[i][oct] = -1; 433 | } 434 | } 435 | 436 | for( i = 0; i < n; i++ ) 437 | { 438 | for( j = i+1; j < n; j++ ) 439 | { 440 | d = dist(pt[i], pt[j]); 441 | 442 | oct = octant( pt[i], pt[j] ); 443 | if( ( nn[i][oct] == -1 ) || 444 | ( d < dist(pt[i], pt[ nn[i][oct] ]) ) 445 | ) 446 | { 447 | nn[i][oct] = j; 448 | } 449 | 450 | oct = (oct + 4) % 8; 451 | if( ( nn[j][oct] == -1 ) || 452 | ( d < dist(pt[j], pt[ nn[j][oct] ]) ) 453 | ) 454 | { 455 | nn[j][oct] = i; 456 | } 457 | } 458 | } 459 | } 460 | 461 | 462 | /***************************************************************************/ 463 | /* 464 | compare nearest neighbors against those computed by brute force 465 | */ 466 | 467 | void check_nn 468 | ( 469 | long n, 470 | Point* pt, 471 | nn_array* nn 472 | ) 473 | { 474 | long i, j, oct; 475 | nn_array* nn1; 476 | 477 | nn1 = (nn_array*)calloc( (size_t)n, (size_t)sizeof(nn_array) ); 478 | brute_force_nearest_neighbors( n, pt, nn1 ); 479 | 480 | for( i = 0; i < n; i++ ) 481 | { 482 | for( oct = 0; oct < 8; oct++ ) 483 | { 484 | if( nn[i][oct] == -1 ) 485 | { 486 | assert( nn1[i][oct] == -1 ); 487 | } 488 | else 489 | { 490 | assert( nn1[i][oct] != -1 ); 491 | 492 | if( octant(pt[i], pt[ nn[i][oct] ]) != oct ) 493 | { 494 | printf( "WRONG OCTANT!\noct=%ld\n", oct ); 495 | printf( "i=%ld, x=%ld, y=%ld\n", i, pt[i].x, pt[i].y ); 496 | j = nn[i][oct]; 497 | printf( "nn=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y, 498 | dist(pt[i], pt[j ]) ); 499 | } 500 | // assert( octant(pt[i], pt[ nn[i][oct] ]) == oct ); 501 | 502 | assert( octant(pt[i], pt[ nn1[i][oct] ]) == oct ); 503 | 504 | if( dist(pt[i], pt[ nn[i][oct] ]) != 505 | dist(pt[i], pt[ nn1[i][oct] ]) ) 506 | { 507 | printf( "NNs DON'T MATCH!\noct=%ld\n", oct ); 508 | printf( "i=%ld, x=%ld, y=%ld\n", i, pt[i].x, pt[i].y ); 509 | j = nn[i][oct]; 510 | printf( "nn=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y, 511 | dist(pt[i], pt[j ]) ); 512 | j = nn1[i][oct]; 513 | printf( "nn1=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y, 514 | dist(pt[i], pt[ j ]) ); 515 | } 516 | // assert( dist(pt[i], pt[ nn[i][oct] ]) == 517 | // dist(pt[i], pt[ nn1[i][oct] ]) ); 518 | } 519 | } 520 | } 521 | 522 | free( nn1 ); 523 | } 524 | 525 | /***************************************************************************/ 526 | /***************************************************************************/ 527 | 528 | -------------------------------------------------------------------------------- /src/rand-pts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int ac, char *av[]) 6 | { 7 | int d=10, tmp, i; 8 | int PNUM = 0; 9 | 10 | for (i=1; i] [-n] []\n", av[0]); 21 | printf(" Output random points "); 22 | printf("as lines of coordinate pairs.\n"); 23 | printf(" Default is 10.\n"); 24 | printf(" -r\t Randomize. Use getpid() as seed.\n"); 25 | printf(" -s\t Set random seed to .\n"); 26 | printf(" -n\t Write first before the random points.\n"); 27 | exit(-1); 28 | } 29 | } 30 | 31 | if (PNUM) 32 | printf("%d\n", d); 33 | for (i=1; i<=d; i++) 34 | printf("%4d %4d\n", (int) random()%10000, (int) random()%10000); 35 | } 36 | -------------------------------------------------------------------------------- /src/setup_heap.cpp: -------------------------------------------------------------------------------- 1 | #include "setup_heap.h" 2 | 3 | namespace sproute { 4 | 5 | void setupHeap_astar_swap(int netID, int edgeID, astar_local_pq& pq1, local_vec& v2, 6 | int regionX1, int regionX2, int regionY1, int regionY2, 7 | float** d1, int** corrEdge, bool** inRegion, float astar_weight) { 8 | int i, j, d, numNodes, n1, n2, x1, y1, x2, y2; 9 | int nbr, nbrX, nbrY, cur, edge; 10 | int x_grid, y_grid; 11 | int queuehead, queuetail, *queue; 12 | bool* visited; 13 | TreeEdge* treeedges; 14 | TreeNode* treenodes; 15 | Route* route; 16 | 17 | for (i = regionY1; i <= regionY2; i++) { 18 | for (j = regionX1; j <= regionX2; j++) 19 | inRegion[i][j] = true; 20 | } 21 | 22 | treeedges = sttrees[netID].edges; 23 | treenodes = sttrees[netID].nodes; 24 | d = sttrees[netID].deg; 25 | 26 | n1 = treeedges[edgeID].n2; 27 | n2 = treeedges[edgeID].n1; 28 | //key: here is changed! 29 | 30 | x1 = treenodes[n1].x; 31 | y1 = treenodes[n1].y; 32 | x2 = treenodes[n2].x; 33 | y2 = treenodes[n2].y; 34 | 35 | // if(netID == 14628) 36 | // printf("net: %d edge: %d src: %d %d dst: %d %d d: %d\n", netID, edgeID, 37 | // y1, x1, y2, x2, d); 38 | pq1.clear(); 39 | v2.clear(); // Michael 40 | if (d == 2) // 2-pin net 41 | { 42 | d1[y1][x1] = 0; 43 | float dst_dist = astar_weight * (fabs(x1 - x2) + fabs(y1 - y2)); 44 | pq1.push({&(d1[y1][x1]), 0, dst_dist}); 45 | v2.push_back(y2 * xGrid + x2); 46 | } else // net with more than 2 pins 47 | { 48 | numNodes = 2 * d - 2; 49 | 50 | visited = (bool*)calloc(numNodes, sizeof(bool)); 51 | for (i = 0; i < numNodes; i++) 52 | visited[i] = false; 53 | 54 | queue = (int*)calloc(numNodes, sizeof(int)); 55 | 56 | // find all the grids on tree edges in subtree t1 (connecting to n1) and put 57 | // them into heap1 58 | if (n1 < d) // n1 is a Pin node 59 | { 60 | // just need to put n1 itself into heap1 61 | d1[y1][x1] = 0; 62 | float dst_dist = astar_weight * (fabs(x1 - x2) + fabs(y1 - y2)); 63 | pq1.push({&(d1[y1][x1]), 0, dst_dist}); 64 | visited[n1] = true; 65 | } else // n1 is a Steiner node 66 | { 67 | queuehead = queuetail = 0; 68 | 69 | // add n1 into heap1 70 | d1[y1][x1] = 0; 71 | float dst_dist = astar_weight * (fabs(x1 - x2) + fabs(y1 - y2)); 72 | pq1.push({&(d1[y1][x1]), 0, dst_dist}); 73 | visited[n1] = true; 74 | 75 | // add n1 into the queue 76 | queue[queuetail] = n1; 77 | queuetail++; 78 | 79 | // loop to find all the edges in subtree t1 80 | while (queuetail > queuehead) { 81 | // get cur node from the queuehead 82 | cur = queue[queuehead]; 83 | queuehead++; 84 | visited[cur] = true; 85 | if (cur >= d) // cur node is a Steiner node 86 | { 87 | for (i = 0; i < 3; i++) { 88 | nbr = treenodes[cur].nbr[i]; 89 | edge = treenodes[cur].edge[i]; 90 | if (nbr != n2) // not n2 91 | { 92 | if (visited[nbr] == false) { 93 | // put all the grids on the two adjacent tree edges into heap1 94 | if (treeedges[edge].route.routelen > 0) // not a degraded edge 95 | { 96 | // put nbr into heap1 if in enlarged region 97 | if (inRegion[treenodes[nbr].y][treenodes[nbr].x]) { 98 | nbrX = treenodes[nbr].x; 99 | nbrY = treenodes[nbr].y; 100 | d1[nbrY][nbrX] = 0; 101 | // if(netID == 252163 && edgeID == 51) 102 | // printf("y: %d x: %d\n", nbrY, nbrX); 103 | dst_dist = astar_weight * (fabs(nbrX - x2) + fabs(nbrY - y2)); 104 | pq1.push({&(d1[nbrY][nbrX]), 0, dst_dist}); 105 | corrEdge[nbrY][nbrX] = edge; 106 | } 107 | 108 | // the coordinates of two end nodes of the edge 109 | 110 | route = &(treeedges[edge].route); 111 | if (route->type == MAZEROUTE) { 112 | for (j = 1; j < route->routelen; 113 | j++) // don't put edge_n1 and edge_n2 into heap1 114 | { 115 | x_grid = route->gridsX[j]; 116 | y_grid = route->gridsY[j]; 117 | 118 | if (inRegion[y_grid][x_grid]) { 119 | d1[y_grid][x_grid] = 0; 120 | // if(netID == 252163 && edgeID == 51) 121 | // printf("y: %d x: %d\n", y_grid, x_grid); 122 | dst_dist = astar_weight * (fabs(x_grid - x2) + fabs(y_grid - y2)); 123 | pq1.push({&(d1[y_grid][x_grid]), 0, dst_dist}); 124 | corrEdge[y_grid][x_grid] = edge; 125 | } 126 | } 127 | } // if MAZEROUTE 128 | else { 129 | printf("Setup Heap: not maze routing\n"); 130 | } 131 | } // if not a degraded edge (len>0) 132 | 133 | // add the neighbor of cur node into queue 134 | queue[queuetail] = nbr; 135 | queuetail++; 136 | } // if the node is not visited 137 | } // if nbr!=n2 138 | } // loop i (3 neigbors for cur node) 139 | } // if cur node is a Steiner nodes 140 | } // while queue is not empty 141 | } // else n1 is not a Pin node 142 | 143 | // find all the grids on subtree t2 (connect to n2) and put them into heap2 144 | // find all the grids on tree edges in subtree t2 (connecting to n2) and put 145 | // them into heap2 146 | if (1) // in astar, only 1 destination node (was n2 < d) 147 | { 148 | // just need to put n2 itself into heap2 149 | v2.push_back(y2 * xGrid + x2); 150 | visited[n2] = true; 151 | } 152 | 153 | free(queue); 154 | free(visited); 155 | } // net with more than two pins 156 | 157 | for (i = regionY1; i <= regionY2; i++) { 158 | for (j = regionX1; j <= regionX2; j++) 159 | inRegion[i][j] = false; 160 | } 161 | } 162 | 163 | 164 | void setupHeap_steiner(int netID, int edgeID, astar_local_pq& pq1, local_vec& v2, 165 | int regionX1, int regionX2, int regionY1, int regionY2, 166 | float** d1, int** corrEdge, bool** inRegion, float astar_weight) { 167 | int i, j, d, numNodes, n1, n2, x1, y1, x2, y2; 168 | int nbr, nbrX, nbrY, cur, edge; 169 | int x_grid, y_grid; 170 | int queuehead, queuetail, *queue; 171 | bool* visited; 172 | TreeEdge* treeedges; 173 | TreeNode* treenodes; 174 | Route* route; 175 | 176 | for (i = regionY1; i <= regionY2; i++) { 177 | for (j = regionX1; j <= regionX2; j++) 178 | inRegion[i][j] = true; 179 | } 180 | 181 | treeedges = sttrees[netID].edges; 182 | treenodes = sttrees[netID].nodes; 183 | d = sttrees[netID].deg; 184 | 185 | n1 = treeedges[edgeID].n1; 186 | n2 = treeedges[edgeID].n2; 187 | x1 = treenodes[n1].x; 188 | y1 = treenodes[n1].y; 189 | x2 = treenodes[n2].x; 190 | y2 = treenodes[n2].y; 191 | 192 | // if(netID == 14628) 193 | // printf("net: %d edge: %d src: %d %d dst: %d %d d: %d\n", netID, edgeID, 194 | // y1, x1, y2, x2, d); 195 | pq1.clear(); 196 | v2.clear(); // Michael 197 | if (d == 2) // 2-pin net 198 | { 199 | d1[y1][x1] = 0; 200 | pq1.push({&(d1[y1][x1]), 0, 0}); 201 | v2.push_back(y2 * xGrid + x2); 202 | } else // net with more than 2 pins 203 | { 204 | numNodes = 2 * d - 2; 205 | 206 | visited = (bool*)calloc(numNodes, sizeof(bool)); 207 | for (i = 0; i < numNodes; i++) 208 | visited[i] = false; 209 | 210 | queue = (int*)calloc(numNodes, sizeof(int)); 211 | 212 | // find all the grids on tree edges in subtree t1 (connecting to n1) and put 213 | // them into heap1 214 | if (n1 < d) // n1 is a Pin node 215 | { 216 | // just need to put n1 itself into heap1 217 | d1[y1][x1] = 0; 218 | pq1.push({&(d1[y1][x1]), 0, 0}); 219 | visited[n1] = true; 220 | } else // n1 is a Steiner node 221 | { 222 | queuehead = queuetail = 0; 223 | 224 | // add n1 into heap1 225 | d1[y1][x1] = 0; 226 | // if(netID == 252163 && edgeID == 51) 227 | // printf("y: %d x: %d\n", y1, x1); 228 | pq1.push({&(d1[y1][x1]), 0, 0}); 229 | visited[n1] = true; 230 | 231 | // add n1 into the queue 232 | queue[queuetail] = n1; 233 | queuetail++; 234 | 235 | // loop to find all the edges in subtree t1 236 | while (queuetail > queuehead) { 237 | // get cur node from the queuehead 238 | cur = queue[queuehead]; 239 | queuehead++; 240 | visited[cur] = true; 241 | if (cur >= d) // cur node is a Steiner node 242 | { 243 | for (i = 0; i < 3; i++) { 244 | nbr = treenodes[cur].nbr[i]; 245 | edge = treenodes[cur].edge[i]; 246 | if (nbr != n2) // not n2 247 | { 248 | if (visited[nbr] == false) { 249 | // put all the grids on the two adjacent tree edges into heap1 250 | if (treeedges[edge].route.routelen > 0) // not a degraded edge 251 | { 252 | // put nbr into heap1 if in enlarged region 253 | if (inRegion[treenodes[nbr].y][treenodes[nbr].x]) { 254 | nbrX = treenodes[nbr].x; 255 | nbrY = treenodes[nbr].y; 256 | d1[nbrY][nbrX] = 0; 257 | // if(netID == 252163 && edgeID == 51) 258 | // printf("y: %d x: %d\n", nbrY, nbrX); 259 | pq1.push({&(d1[nbrY][nbrX]), 0, 0}); 260 | corrEdge[nbrY][nbrX] = edge; 261 | } 262 | 263 | // the coordinates of two end nodes of the edge 264 | 265 | route = &(treeedges[edge].route); 266 | if (route->type == MAZEROUTE) { 267 | for (j = 1; j < route->routelen; 268 | j++) // don't put edge_n1 and edge_n2 into heap1 269 | { 270 | x_grid = route->gridsX[j]; 271 | y_grid = route->gridsY[j]; 272 | 273 | if (inRegion[y_grid][x_grid]) { 274 | d1[y_grid][x_grid] = 0; 275 | // if(netID == 252163 && edgeID == 51) 276 | // printf("y: %d x: %d\n", y_grid, x_grid); 277 | pq1.push({&(d1[y_grid][x_grid]), 0, 0}); 278 | corrEdge[y_grid][x_grid] = edge; 279 | } 280 | } 281 | } // if MAZEROUTE 282 | else { 283 | printf("Setup Heap: not maze routing\n"); 284 | } 285 | } // if not a degraded edge (len>0) 286 | 287 | // add the neighbor of cur node into queue 288 | queue[queuetail] = nbr; 289 | queuetail++; 290 | } // if the node is not visited 291 | } // if nbr!=n2 292 | } // loop i (3 neigbors for cur node) 293 | } // if cur node is a Steiner nodes 294 | } // while queue is not empty 295 | } // else n1 is not a Pin node 296 | 297 | // find all the grids on subtree t2 (connect to n2) and put them into heap2 298 | // find all the grids on tree edges in subtree t2 (connecting to n2) and put 299 | // them into heap2 300 | if (n2 < d) // n2 is a Pin node 301 | { 302 | // just need to put n2 itself into heap2 303 | v2.push_back(y2 * xGrid + x2); 304 | // if(netID == 14628) 305 | // printf("y: %d x: %d \n", y2, x2); 306 | visited[n2] = true; 307 | } else // n2 is a Steiner node 308 | { 309 | queuehead = queuetail = 0; 310 | 311 | // add n2 into heap2 312 | v2.push_back(y2 * xGrid + x2); 313 | // if(netID == 252163 && edgeID == 51) 314 | // printf("dst y: %d x: %d \n", y2, x2); 315 | visited[n2] = true; 316 | 317 | // add n2 into the queue 318 | queue[queuetail] = n2; 319 | queuetail++; 320 | 321 | // loop to find all the edges in subtree t2 322 | while (queuetail > queuehead) { 323 | // get cur node form queuehead 324 | cur = queue[queuehead]; 325 | visited[cur] = true; 326 | queuehead++; 327 | 328 | if (cur >= d) // cur node is a Steiner node 329 | { 330 | for (i = 0; i < 3; i++) { 331 | nbr = treenodes[cur].nbr[i]; 332 | edge = treenodes[cur].edge[i]; 333 | if (nbr != n1) // not n1 334 | { 335 | if (visited[nbr] == false) { 336 | // put all the grids on the two adjacent tree edges into heap2 337 | if (treeedges[edge].route.routelen > 0) // not a degraded edge 338 | { 339 | // put nbr into heap2 340 | if (inRegion[treenodes[nbr].y][treenodes[nbr].x]) { 341 | nbrX = treenodes[nbr].x; 342 | nbrY = treenodes[nbr].y; 343 | v2.push_back(nbrY * xGrid + nbrX); 344 | // if(netID == 252163 && edgeID == 51) 345 | // printf("dst y: %d x: %d\n", nbrY, nbrX); 346 | corrEdge[nbrY][nbrX] = edge; 347 | } 348 | 349 | // the coordinates of two end nodes of the edge 350 | 351 | route = &(treeedges[edge].route); 352 | if (route->type == MAZEROUTE) { 353 | for (j = 1; j < route->routelen; 354 | j++) // don't put edge_n1 and edge_n2 into heap2 355 | { 356 | x_grid = route->gridsX[j]; 357 | y_grid = route->gridsY[j]; 358 | if (inRegion[y_grid][x_grid]) { 359 | v2.push_back(y_grid * xGrid + x_grid); 360 | // if(netID == 252163 && edgeID == 51) 361 | // printf("dst y: %d x: %d\n", y_grid, x_grid); 362 | corrEdge[y_grid][x_grid] = edge; 363 | } 364 | } 365 | } // if MAZEROUTE 366 | else { 367 | printf("Setup Heap: not maze routing\n"); 368 | } 369 | } // if the edge is not degraded (len>0) 370 | 371 | // add the neighbor of cur node into queue 372 | queue[queuetail] = nbr; 373 | queuetail++; 374 | } // if the node is not visited 375 | } // if nbr!=n1 376 | } // loop i (3 neigbors for cur node) 377 | } // if cur node is a Steiner nodes 378 | } // while queue is not empty 379 | } // else n2 is not a Pin node 380 | 381 | free(queue); 382 | free(visited); 383 | } // net with more than two pins 384 | 385 | for (i = regionY1; i <= regionY2; i++) { 386 | for (j = regionX1; j <= regionX2; j++) 387 | inRegion[i][j] = false; 388 | } 389 | } 390 | 391 | } //namespace sproute 392 | -------------------------------------------------------------------------------- /src/soft_cap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "soft_cap.h" 3 | 4 | int GLOBAL_CAP_ADJ(int x, float rudy, int layerID) //layerID starting from 0, i.e. 0 = metal1, 1 = metal2, 2 = metal3 5 | { 6 | if(x == 0) 7 | return 0; 8 | else { 9 | float adj; 10 | 11 | if(layerID == 1) //metal2 12 | adj = (float) M2_ADJ_MIN + (float)(M2_ADJ_MAX - M2_ADJ_MIN) / (1.0 + exp(M2_ADJ_K * (rudy - M2_ADJ_MID))); 13 | else if(layerID == 2) //metal3 14 | adj = (float) M3_ADJ_MIN + (float)(M3_ADJ_MAX - M3_ADJ_MIN) / (1.0 + exp(M3_ADJ_K * (rudy - M3_ADJ_MID))); 15 | else if(layerID >= 3 && layerID <= 4) //metal4 metal5 16 | adj = (float) MID_ADJ_MIN + (float)(MID_ADJ_MAX - MID_ADJ_MIN) / (1.0 + exp(MID_ADJ_K * (rudy - MID_ADJ_MID))); 17 | else if(layerID >= 5) // metal6 and above 18 | adj = HIGH_ADJ; 19 | 20 | 21 | //adj = 0.9; 22 | 23 | return ((float) x * adj < 2)? 1 : x * adj; 24 | } 25 | } -------------------------------------------------------------------------------- /src/sproute_run.cpp: -------------------------------------------------------------------------------- 1 | #include "sproute.h" 2 | 3 | 4 | namespace sproute { 5 | 6 | void SPRoute::Run() { 7 | LinkTrackToLayer(); 8 | PreprocessSpacingTable(); 9 | 10 | PreprocessComponent(); 11 | InitGcell(); 12 | 13 | PreprocessSNet(); 14 | PreprocessDesignRule(); 15 | PreprocessDesignRuleOBS(); 16 | AdjustGcellCap(); 17 | 18 | InitGrGen(); 19 | 20 | RunGlobalRoute("", max_iteration, algo); 21 | if(verbose_ > none) 22 | std::cout << "routing guides written into phydb" << std::endl; 23 | 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | include_directories(../include) 4 | 5 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "sproute.h" 3 | 4 | //#include "fastroute.h" 5 | //#include "maxflow.h" 6 | #include 7 | 8 | int main(int argc, char** argv) 9 | { 10 | string defFileName, lefFileName, outFileName, algo_str; 11 | int numThreads = 1; 12 | for(int i = 1; i < argc; i++) 13 | { 14 | string tmp(argv[i]); 15 | if(tmp == "-lef") 16 | { 17 | lefFileName = string(argv[i+1]); 18 | } 19 | else if(tmp == "-def") 20 | { 21 | defFileName = string(argv[i+1]); 22 | } 23 | else if(tmp == "-t") 24 | { 25 | numThreads = atoi(argv[i+1]); 26 | } 27 | else if(tmp == "-output") 28 | { 29 | outFileName = string(argv[i+1]); 30 | } 31 | else if(tmp == "-algo") 32 | { 33 | algo_str = string(argv[i+1]); 34 | } 35 | } 36 | if(defFileName.size() == 0 || defFileName.size() == 0 || outFileName.size() == 0) 37 | { 38 | cout << "usage: ./lefdef_SPRoute -lef [LefFile] -def [DefFile] -t [nthreads] -output [Output file] -algo [Algo]" << endl; 39 | exit(1); 40 | } 41 | cout << "reading lef: " << lefFileName <