Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Place.java
* Silicon compiler tool (QUISC): placement
* Written by Andrew R. Kostiuk, Queen's University.
* Translated to Java by Steven M. Rubin, Sun Microsystems.
*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.sc;
import com.sun.electric.database.hierarchy.Cell;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* The placement part of the Silicon Compiler tool.
*/
public class Place
{
/** for debugging output */ private static final boolean DEBUG = false;
/** TRUE = sort cluster tree */ private static final boolean SORTFLAG = true;
/** TRUE = do net balance */ private static final boolean BALANCEFLAG = false;
/** limit of movement */ private static final int BALANCELIMIT = 2;
/** scaling factor */ private static final int VERTICALCOST = 2;
/***** general placement information *****/
static class SCPlace
{
/** number of instances */ int numInst;
/** total size of instances */ int sizeInst;
/** average size of inst */ int avgSize;
/** average height of inst */ int avgHeight;
/** number of rows */ int numRows;
/** target size of each row */ int sizeRows;
/** rows of placed cells */ List theRows;
/** start of cell list */ NBPlace plist;
/** end of cell list */ NBPlace endList;
};
private static final int BITS_PLACED = 0x01;
static final int BITS_EXTRACT = 0x02;
private static class Cluster
{
/** instance of cluster */ GetNetlist.SCNiTree node;
/** number of cluster */ int number;
/** total size of members */ double size;
};
private static class ClusterTree
{
/** cluster, null if intermediate node*/ Cluster cluster;
/** working bits */ int bits;
/** parent node */ ClusterTree parent;
/** pointer to nodes on same level */ ClusterTree next;
/** pointer to one group */ ClusterTree lPtr;
/** pointer to second group */ ClusterTree rPtr;
};
private static class ClConnect
{
/** pointers to names of nodes */ ClusterTree [] node;
/** number of connections */ int count;
private ClConnect(ClusterTree ct0, ClusterTree ct1, int c)
{
node = new ClusterTree[2];
node[0] = ct0;
node[1] = ct1;
count = c;
}
};
static class RowList
{
/** start of row cells */ NBPlace start;
/** end of row cells */ NBPlace end;
/** row number (0 = bottom) */ int rowNum;
/** current row size */ int rowSize;
};
static class NBPlace
{
/** pointer to cell */ GetNetlist.SCNiTree cell;
/** x position (0 at left) */ double xPos;
/** pointer to last in list */ NBPlace last;
/** pointer to right in list */ NBPlace next;
};
private static class Channel
{
/** number of channel */ int number;
/** list of trunks */ NBTrunk trunks;
};
private static class NBTrunk
{
/** pointer to extracted node */ GetNetlist.ExtNode ext_node;
/** minimum trunk going left */ double minX;
/** maximum trunk going right */ double maxX;
/** same in next channel */ NBTrunk same;
/** pointer to next trunk */ NBTrunk next;
};
/************************* File variables *************************/
/** global root of cluster tree */ private ClusterTree gClusterTree;
/** cost of current cluster tree */ private int currentCost;
SilComp.SilCompPrefs localPrefs;
public Place(SilComp.SilCompPrefs prefs) { localPrefs = prefs; }
/**
* Method to place the nodes in the current cell in optimal position for routing
* based upon number of connections between cells.
*
* Cluster Tree Creation:
* o Maxi-cut Algorithm
* o Minimum use for best pair choice for equal weight
* Cluster Tree Sorting:
* o Top-down cluster tree sort
* o Bottom-up cluster tree sort
* Net Balancing:
* o Independent routing channels
* o Cross refencing of trunks to improve speed
* o Effective calculation of rows in costing
*/
public String placeCells(GetNetlist gnl)
{
// check to see if currently working in a cell
if (gnl.curSCCell == null) return "No cell selected";
// create placement structure
SCPlace place = new SCPlace();
gnl.curSCCell.placement = place;
place.numInst = 0;
place.sizeInst = 0;
place.avgSize = 0;
place.avgHeight = 0;
place.numRows = localPrefs.numRows;
place.sizeRows = 0;
place.theRows = new ArrayList();
place.plist = null;
place.endList = null;
// create clusters of cells
List clusters = createClusters(gnl.curSCCell);
int numCl = clusters.size();
if (numCl == 0)
{
System.out.println("ERROR - No cells found to place. Aborting.");
return null;
}
// if there are fewer cells than rows, decrease the number of rows
if (numCl < place.numRows) place.numRows = numCl;
// create a cluster tree node for each cluster
ClusterTree nStart = null;
for (Cluster clus : clusters)
{
ClusterTree node = new ClusterTree();
node.cluster = clus;
node.parent = null;
node.next = nStart;
nStart = node;
node.lPtr = null;
node.rPtr = null;
}
// recursively create cluster tree
gClusterTree = createCTreeRecurse(nStart, gnl.curSCCell);
cTreeAddParents(gClusterTree, null);
if (DEBUG)
{
System.out.println("************ Initial placement of Clusters");
printClusterTree(gClusterTree, 0);
}
place.sizeRows = place.sizeInst / place.numRows;
// place clusters in list by sorting groups
if (SORTFLAG)
{
sortClusterTree(gClusterTree, gnl.curSCCell);
if (DEBUG)
{
System.out.println("************ Placement of Clusters after Sorting");
printClusterTree(gClusterTree, 0);
}
}
// create first row structure
RowList row = new RowList();
row.start = null;
row.end = null;
row.rowNum = 0;
row.rowSize = 0;
gnl.curSCCell.placement.theRows.add(row);
// create cell placement list from sorted cluster list
createPlaceList(gClusterTree, gnl.curSCCell);
// number placement
numberPlacement(gnl.curSCCell.placement.theRows);
if (DEBUG)
{
System.out.println("************ Placement before Net Balancing");
showPlacement(gnl.curSCCell.placement.theRows);
}
// do net balance algorithm
if (BALANCEFLAG)
{
netBalance(gnl.curSCCell);
if (DEBUG)
{
System.out.println("************ Placement after Net Balancing");
showPlacement(gnl.curSCCell.placement.theRows);
}
}
// print process time for placement
reorderRows(gnl.curSCCell.placement.theRows);
return null;
}
/**
* Method to add the parent pointer to the cluster tree by doing a preorder transversal.
* @param node pointer to current node in transversal.
* @param parent pointer to parent node.
*/
private void cTreeAddParents(ClusterTree node, ClusterTree parent)
{
if (node == null) return;
node.parent = parent;
cTreeAddParents(node.lPtr, node);
cTreeAddParents(node.rPtr, node);
}
/**
* Method to create "clusters" of cells of size one.
* @param cell pointer to complex cell.
* @return list of clusters.
*/
private List createClusters(GetNetlist.SCCell cell)
{
// find total 'size' and number of all the cells
int size = 0;
int num = 0;
int height = 0;
for (GetNetlist.SCNiTree iList : cell.niList)
{
if (iList.type == GetNetlist.LEAFCELL)
{
num++;
size += iList.size;
height += SilComp.leafCellYSize((Cell)iList.np);
}
}
List clusters = new ArrayList();
if (num == 0)
{
System.out.println("WARNING - No leaf cells found for placement");
return clusters;
}
int avgSize = size / num;
int avgHeight = height / num;
if (DEBUG)
{
System.out.println("************ Cell Statistics");
System.out.println(" Number of cells = " + num);
System.out.println(" Total length = " + size);
System.out.println(" Average size of cells = " + avgSize);
System.out.println(" Average height of cells = " + avgHeight);
}
cell.placement.numInst = num;
cell.placement.sizeInst = size;
cell.placement.avgSize = avgSize;
cell.placement.avgHeight = avgHeight;
// create cluster list
int i = 0;
boolean warn = false;
for (GetNetlist.SCNiTree node : cell.niList)
{
if (node.type != GetNetlist.LEAFCELL)
{
if (node.type == GetNetlist.COMPLEXCELL) warn = true;
continue;
}
Cluster cluster = new Cluster();
cluster.node = node;
cluster.size = node.size;
cluster.number = i++;
clusters.add(cluster);
}
if (warn)
{
System.out.println("WARNING - At least one complex cell found during Create_Clusters");
System.out.println(" - Probable cause: Forgot to do 'PULL' command");
}
return clusters;
}
/**
* Method to recursively create the cluster tree from the bottom up by pairing
* strongly connected tree nodes together. When only one tree node
* exists, this is the root and can be written to the indicated address.
* @param nodes pointer to start of tree nodes.
* @param cell pointer to parent cell.
* @return tree root.
*/
private ClusterTree createCTreeRecurse(ClusterTree nodes, GetNetlist.SCCell cell)
{
// if no node, end
if (nodes == null) return null;
// if one node, write to root and end
if (nodes.next == null) return nodes;
// create list of connections between nodes
List connectList = cTreeNumConnects(nodes, cell);
// pair by number of connects
ClusterTree nStart = cTreePair(nodes, connectList);
// recurse up a level
return createCTreeRecurse(nStart, cell);
}
/**
* Method to create a list of the number of connections from all groups to all other groups.
* @param nodes List of current nodes.
* @param cell Pointer to parent cell.
*/
private List cTreeNumConnects(ClusterTree nodes, GetNetlist.SCCell cell)
{
List connections = new ArrayList();
int nodeNum = 0;
// go through list of nodes
for ( ; nodes != null; nodes = nodes.next)
{
// check all other node
for (ClusterTree nextnode = nodes.next; nextnode != null; nextnode = nextnode.next)
{
nodeNum += 2;
// mark all extracted nodes used by first node
setExtNodesByCTree(nodes, nodeNum);
// count number of common extracted nodes
int common = countExtNodes(nextnode, nodeNum);
if (common != 0)
{
ClConnect newCon = new ClConnect(nodes, nextnode, common);
connections.add(newCon);
}
}
}
// sort number of connects from largest to smallest
Collections.sort(connections, new ConnectsByCount());
return connections;
}
private static class ConnectsByCount implements Comparator
{
public int compare(ClConnect c1, ClConnect c2)
{
return c2.count - c1.count;
}
}
/**
* Method to mark all extracted nodes references by any member of all the
* clusters in the indicated cluster tree.
* @param node pointer to cluster tree node.
* @param marker value to set flags field to.
*/
private void setExtNodesByCTree(ClusterTree node, int marker)
{
if (node == null) return;
setExtNodesByCTree(node.lPtr, marker);
// process node if cluster
if (node.cluster != null)
{
// check every port of member
for (GetNetlist.SCNiPort port = node.cluster.node.ports; port != null; port = port.next)
{
if (port.extNode == null) continue;
port.extNode.flags = marker;
}
}
setExtNodesByCTree(node.rPtr, marker);
}
/**
* Method to return the number of extracted nodes which have flag bit set only
* and is accessed by subtree.
* @param node start of cluster tree node.
* @param marker value to look for.
*/
private int countExtNodes(ClusterTree node, int marker)
{
if (node == null) return 0;
int count = countExtNodes(node.lPtr, marker);
// process node if cluster
if (node.cluster != null)
{
// check every port of member
for (GetNetlist.SCNiPort port = node.cluster.node.ports; port != null; port = port.next)
{
if (port.extNode == null) continue;
if (port.extNode.flags == marker) count++;
}
}
count += countExtNodes(node.rPtr, marker);
return count;
}
/**
* Method to pair up the given nodes by using the information in the connection list.
* @param nodes pointer to start of list of nodes.
* @param nConnects pointer to start of list of connections.
* @return new list.
*/
private ClusterTree cTreePair(ClusterTree nodes, List connectList)
{
// clear the placed flag in all tree nodes
for (ClusterTree tPtr = nodes; tPtr != null; tPtr = tPtr.next)
tPtr.bits &= ~BITS_PLACED;
// go through connection list
ClusterTree newStart = null;
if (connectList.size() > 0)
{
for (int i=0; i connectList, int index)
{
List sList = new ArrayList();
ClConnect connect = connectList.get(index);
for(int oIndex=index; oIndex theRows, SCPlace place)
{
if (cluster.node.type != GetNetlist.LEAFCELL) return;
NBPlace newPlace = new NBPlace();
newPlace.cell = cluster.node;
newPlace.xPos = 0;
cluster.node.tp = newPlace;
newPlace.next = null;
newPlace.last = place.endList;
if (place.endList == null)
{
place.plist = place.endList = newPlace;
} else
{
place.endList.next = newPlace;
place.endList = newPlace;
}
// get the last entry in the list
RowList row = theRows.get(theRows.size() - 1);
double oldCondition = place.sizeRows - row.rowSize;
double newCondition = place.sizeRows - (row.rowSize + cluster.node.size);
if ((row.rowNum + 1) < place.numRows &&
Math.abs(oldCondition) < Math.abs(newCondition))
{
RowList row2 = new RowList();
row2.start = null;
row2.end = null;
row2.rowNum = row.rowNum + 1;
row2.rowSize = 0;
theRows.add(row2);
row = row2;
}
// add to row
if ((row.rowNum % 2) != 0)
{
// odd row
if (row.end == null)
row.end = newPlace;
row.start = newPlace;
} else
{
// even row
if (row.start == null)
row.start = newPlace;
row.end = newPlace;
}
row.rowSize += cluster.node.size;
}
/**
* Method to do a net balancing on the placelist.
* @param row pointer to start of row list.
* @param cell pointer to parent cell.
*/
private void netBalance(GetNetlist.SCCell cell)
{
// create channel list
List channels = new ArrayList();
int i = 0;
NBTrunk sameTrunk = null;
do
{
Channel newChan = new Channel();
newChan.number = i;
NBTrunk trunks = null, oldTrunk = null;
// create trunk list for each channel
for (GetNetlist.ExtNode nList = cell.exNodes; nList != null; nList = nList.next)
{
NBTrunk nTrunk = new NBTrunk();
nTrunk.ext_node = nList;
nTrunk.minX = 0;
nTrunk.maxX = 0;
nTrunk.same = null;
if (sameTrunk == null)
{
nList.ptr = nTrunk;
} else
{
sameTrunk.same = nTrunk;
sameTrunk = sameTrunk.next;
}
nTrunk.next = null;
if (oldTrunk == null)
{
trunks = oldTrunk = nTrunk;
} else
{
oldTrunk.next = nTrunk;
oldTrunk = nTrunk;
}
}
newChan.trunks = trunks;
channels.add(newChan);
sameTrunk = trunks;
i++;
} while ((i + 1) < cell.placement.numRows);
// report current placement evaluation
if (DEBUG)
System.out.println("Evaluation before Net-Balancing = " +
nBCost(cell.placement.theRows, channels, cell));
// do the net balance for each cell
nBAllCells(cell, channels);
// number placement
nBRebalanceRows(cell.placement.theRows, cell.placement);
numberPlacement(cell.placement.theRows);
// report new evaluation
if (DEBUG)
System.out.println("Evaluation after Net-Balancing = %d" +
nBCost(cell.placement.theRows, channels, cell));
}
/**
* Method to do a net balance for each cell on at a time. Use the SCNiTree to
* insure that each cell is processed.
* @param cell pointer to parent cell.
* @param channels pointer to start of channel list.
*/
private void nBAllCells(GetNetlist.SCCell cell, List channels)
{
// process cell
for (GetNetlist.SCNiTree iList : cell.niList)
{
if (iList.type == GetNetlist.LEAFCELL)
nBDoCell((NBPlace)iList.tp, channels, cell);
}
}
/**
* Method to do a net balance for the indicated instance.
* @param place pointer to place of instance.
* @param channels pointer to channel list of trunks.
* @param cell parent complex cell.
*/
private void nBDoCell(NBPlace place, List channels, GetNetlist.SCCell cell)
{
if (place == null) return;
// find cost at present location and set as current minimum
List theRows = cell.placement.theRows;
int minCost = nBCost(theRows, channels, cell);
int pos = 0;
// temporarily remove from list
NBPlace oldLast = place.last;
NBPlace oldNext = place.next;
nBRemove(place, theRows);
// check locations backwards for nb_limit
int nPos = -1;
for (NBPlace nPlace = oldLast; nPos >= -BALANCELIMIT; nPlace = nPlace.last)
{
if (nPlace != null)
{
// temporarily insert in list
nBInsertBefore(place, nPlace, theRows);
// check new cost
int cost = nBCost(theRows, channels, cell);
if (cost < minCost)
{
minCost = cost;
pos = nPos;
}
// remove place from list
nBRemove(place, theRows);
} else
{
break;
}
nPos--;
}
// check forward locations for nb_limit
nPos = 1;
for (NBPlace nPlace = oldNext; nPos < BALANCELIMIT; nPlace = nPlace.next)
{
if (nPlace != null)
{
// temporarily insert in list
nBInsertAfter(place, nPlace, theRows);
// check new cost
int cost = nBCost(theRows, channels, cell);
if (cost < minCost)
{
minCost = cost;
pos = nPos;
}
// remove place from list
nBRemove(place, theRows);
} else
{
break;
}
nPos++;
}
// move if necessary
if (pos > 0)
{
while(pos-- > 1)
{
oldNext = oldNext.next;
}
nBInsertAfter(place, oldNext, theRows);
} else if (pos < 0)
{
while(pos++ < -1)
{
oldLast = oldLast.last;
}
nBInsertBefore(place, oldLast, theRows);
} else
{
if (oldLast != null)
{
nBInsertAfter(place, oldLast, theRows);
} else
{
nBInsertBefore(place, oldNext, theRows);
}
}
}
/**
* Method to return cost of the indicated placement.
* @param rows pointer to start of list or rows.
* @param channels pointer to list of channels.
* @param cell pointer to parent cell.
* @return cost.
*/
private int nBCost(List theRows, List channels, GetNetlist.SCCell cell)
{
// initialize all trunks
for(Channel nChan : channels)
{
for (NBTrunk nTrunk = nChan.trunks; nTrunk != null; nTrunk = nTrunk.next)
{
nTrunk.minX = Double.MAX_VALUE;
nTrunk.maxX = -Double.MAX_VALUE;
}
}
// check all rows
int chanPos = 0;
Channel nChan = channels.get(chanPos);
boolean above = true;
int dis = 0;
int rowNum = 0;
int maxRowSize = cell.placement.sizeRows + (cell.placement.avgSize >>1);
RowList rows = theRows.get(0);
for (NBPlace nPlace = rows.start; nPlace != null; nPlace = nPlace.next)
{
// check for room in current row
if ((rowNum % 2) != 0)
{
// odd row
if ((dis - nPlace.cell.size) < 0)
{
if ((rowNum + 1) < cell.placement.numRows)
{
rowNum++;
dis = 0;
if (above ^= true)
{
chanPos++;
nChan = channels.get(chanPos);
}
}
}
} else
{
// even row
if ((dis + nPlace.cell.size) > maxRowSize)
{
if ((rowNum + 1) < cell.placement.numRows)
{
rowNum++;
dis = maxRowSize;
if (above ^= true)
{
chanPos++;
nChan = channels.get(chanPos);
}
}
}
}
// check all ports on instance
for (GetNetlist.SCNiPort port = nPlace.cell.ports; port != null; port = port.next)
{
// find the correct trunk
NBTrunk nTrunk = (NBTrunk)port.extNode.ptr;
if (nTrunk == null) continue;
for (int i = nChan.number; i != 0; i--)
nTrunk = nTrunk.same;
if (nTrunk.minX == Double.MAX_VALUE)
{
if (!above && nTrunk.same != null)
nTrunk = nTrunk.same;
}
double pos = 0;
if ((rowNum % 2) != 2)
{
pos = dis - port.xPos;
} else
{
pos = dis + port.xPos;
}
nTrunk.minX = Math.min(nTrunk.minX, pos);
nTrunk.maxX = Math.max(nTrunk.maxX, pos);
}
if ((rowNum % 2) != 2)
{
dis -= nPlace.cell.size;
} else
{
dis += nPlace.cell.size;
}
}
// calculate cost
int cost = 0;
// calculate horizontal costs
for(Channel aChan : channels)
{
nChan = aChan;
for (NBTrunk nTrunk = nChan.trunks; nTrunk != null; nTrunk = nTrunk.next)
{
if (nTrunk.minX != Double.MAX_VALUE)
cost += Math.abs(nTrunk.maxX - nTrunk.minX);
}
}
// calculate vertical cost
for (NBTrunk nTrunk = (channels.get(0)).trunks; nTrunk != null; nTrunk = nTrunk.next)
{
NBTrunk fTrunk = null;
int fCount = 0, count = 0;
for (NBTrunk sTrunk = nTrunk; sTrunk != null; sTrunk = sTrunk.same)
{
if (sTrunk.minX != Double.MAX_VALUE)
{
double fMinX = 0, fMaxX = 0;
if (fTrunk == null)
{
fTrunk = sTrunk;
fMinX = sTrunk.minX;
fMaxX = sTrunk.maxX;
fCount = count;
} else
{
// add new vertical
cost += (count - fCount) * cell.placement.avgHeight * VERTICALCOST;
fCount = count;
// additional horizontal
if (fMaxX < sTrunk.minX)
{
cost += Math.abs(sTrunk.minX - fMaxX);
fMaxX = sTrunk.maxX;
} else if (fMinX > sTrunk.maxX)
{
cost += Math.abs(fMinX - sTrunk.maxX);
fMinX = sTrunk.minX;
} else
{
if (fMinX > sTrunk.minX) fMinX = sTrunk.minX;
if (fMaxX < sTrunk.maxX) fMaxX = sTrunk.maxX;
}
}
}
count++;
}
}
return cost;
}
/**
* Method to remove the indicated placed instance and clean up the rows structures.
* @param place pointer to place to be removed.
* @param rows pointer to start of row list.
*/
private void nBRemove(NBPlace place, List theRows)
{
NBPlace oldNext = place.next;
NBPlace oldLast = place.last;
if (place.last != null)
place.last.next = oldNext;
if (place.next != null)
place.next.last = oldLast;
// check if row change
for(RowList row : theRows)
{
if (row.start == place)
{
if ((row.rowNum % 2) != 0)
{
row.start = oldLast;
} else
{
row.start = oldNext;
}
}
if (row.end == place)
{
if ((row.rowNum % 2) != 2)
{
row.end = oldNext;
} else
{
row.end = oldLast;
}
}
}
}
/**
* Module to insert the indicated place before the indicated second place and
* clear up the row markers if necessary.
* @param place pointer to place to be inserted.
* @param oldPlace pointer to place to be inserted before.
* @param rows start of list of row markers.
*/
private void nBInsertBefore(NBPlace place, NBPlace oldPlace, List theRows)
{
place.next = oldPlace;
if (oldPlace != null)
{
place.last = oldPlace.last;
if (oldPlace.last != null)
oldPlace.last.next = place;
oldPlace.last = place;
} else
{
place.last = null;
}
// check if row change
for(RowList row : theRows)
{
if (row.start == oldPlace)
{
if ((row.rowNum % 2) != 0)
{
// EMPTY
} else
{
row.start = place;
}
}
if (row.end == oldPlace)
{
if ((row.rowNum % 2) != 0)
row.end = place;
}
}
}
/**
* Method to insert the indicated place after the indicated second place and
* clear up the row markers if necessary.
* @param place pointer to place to be inserted.
* @param oldPlace pointer to place to be inserted after.
* @param rows start of list of row markers.
*/
private void nBInsertAfter(NBPlace place, NBPlace oldPlace, List theRows)
{
place.last = oldPlace;
if (oldPlace != null)
{
place.next = oldPlace.next;
if (oldPlace.next != null)
oldPlace.next.last = place;
oldPlace.next = place;
} else
{
place.next = null;
}
// check if row change
RowList rows = theRows.get(0);
for (RowList row : theRows)
{
if (row.start == oldPlace)
{
if ((row.rowNum % 2) != 0)
row.start = place;
}
if (row.end == oldPlace)
{
if ((rows.rowNum % 2) != 0)
{
// EMPTY
} else
{
row.end = place;
}
}
}
}
/**
* Method to check balancing for rows as there has been a change in placement.
* @param rows pointer to start of row list.
* @param place pointer to global placement structure.
*/
private void nBRebalanceRows(List theRows, SCPlace place)
{
int maxRowSize = place.sizeRows + (place.avgSize >> 1);
int rowPos = 0;
RowList rows = theRows.get(rowPos);
rows.rowSize = 0;
for (NBPlace nPlace = rows.start; nPlace != null; nPlace = nPlace.next)
{
if ((rows.rowNum + 1) < place.numRows &&
(rows.rowSize + nPlace.cell.size) > maxRowSize)
{
rowPos++;
rows = theRows.get(rowPos);
rows.rowSize = 0;
if ((rows.rowNum % 2) != 0)
{
rows.end = nPlace;
} else
{
rows.start = nPlace;
}
}
rows.rowSize += nPlace.cell.size;
if ((rows.rowNum % 2) != 0)
{
rows.start = nPlace;
} else
{
rows.end = nPlace;
}
}
}
/**
* Method to number the x position of all the cells in their rows.
* @param rows pointer to the start of the rows.
*/
private void numberPlacement(List theRows)
{
for (RowList row : theRows)
{
int xPos = 0;
NBPlace nPlace = row.start;
while (nPlace != null)
{
nPlace.xPos = xPos;
xPos += nPlace.cell.size;
if (nPlace == row.end) break;
if ((row.rowNum % 2) != 0)
{
nPlace = nPlace.last;
} else
{
nPlace = nPlace.next;
}
}
}
}
/**
* Method to clean up the placement rows structure by reversing the pointers
* of odd rows and breaking the snake pattern by row.
* @param rows pointer to start of row list.
*/
private void reorderRows(List theRows)
{
for(RowList row : theRows)
{
if ((row.rowNum % 2) != 0)
{
// odd row
for (NBPlace place = row.start; place != null; place = place.next)
{
NBPlace tPlace = place.next;
place.next = place.last;
place.last = tPlace;
if (place == row.end) break;
}
row.start.last = null;
row.end.next = null;
} else
{
// even row
row.start.last = null;
row.end.next = null;
}
}
}
/**
* Method to print the cells in their rows of placement.
* @param rows pointer to the start of the rows.
*/
private void showPlacement(List theRows)
{
for (RowList row : theRows)
{
System.out.println("For Row #" + row.rowNum + ", size " + row.rowSize+ ":");
NBPlace inst;
for (inst = row.start; inst != row.end;)
{
System.out.println(" " + inst.xPos + " " + inst.cell.name);
if ((row.rowNum % 2) != 0)
{
inst = inst.last;
} else
{
inst = inst.next;
}
}
System.out.println(" " + inst.xPos + " " + inst.cell.name);
}
}
/**
* Method to print the cluster placement tree by doing an inorder transversal.
* @param node pointer to cluster tree node.
* @param level current level of tree (0 = root).
*/
private void printClusterTree(ClusterTree node, int level)
{
if (node == null) return;
printClusterTree(node.lPtr, level + 1);
// process node
int i = level << 2;
StringBuffer sb = new StringBuffer();
for(int j=0; j