All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
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.
com.sun.electric.database.ImmutableNet Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: ImmutableNetLayout.java
* Written by: Dmitry Nadezhin, Sun Microsystems.
*
* Copyright (c) 2011, 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.database;
import com.sun.electric.database.id.CellId;
import com.sun.electric.database.id.CellUsage;
import com.sun.electric.database.id.ExportId;
import com.sun.electric.database.id.NodeProtoId;
import com.sun.electric.database.id.PortProtoId;
import com.sun.electric.database.id.PrimitiveNodeId;
import com.sun.electric.database.id.PrimitivePortId;
import com.sun.electric.technology.ArcProto;
import com.sun.electric.technology.PrimitiveNode;
import com.sun.electric.technology.PrimitivePort;
import com.sun.electric.technology.TechPool;
import com.sun.electric.technology.technologies.Artwork;
import com.sun.electric.technology.technologies.Generic;
import com.sun.electric.technology.technologies.Schematics;
import com.sun.electric.util.collections.ImmutableArrayList;
import java.io.PrintStream;
import java.util.Arrays;
/**
*
*/
public class ImmutableNet {
private static boolean DEBUG = false;
final CellTree cellTree;
final TechPool techPool;
final Schematics schemTech;
final PrimitivePortId busPinPortId;
final ArcProto busArc;
final CellBackup cellBackup;
final CellRevision cellRevision;
final CellId cellId;
final ImmutableArrayList exports;
final ImmutableArrayList nodes;
final ImmutableArrayList arcs;
final int numExports;
final int numNodes;
final int numArcs;
/**
* nodeIndex by nodeId.
*/
private final int[] nodeIndexByNodeId;
/**
* nodeIndex by nodeId.
*/
private final int[] arcIndexByArcId;
/** Node offsets. */
final int[] ni_pi;
final int arcsOffset;
final int[] drawns;
public final int numDrawns;
public final int numExportedDrawns;
public final int numConnectedDrawns;
public ImmutableNet(CellTree cellTree) {
this.cellTree = cellTree;
techPool = cellTree.techPool;
Generic genericTech = techPool.getGeneric();
Artwork artworkTech = techPool.getArtwork();
schemTech = techPool.getSchematics();
PrimitiveNode invisiblePinNode = genericTech != null ? genericTech.invisiblePinNode : null;
PrimitiveNode simProbeNode = genericTech != null ? genericTech.simProbeNode : null;
PrimitiveNode pinNode = artworkTech != null ? artworkTech.pinNode : null;
busPinPortId = schemTech != null ? schemTech.busPinNode.getPort(0).getId() : null;
busArc = schemTech != null ? schemTech.bus_arc : null;
cellBackup = cellTree.top;
cellRevision = cellBackup.cellRevision;
exports = cellRevision.exports;
nodes = cellRevision.nodes;
arcs = cellRevision.arcs;
numExports = cellRevision.exports.size();
numNodes = cellRevision.nodes.size();
numArcs = cellRevision.arcs.size();
cellId = cellRevision.d.cellId;
boolean sameNodeIdAndIndex = true;
int maxNodeId = -1;
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = nodes.get(nodeIndex);
sameNodeIdAndIndex = sameNodeIdAndIndex && n.nodeId == nodeIndex;
maxNodeId = Math.max(maxNodeId, n.nodeId);
}
if (!sameNodeIdAndIndex) {
nodeIndexByNodeId = new int[maxNodeId + 1];
Arrays.fill(nodeIndexByNodeId, -1);
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = nodes.get(nodeIndex);
nodeIndexByNodeId[n.nodeId] = nodeIndex;
}
} else {
nodeIndexByNodeId = null;
}
boolean sameArcIdAndIndex = true;
int maxArcId = -1;
for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) {
ImmutableArcInst a = arcs.get(arcIndex);
sameArcIdAndIndex = sameArcIdAndIndex && a.arcId == arcIndex;
maxArcId = Math.max(maxArcId, a.arcId);
}
if (!sameArcIdAndIndex) {
arcIndexByArcId = new int[maxArcId + 1];
Arrays.fill(arcIndexByArcId, -1);
for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) {
ImmutableArcInst a = arcs.get(arcIndex);
arcIndexByArcId[a.arcId] = arcIndex;
}
} else {
arcIndexByArcId = null;
}
ni_pi = new int[numNodes];
int offset = numExports;
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = nodes.get(nodeIndex);
ni_pi[nodeIndex] = offset;
offset += getNumPorts(n.protoId);
}
arcsOffset = offset;
drawns = initMap(arcsOffset + numArcs);
// Connect exports to their original ports
for (int exportIndex = 0; exportIndex < cellRevision.exports.size(); exportIndex++) {
ImmutableExport e = cellRevision.exports.get(exportIndex);
if (!isIsolated(e.originalPortId)) {
connectMap(drawns, exportIndex, mapIndex(e.originalNodeId, e.originalPortId));
if (DEBUG) {
System.err.println("Connect export " + exportIndex + " " + mapIndex(e.originalNodeId, e.originalPortId));
}
}
}
// Connect arcs to their ends
for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) {
ImmutableArcInst a = cellRevision.arcs.get(arcIndex);
ArcProto ap = techPool.getArcProto(a.protoId);
if (ap.getFunction() == ArcProto.Function.NONELEC) {
continue;
}
if (!(isIsolated(a.tailPortId) || a.tailPortId == busPinPortId && ap != busArc)) {
connectMap(drawns, arcsOffset + arcIndex, mapIndex(a.tailNodeId, a.tailPortId));
if (DEBUG) {
System.err.println("Connect tail " + (arcsOffset + arcIndex) + " " + mapIndex(a.tailNodeId, a.tailPortId));
}
}
if (!(isIsolated(a.headPortId) || a.headPortId == busPinPortId && ap != busArc)) {
connectMap(drawns, arcsOffset + arcIndex, mapIndex(a.headNodeId, a.headPortId));
if (DEBUG) {
System.err.println("Connect head " + (arcsOffset + arcIndex) + " " + mapIndex(a.headNodeId, a.headPortId));
}
}
}
// Internal connections on primitive nodes
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = cellRevision.nodes.get(nodeIndex);
if (!(n.protoId instanceof PrimitiveNodeId)) {
continue;
}
PrimitiveNode pn = techPool.getPrimitiveNode((PrimitiveNodeId) n.protoId);
if (pn.getNumPorts() <= 1) {
continue;
}
int mapOffset = ni_pi[nodeIndex];
for (int i = 1; i < pn.getNumPorts(); i++) {
PrimitivePort ppi = pn.getPort(i);
for (int j = 0; j < i; j++) {
PrimitivePort ppj = pn.getPort(j);
if (ppi.getTopology() == ppj.getTopology()) {
assert !ppi.isIsolated() && !ppj.isIsolated();
connectMap(drawns, mapOffset + i, mapOffset + j);
if (DEBUG) {
System.err.println("Connect topology " + (mapOffset + i) + " " + (mapOffset + j));
}
}
}
}
}
if (DEBUG) {
printDrawns(System.err, "before closure");
}
closureMap(drawns);
if (DEBUG) {
printDrawns(System.err, "after closure");
}
int curDrawn = 0;
// Register drawns on exports
for (int exportIndex = 0; exportIndex < cellRevision.exports.size(); exportIndex++) {
if (addDrawn(exportIndex, curDrawn)) {
curDrawn++;
}
}
numExportedDrawns = curDrawn;
// Register drawns on arcs
for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) {
ImmutableArcInst a = cellRevision.arcs.get(arcIndex);
ArcProto ap = techPool.getArcProto(a.protoId);
if (ap.getFunction() == ArcProto.Function.NONELEC) {
nullDrawn(arcsOffset + arcIndex);
} else if (addDrawn(arcsOffset + arcIndex, curDrawn)) {
curDrawn++;
}
}
numConnectedDrawns = curDrawn;
// Register drawns on port insts
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = cellRevision.nodes.get(nodeIndex);
int mapOffset = ni_pi[nodeIndex];
if (n.protoId instanceof CellId) {
if (!isIconOfParent(n)) {
for (int portIndex = 0, numPortInsts = getNumPorts(n.protoId); portIndex < numPortInsts; portIndex++) {
if (addDrawn(mapOffset + portIndex, curDrawn)) {
curDrawn++;
}
}
continue;
}
} else {
PrimitiveNode pn = techPool.getPrimitiveNode((PrimitiveNodeId) n.protoId);
if (!(pn.getFunction() == PrimitiveNode.Function.ART && pn != simProbeNode
|| pn == pinNode
|| pn == invisiblePinNode)) {
for (int portIndex = 0, numPortInsts = getNumPorts(n.protoId); portIndex < numPortInsts; portIndex++) {
if (pn.getPort(portIndex).isIsolated()) {
nullDrawn(mapOffset + portIndex);
} else if (addDrawn(mapOffset + portIndex, curDrawn)) {
curDrawn++;
}
}
continue;
}
}
// Don't make drawns for unconnected port insts in this case
for (int portIndex = 0, numPortInsts = getNumPorts(n.protoId); portIndex < numPortInsts; portIndex++) {
addDrawn(mapOffset + portIndex, -1);
}
}
numDrawns = curDrawn;
for (int i = 0; i < drawns.length; i++) {
int d = drawns[i];
assert d < 0;
drawns[i] = -2 - d;
}
if (DEBUG) {
printDrawns(System.err, "at the end");
}
}
public void printDrawns(PrintStream out, String msg) {
out.println("Drawns of " + cellId + " " + msg);
for (int exportIndex = 0; exportIndex < numExports; exportIndex++) {
ImmutableExport e = exports.get(exportIndex);
out.println("Export " + e.name + " " + getDrawn(e.exportId) + " " + drawns[exportIndex]);
}
for (int nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) {
ImmutableNodeInst n = nodes.get(nodeIndex);
int mapOffset = ni_pi[nodeIndex];
for (int portIndex = 0, numPortInsts = getNumPorts(n.protoId); portIndex < numPortInsts; portIndex++) {
if (n.protoId instanceof CellId) {
ImmutableExport e = getSubTree((CellId) n.protoId).top.cellRevision.exports.get(portIndex);
out.println("PortInst " + n.name + " " + e.exportId.parentId + ":" + e.name + " " + getDrawn(n, e.exportId) + " " + drawns[mapOffset + portIndex]);
} else {
PrimitivePort p = techPool.getPrimitiveNode((PrimitiveNodeId) n.protoId).getPort(portIndex);
out.println("PortInst " + n.name + " " + n.protoId + ":" + p.getName() + " " + getDrawn(n, p.getId()) + " " + drawns[mapOffset + portIndex]);
}
}
}
for (int arcIndex = 0; arcIndex < numArcs; arcIndex++) {
ImmutableArcInst a = arcs.get(arcIndex);
out.println("Arc " + a.name + " " + getDrawn(a) + " " + drawns[arcsOffset + arcIndex]);
}
}
public int getDrawn(ExportId exportId) {
assert exportId.parentId == cellId;
int exportIndex = cellRevision.getExportIndexByExportId(exportId);
assert exports.get(exportIndex).exportId == exportId;
return drawns[exportIndex];
}
public int getDrawn(ImmutableNodeInst n, PortProtoId portId) {
int nodeIndex = nodeIndexByNodeId(n.nodeId);
assert nodes.get(nodeIndex) == n;
return drawns[mapIndex(n.nodeId, portId)];
}
public int getDrawn(ImmutableArcInst a) {
int arcIndex = arcIndexByArcId(a.arcId);
assert arcs.get(arcIndex) == a;
return drawns[arcsOffset + arcIndex];
}
private void nullDrawn(int mapIndex) {
assert drawns[mapIndex] == mapIndex;
drawns[mapIndex] = -1;
}
private boolean addDrawn(int mapIndex, int drawn) {
if (drawns[mapIndex] < 0) {
return false;
}
int baseIndex = drawns[mapIndex];
int baseDrawn = drawns[baseIndex];
if (baseDrawn < 0) {
drawns[mapIndex] = baseDrawn;
return false;
}
drawns[mapIndex] = drawns[baseIndex] = -2 - drawn;
return true;
}
private int mapIndex(int nodeId, PortProtoId portId) {
return ni_pi[nodeIndexByNodeId(nodeId)] + getPortIndex(portId);
}
int nodeIndexByNodeId(int nodeId) {
return nodeIndexByNodeId != null ? nodeIndexByNodeId[nodeId] : nodeId;
}
int arcIndexByArcId(int arcId) {
return arcIndexByArcId != null ? arcIndexByArcId[arcId] : arcId;
}
int getNumPorts(NodeProtoId nodeProtoId) {
if (nodeProtoId instanceof CellId) {
return getSubTree((CellId) nodeProtoId).top.cellRevision.exports.size();
} else {
return techPool.getPrimitiveNode((PrimitiveNodeId) nodeProtoId).getNumPorts();
}
}
int getPortIndex(PortProtoId portId) {
if (portId instanceof ExportId) {
return getSubTree((CellId) portId.parentId).top.cellRevision.getExportIndexByExportId((ExportId) portId);
} else {
return techPool.getPrimitivePort((PrimitivePortId) portId).getPortIndex();
}
}
/**
* Method to tell whether this NodeInst is an icon of its parent.
* Electric does not allow recursive circuit hierarchies (instances of Cells inside of themselves).
* However, it does allow one exception: a schematic may contain its own icon for documentation purposes.
* This method determines whether this NodeInst is such an icon.
* @return true if this NodeInst is an icon of its parent.
*/
boolean isIconOfParent(ImmutableNodeInst n) {
if (!(n.protoId instanceof CellId)) {
return false;
}
CellBackup subCell = getSubTree((CellId) n.protoId).top;
CellId subCellId = subCell.cellRevision.d.cellId;
return subCellId.isIcon() && cellId.isSchematic() && subCellId.libId == cellId.libId
&& subCell.cellRevision.d.groupName.equals(cellRevision.d.groupName);
}
private CellTree getSubTree(CellId cellId) {
CellUsage cu = cellTree.top.cellRevision.d.cellId.getUsageIn(cellId);
return cellTree.subTrees[cu.indexInParent];
}
private boolean isIsolated(PortProtoId portId) {
return (portId instanceof PrimitivePortId && techPool.getPrimitivePort((PrimitivePortId) portId).isIsolated());
}
/**
* Init equivalence map.
* @param size numeber of elements in equivalence map
* @return integer array representing equivalence map consisting of disjoint elements.
*/
static int[] initMap(int size) {
int[] map = new int[size];
for (int i = 0; i < map.length; i++) {
map[i] = i;
}
return map;
}
/**
* Merge classes of equivalence map to which elements a1 and a2 belong.
* Returns true if the classes were different
*/
static boolean connectMap(int[] map, int a1, int a2) {
int m1, m2, m;
for (m1 = a1; map[m1] != m1; m1 = map[m1]);
for (m2 = a2; map[m2] != m2; m2 = map[m2]);
boolean changed = m1 != m2;
m = m1 < m2 ? m1 : m2;
for (;;) {
int k = map[a1];
map[a1] = m;
if (a1 == k) {
break;
}
a1 = k;
}
for (;;) {
int k = map[a2];
map[a2] = m;
if (a2 == k) {
break;
}
a2 = k;
}
return changed;
}
/**
* Obtain canonical representation of equivalence map.
*/
static void closureMap(int[] map) {
for (int i = 0; i < map.length; i++) {
map[i] = map[map[i]];
}
}
}