blob: 3591e32f8b3db0375820a0a480ec7a30d72d1e64 [file] [log] [blame]
/* Authors: Lutong Wang and Bangqi Xu */
/*
* Copyright (c) 2019, The Regents of the University of California
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the University nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 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 REGENTS 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, 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.
*/
#include "dr/FlexGridGraph.h"
#include <iostream>
#include <map>
#include <fstream>
using namespace std;
using namespace fr;
//void FlexGridGraph::resetCost(frMIdx x, frMIdx y, frMIdx z) {
// resetGridCostE(x, y, z);
// resetGridCostN(x, y, z);
// resetGridCostU(x, y, z);
// resetShapePlanar(x, y, z);
// resetShapeVia(x, y, z);
// resetDRCCostPlanar(x, y, z);
// resetDRCCostVia(x, y, z);
// resetMarkerCostPlanar(x, y, z);
// resetMarkerCostVia(x, y, z);
//}
void FlexGridGraph::initGrids(const map<frCoord, map<frLayerNum, frTrackPattern* > > &xMap,
const map<frCoord, map<frLayerNum, frTrackPattern* > > &yMap,
const map<frLayerNum, frPrefRoutingDirEnum> &zMap) {
//bool enableOutput = true;
bool enableOutput = false;
// initialize coord vectors
xCoords.clear();
yCoords.clear();
zCoords.clear();
zHeights.clear();
zDirs.clear();
halfViaEncArea.clear();
for (auto &[k, v]: xMap) {
xCoords.push_back(k);
}
for (auto &[k, v]: yMap) {
yCoords.push_back(k);
}
frCoord zHeight = 0;
for (auto &[k, v]: zMap) {
zCoords.push_back(k);
zHeight += getTech()->getLayer(k)->getPitch() * VIACOST;
zHeights.push_back(zHeight);
zDirs.push_back((v == frPrefRoutingDirEnum::frcHorzPrefRoutingDir));
if (k + 1 <= getTech()->getTopLayerNum() && getTech()->getLayer(k + 1)->getType() == frLayerTypeEnum::CUT) {
auto viaDef = getTech()->getLayer(k + 1)->getDefaultViaDef();
frVia via(viaDef);
frBox layer1Box;
frBox layer2Box;
via.getLayer1BBox(layer1Box);
via.getLayer2BBox(layer2Box);
auto layer1HalfArea = layer1Box.width() * layer1Box.length() / 2;
auto layer2HalfArea = layer2Box.width() * layer2Box.length() / 2;
// cout <<"z = " <<zCoords.size() <<" " <<"layer1/2HalfArea = " <<layer1HalfArea <<"/" <<layer2HalfArea <<endl;
halfViaEncArea.push_back(make_pair(layer1HalfArea, layer2HalfArea));
} else {
halfViaEncArea.push_back(make_pair(0,0));
}
}
// initialize all grids
frMIdx xDim, yDim, zDim;
getDim(xDim, yDim, zDim);
bits.clear();
bits.resize(xDim*yDim*zDim, 0);
// new
prevDirs.clear();
srcs.clear();
dsts.clear();
prevDirs.resize(xDim*yDim*zDim*3, 0);
srcs.resize(xDim*yDim*zDim, 0);
dsts.resize(xDim*yDim*zDim, 0);
//for (int k = 0; k < (int)zDim; k++) {
// for (int j = 0; j < (int)yDim; j++) {
// for (int i = 0; i < (int)xDim; i++) {
// resetCost(i, j, k);
// }
// }
//}
if (enableOutput) {
cout <<"x ";
for (auto &k: xCoords) {
cout <<" " <<k;
}
cout <<endl;
cout <<"y ";
for (auto &k: yCoords) {
cout <<" " <<k;
}
cout <<endl;
cout <<"z ";
for (auto &k: zCoords) {
cout <<" " <<k;
}
cout <<endl;
cout <<"z height ";
for (auto &k: zHeights) {
cout <<" " <<k;
}
cout <<endl;
}
}
void FlexGridGraph::initEdges(const map<frCoord, map<frLayerNum, frTrackPattern* > > &xMap,
const map<frCoord, map<frLayerNum, frTrackPattern* > > &yMap,
const map<frLayerNum, frPrefRoutingDirEnum> &zMap,
const frBox &bbox, bool initDR) {
//bool enableOutput = true;
bool enableOutput = false;
frMIdx xDim, yDim, zDim;
getDim(xDim, yDim, zDim);
// initialize grid graph
frMIdx xIdx = 0, yIdx = 0, zIdx = 0;
bool flag = false;
// add cost to out-of-die edge
//frBox blockBox;
//getDesign()->getTopBlock()->getBoundaryBBox(blockBox);
//frBox viaBox, planarBox;
//frVia dVia(nullptr);
//dVia.setOrigin(frPoint(0,0));
//frCoord halfWidth = 0;
//frTransform xform;
for (auto &[layerNum, dir]: zMap) {
frLayerNum nonPrefLayerNum;
//viaBox.set(0,0,0,0);
//halfWidth = getDesign()->getTech()->getLayer(layerNum)->getWidth() / 2;
//planarBox.set(-halfWidth, -halfWidth, halfWidth, halfWidth);
if (layerNum + 2 <= getTech()->getTopLayerNum()) {
nonPrefLayerNum = layerNum + 2;
//dVia.setViaDef(getDesign()->getTech()->getLayer(layerNum + 1)->getDefaultViaDef());
//dVia.getBBox(viaBox);
} else if (layerNum - 2 >= getTech()->getBottomLayerNum()) {
nonPrefLayerNum = layerNum - 2;
} else {
nonPrefLayerNum = layerNum;
}
yIdx = 0;
for (auto &[yCoord, ySubMap]: yMap) {
auto yIt = ySubMap.find(layerNum);
auto yIt2 = ySubMap.find(layerNum+2);
auto yIt3 = ySubMap.find(nonPrefLayerNum);
bool yFound = (yIt != ySubMap.end());
bool yFound2 = (yIt2 != ySubMap.end());
bool yFound3 = (yIt3 != ySubMap.end());
xIdx = 0;
for (auto &[xCoord, xSubMap]: xMap) {
auto xIt = xSubMap.find(layerNum);
auto xIt2 = xSubMap.find(layerNum+2);
auto xIt3 = xSubMap.find(nonPrefLayerNum);
bool xFound = (xIt != xSubMap.end());
bool xFound2 = (xIt2 != xSubMap.end());
bool xFound3 = (xIt3 != xSubMap.end());
// add cost to out-of-die edge
//xform.set(frPoint(xCoord, yCoord));
//viaBox.transform(xform);
//planarBox.transform(xform);
//bool outOfDiePlanar = !blockBox.contains(planarBox);
//bool outOfDieVia = !blockBox.contains(viaBox);
bool outOfDiePlanar = false;
bool outOfDieVia = false;
//for (auto &[layerNum, dir]: zMap) {
// add edge for preferred direction
if (dir == frcHorzPrefRoutingDir && yFound) {
if (layerNum >= BOTTOM_ROUTING_LAYER) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::E)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::E, bbox, initDR);
if (yIt->second == nullptr || outOfDiePlanar) {
setGridCostE(xIdx, yIdx, zIdx);
}
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::E)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) not set" <<endl;
} else {
if (hasGridCostE(xIdx, yIdx, zIdx) != ((yIt->second || outOfDiePlanar) ? false : true)) {
cout <<"check edge cost failed (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) != 1" <<endl;
}
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E)" <<endl;
}
}
}
// via to upper layer
if (xFound2) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::U)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::U, bbox, initDR);
bool condition = (yIt->second == nullptr || xIt2->second == nullptr);
if (condition || outOfDieVia) {
setGridCostU(xIdx, yIdx, zIdx);
}
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::U)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U) not set" <<endl;
} else {
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U)" <<endl;
}
}
}
} else if (dir == frcVertPrefRoutingDir && xFound) {
if (layerNum >= BOTTOM_ROUTING_LAYER) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::N)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::N, bbox, initDR);
if (xIt->second == nullptr || outOfDiePlanar) {
setGridCostN(xIdx, yIdx, zIdx);
}
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::N)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) not set" <<endl;
} else {
if (hasGridCostN(xIdx, yIdx, zIdx) != ((xIt->second || outOfDiePlanar) ? false : true)) {
cout <<"check edge cost failed (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) != 1" <<endl;
}
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N)" <<endl;
}
}
}
// via to upper layer
if (yFound2) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::U)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::U, bbox, initDR);
bool condition = (yIt2->second == nullptr || xIt->second == nullptr);
if (condition || outOfDieVia) {
setGridCostU(xIdx, yIdx, zIdx);
}
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::U)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U) not set" <<endl;
} else {
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U)" <<endl;
}
}
}
}
// get non pref track layer --> use upper layer pref dir track if possible
if (USENONPREFTRACKS) {
// add edge for non-preferred direction
// vertical non-pref track
if (dir == frcHorzPrefRoutingDir && xFound3) {
if (layerNum >= BOTTOM_ROUTING_LAYER) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::N)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::N, bbox, initDR);
setGridCostN(xIdx, yIdx, zIdx);
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::N)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) not set" <<endl;
} else {
if (!hasGridCostN(xIdx, yIdx, zIdx)) {
cout <<"check edge cost failed (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) != 1" <<endl;
}
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N)" <<endl;
}
}
}
// horizontal non-pref track
} else if (dir == frcVertPrefRoutingDir && yFound3) {
if (layerNum >= BOTTOM_ROUTING_LAYER) {
if (enableOutput) {
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::E)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) already set" <<endl;
}
}
flag = addEdge(xIdx, yIdx, zIdx, frDirEnum::E, bbox, initDR);
setGridCostE(xIdx, yIdx, zIdx);
if (enableOutput) {
if (!flag) {
cout <<"edge out of bound (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E)" <<endl;
} else if (!hasEdge(xIdx, yIdx, zIdx, frDirEnum::E)) {
cout <<"Error: (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) not set" <<endl;
} else {
if (!hasGridCostE(xIdx, yIdx, zIdx)) {
cout <<"check edge cost failed (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) != 1" <<endl;
}
cout <<"add edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E)" <<endl;
}
}
}
}
}
++xIdx;
}
++yIdx;
}
++zIdx;
}
}
// initialization: update grid graph topology, does not assign edge cost
void FlexGridGraph::init(const frBox &routeBBox, const frBox &extBBox,
map<frCoord, map<frLayerNum, frTrackPattern* > > &xMap,
map<frCoord, map<frLayerNum, frTrackPattern* > > &yMap,
bool initDR) {
bool enableOutput = false;
// get tracks intersecting with the Maze bbox
map<frLayerNum, frPrefRoutingDirEnum> zMap;
initTracks(xMap, yMap, zMap, extBBox);
initGrids(xMap, yMap, zMap); // buildGridGraph
initEdges(xMap, yMap, zMap, routeBBox, initDR); // add edges and edgeCost
if (enableOutput) {
for(int i = 0; i < (int)xCoords.size(); i++) {
for(int j = 0; j < (int)yCoords.size(); j++) {
for(int k = 0; k < (int)zCoords.size(); k++) {
cout <<"test x/y/z/E/N/U = " <<i <<" " <<j <<" " <<k <<" "
<<hasGridCostE(i, j, k) <<" "
<<hasGridCostN(i, j, k) <<" "
<<"0" <<" " <<endl;
}
}
}
}
}
// initialization helpers
// get all tracks inetersecting with the Maze bbox, left/bottom are inclusive
void FlexGridGraph::initTracks(map<frCoord, map<frLayerNum, frTrackPattern* > > &xMap,
map<frCoord, map<frLayerNum, frTrackPattern* > > &yMap,
map<frLayerNum, frPrefRoutingDirEnum> &zMap,
const frBox &bbox) {
bool enableOutput = false;
//bool enableOutput = true;
for (auto &layer: getTech()->getLayers()) {
if (layer->getType() != frLayerTypeEnum::ROUTING) {
continue;
}
if (enableOutput) {
cout <<"initTracks: " <<layer->getName() <<endl <<flush;
}
frLayerNum currLayerNum = layer->getLayerNum();
frPrefRoutingDirEnum currPrefRouteDir = layer->getDir();
//bool hasTrack = false;
for (auto &tp: getDesign()->getTopBlock()->getTrackPatterns(currLayerNum)) {
bool flag = USENONPREFTRACKS ?
(tp->isHorizontal() && currPrefRouteDir == frcVertPrefRoutingDir ||
!tp->isHorizontal() && currPrefRouteDir == frcHorzPrefRoutingDir) :
true;
if (flag) {
//cout <<"checkPoint 1" <<endl <<flush;
int trackNum = ((tp->isHorizontal() ? bbox.left() : bbox.bottom()) - tp->getStartCoord()) / (int)tp->getTrackSpacing();
if (trackNum < 0) {
trackNum = 0;
}
if (trackNum * (int)tp->getTrackSpacing() + tp->getStartCoord() < (tp->isHorizontal() ? bbox.left() : bbox.bottom())) {
++trackNum;
}
for (;
trackNum < (int)tp->getNumTracks() &&
trackNum * (int)tp->getTrackSpacing() + tp->getStartCoord() < (tp->isHorizontal() ? bbox.right() : bbox.top());
++trackNum) {
frCoord trackLoc = trackNum * tp->getTrackSpacing() + tp->getStartCoord();
//cout <<"checkPoint 2" <<endl <<flush;
//hasTrack = true;
if (tp->isHorizontal()) {
xMap[trackLoc][currLayerNum] = tp.get();
} else {
yMap[trackLoc][currLayerNum] = tp.get();
}
}
}
}
//if (hasTrack) {
//cout <<"checkPoint 3" <<endl <<flush;
zMap[currLayerNum] = currPrefRouteDir;
//}
}
if (enableOutput) {
cout <<"finish initTracks" <<endl <<flush;
}
}
void FlexGridGraph::resetStatus() {
//frMIdx xDim, yDim, zDim;
//getDim(xDim, yDim, zDim);
//for (frMIdx z = 0; z < zDim; z++) {
// for (frMIdx y = 0; y < yDim; y++) {
// for (frMIdx x = 0; x < xDim; x++) {
// //resetSrc(x, y, z);
// //resetDst(x, y, z);
// setPrevAstarNodeDir(x, y, z, frDirEnum::UNKNOWN);
// }
// }
//}
resetSrc();
resetDst();
resetPrevNodeDir();
}
void FlexGridGraph::resetSrc() {
srcs.assign(srcs.size(), 0);
}
void FlexGridGraph::resetDst() {
dsts.assign(dsts.size(), 0);
}
void FlexGridGraph::resetPrevNodeDir() {
//frMIdx xDim, yDim, zDim;
//getDim(xDim, yDim, zDim);
//for (frMIdx z = 0; z < zDim; z++) {
// for (frMIdx y = 0; y < yDim; y++) {
// for (frMIdx x = 0; x < xDim; x++) {
// setPrevAstarNodeDir(x, y, z, frDirEnum::UNKNOWN);
// }
// }
//}
prevDirs.assign(prevDirs.size(), 0);
}
// print the grid graph with edge and vertex for debug purpose
void FlexGridGraph::print() {
ofstream mazeLog(OUT_MAZE_FILE.c_str());
if (mazeLog.is_open()) {
// print edges
frBox gridBBox;
getBBox(gridBBox);
mazeLog << "printing Maze grid (" << gridBBox.left() << ", " << gridBBox.bottom() << ") -- ("
<< gridBBox.right() << ", " << gridBBox.top() << ")\n";
frMIdx xDim, yDim, zDim;
getDim(xDim, yDim, zDim);
if (xDim == 0 || yDim == 0 || zDim == 0) {
cout << "Error: dimension == 0\n";
return;
} else {
cout << "(xDim, yDim, zDim) = (" << xDim << ", " << yDim << ", " << zDim << ")\n";
}
// mazeLog << "xDim = " << xDim << ", yDim = " << yDim << ", zDim = " << zDim << "\n";
frPoint p;
for (frMIdx xIdx = 0; xIdx < xDim; ++xIdx) {
// mazeLog << "xxxIdx = " << xIdx << "\n" << std::flush;
for (frMIdx yIdx = 0; yIdx < yDim; ++yIdx) {
for (frMIdx zIdx = 0; zIdx < zDim; ++zIdx) {
// mazeLog << "xIdx = " << xIdx << ", yIdx = " << yIdx << ", zIdx = " << zIdx << "\n" << std::flush;
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::N)) {
if (yIdx + 1 >= yDim) {
cout <<"Error: no edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", N) " <<yDim <<endl;
continue;
}
mazeLog << "Edge: " << getPoint(p, xIdx, yIdx).x() << " " << getPoint(p, xIdx, yIdx).y() << " " << zIdx
<< " " << getPoint(p, xIdx, yIdx+1).x() << " " << getPoint(p, xIdx, yIdx+1).y() << " " << zIdx << "\n";
}
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::E)) {
if (xIdx + 1 >= xDim) {
cout <<"Error: no edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", E) " << xDim <<endl;
continue;
}
mazeLog << "Edge: " << getPoint(p, xIdx, yIdx).x() << " " << getPoint(p, xIdx, yIdx).y() << " " << zIdx
<< " " << getPoint(p, xIdx+1, yIdx).x() << " " << getPoint(p, xIdx+1, yIdx).y() << " " << zIdx << "\n";
}
if (hasEdge(xIdx, yIdx, zIdx, frDirEnum::U)) {
if (zIdx + 1 >= zDim) {
cout <<"Error: no edge (" <<xIdx <<", " <<yIdx <<", " <<zIdx <<", U) " <<zDim <<endl;
continue;
}
mazeLog << "Edge: " << getPoint(p, xIdx, yIdx).x() << " " << getPoint(p, xIdx, yIdx).y() << " " << zIdx
<< " " << getPoint(p, xIdx, yIdx).x() << " " << getPoint(p, xIdx, yIdx).y() << " " << zIdx + 1 << "\n";
}
}
}
}
} else {
cout << "Error: Fail to open maze log\n";
}
}