/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: MetricBoundingBox3.java
* Written by Team 3: Christian Wittner
*
* This code has been developed at the Karlsruhe Institute of Technology (KIT), Germany,
* as part of the course "Multicore Programming in Practice: Tools, Models, and Languages".
* Contact instructor: Dr. Victor Pankratius (pankratius@ipd.uka.de)
*
* Copyright (c) 2010 Sun Microsystems and Static Free Software
*
* 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.placement.genetic1.g1;
import com.sun.electric.tool.placement.PlacementFrame.PlacementNetwork;
import com.sun.electric.tool.placement.PlacementFrame.PlacementPort;
import com.sun.electric.tool.placement.genetic1.Chromosome;
import com.sun.electric.tool.placement.genetic1.Metric;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
/**
* Calculate Bounding Box metric for all networks in a chromosome.
*/
public class MetricBoundingBox3 implements Metric {
// short[] represents ports x and y offset
static HashMap<int[], Integer> port2ProxyIndexMap;
// first level is net level
// second level is port level
// last level represents x and y offset
static int[][][] net2PlacementPortsXYOffset;
static Level LOG_LEVEL = Level.FINER;
public static double cutOffThreshhold = .85;
public static int nodeThreshhold = 100;
public MetricBoundingBox3(List<PlacementNetwork> networks,
PlacementNodeProxy[] nodeProxies) {
if (port2ProxyIndexMap == null)
generatePortToProxyIndexMap(networks, nodeProxies);
}
void generatePortToProxyIndexMap(List<PlacementNetwork> networks,
PlacementNodeProxy[] nodeProxies) {
if (GeneticPlacement.IS_LOGGING_ENABLED)
GeneticPlacement.logger.log(LOG_LEVEL,
"start precalculating portToProxyIndexMap");
int allocationCounter = 0;
int cutOffBarrier = (int) (cutOffThreshhold * nodeProxies.length);
// if node number over defined threshold ignore nets with more than
// cutoff percentage of connected nodes
// idea: it doesn't make sense to optimize a bounding box for a net
// containing all nodes
// if a node is moved within the chip the outer bounding box doesn't get
// smaller.
// it is a waste of cpu time in metric calculation.
if (nodeProxies.length > nodeThreshhold) {
// calculate number of nets below cutoff for array allocation
for (PlacementNetwork net : networks)
if (net.getPortsOnNet().size() <= cutOffBarrier)
allocationCounter++;
} else
allocationCounter = networks.size();
net2PlacementPortsXYOffset = new int[allocationCounter][][];
port2ProxyIndexMap = new HashMap<int[], Integer>(networks.size());
PlacementNetwork curNet;
PlacementPort curPort;
int netIndex = 0;
for (int i = 0; i < networks.size(); i++) {
curNet = networks.get(i);
// if cutting of and network to big skip it
if (nodeProxies.length > nodeThreshhold
&& curNet.getPortsOnNet().size() > cutOffBarrier)
continue;
// create array of all ports on that network
net2PlacementPortsXYOffset[netIndex] = new int[curNet.getPortsOnNet()
.size()][];
for (int p = 0; p < curNet.getPortsOnNet().size(); p++) {
curPort = curNet.getPortsOnNet().get(p);
// store ports x and y offset in map
net2PlacementPortsXYOffset[netIndex][p] = new int[2];
net2PlacementPortsXYOffset[netIndex][p][0] = (short) curPort.getOffX();
net2PlacementPortsXYOffset[netIndex][p][1] = (short) curPort.getOffY();
List<PlacementNodeProxy> nodeProxyList = Arrays
.asList(nodeProxies);
// TODO: eventual introduce a port proxy to store port2Proxy
// mapping
// Definitely take care to do this calculation only once and not
// for all threads!!
// create map to find gene representing a node containing a port
if (!port2ProxyIndexMap
.containsKey(net2PlacementPortsXYOffset[netIndex][p])) {
for (PlacementNodeProxy proxy : nodeProxies) {
if (proxy.node == curPort.getPlacementNode()) {
port2ProxyIndexMap.put(
net2PlacementPortsXYOffset[netIndex][p],
new Integer(nodeProxyList.indexOf(proxy)));
break;
}
}
}
}
netIndex++;
}
if (GeneticPlacement.IS_LOGGING_ENABLED)
GeneticPlacement.logger.log(LOG_LEVEL,
"done precalculating portToProxyIndexMap");
}
public void evaluate(List<Chromosome> population) {
for (Chromosome c : population) {
if (c.altered)
c.fitness = Double.valueOf(0);
}
// TODO:Loop Locking auf Targetmachine anpassen :)
// kann man cachezeilen groesse abfragen?
for (int[][] net : net2PlacementPortsXYOffset) {
for (Chromosome c : population) {
if (c.altered)
c.fitness = new Double(c.fitness.doubleValue() + compute(net, c));
}
}
for (Chromosome c : population) {
c.altered = false;
}
}
public double evaluate(Chromosome c) {
double sum = 0;
for (int[][] net : net2PlacementPortsXYOffset) {
// ignore nets which got only one port assigned
if (net.length == 1)
continue;
sum += compute(net, c);
}
assert sum != 0;
return sum;
}
private int getPortXOffset(int port[], short geneRotation) {
// port[0] is it's x offset port[1] the y offset
switch (geneRotation) {
case 0:
return port[0];
case 900:
return -port[1];
case 1800:
return -port[0];
case 2700:
return port[1];
default:
System.err.println(this.getClass().getName()
+ " unsupported rotation angle: " + geneRotation);
return -1;
}
}
public int getPortYOffset(int port[], short geneRotation) {
// port[0] is it's x offset port[1] the y offset
switch (geneRotation) {
case 0:
return port[1];
case 900:
return port[0];
case 1800:
return -port[1];
case 2700:
return -port[0];
default:
System.err.println(this.getClass().getName()
+ " unsupported rotation angle: " + geneRotation);
return -1;
}
}
private double compute(int[][] net, Chromosome c) {
double left, right, top, bottom;
double portX, portY;
int indexOfProxy;
// values of first cell as starting point
{
indexOfProxy = port2ProxyIndexMap.get(net[0]).intValue();
short rotation = 0;
int addendX = 0, addendY = 0;
if (indexOfProxy < c.GeneRotation.length)
{
rotation = c.GeneRotation[indexOfProxy];
addendX = c.GeneXPos[indexOfProxy];
addendY = c.GeneYPos[indexOfProxy];
}
portX = getPortXOffset(net[0], rotation) + addendX;
portY = getPortYOffset(net[0], rotation) + addendY;
left = right = portX;
top = bottom = portY;
}
// calculate rest of cells
for (int i = 1; i < net.length; i++) {
indexOfProxy = port2ProxyIndexMap.get(net[i]).intValue();
short rotation = 0;
int addendX = 0, addendY = 0;
if (indexOfProxy < c.GeneRotation.length)
{
rotation = c.GeneRotation[indexOfProxy];
addendX = c.GeneXPos[indexOfProxy];
addendY = c.GeneYPos[indexOfProxy];
}
portX = getPortXOffset(net[i], rotation) + addendX;
portY = getPortYOffset(net[i], rotation) + addendY;
if (portX < left) {
left = portX;
} else if (portX > right) {
right = portX;
}
if (portY > top) {
top = portY;
} else if (portY < bottom) {
bottom = portY;
}
}
assert (right > left || top > bottom);
return (right - left) + (top - bottom);
}
}