📄 mimicstitch.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: MimicStitch.java * Routing tool: Mimic Stitcher (duplicates user's routes elsewhere in the cell). * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2003 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.routing;import com.sun.electric.database.ImmutableArcInst;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.EDatabase;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.id.ArcProtoId;import com.sun.electric.database.network.Netlist;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.Connection;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.database.variable.EditWindow_;import com.sun.electric.database.variable.UserInterface;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.SizeOffset;import com.sun.electric.tool.Job;import com.sun.electric.tool.JobException;import com.sun.electric.tool.user.Highlight2;import com.sun.electric.tool.user.dialogs.EDialog;import com.sun.electric.tool.user.ui.TopLevel;import java.awt.Frame;import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.Insets;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import javax.swing.JButton;import javax.swing.JLabel;import javax.swing.SwingUtilities;import javax.swing.WindowConstants;/** * This is the Mimic Stitching tool. */public class MimicStitch{ /** router to use */ private static InteractiveRouter router = new SimpleWirer(); private static final int NUMSITUATIONS = 7; private static final int LIKELYDIFFPORT = 1; private static final int LIKELYDIFFPORTWIDTH = 2; private static final int LIKELYDIFFARCCOUNT = 4; private static final int LIKELYDIFFNODETYPE = 8; private static final int LIKELYDIFFNODESIZE = 16; private static final int LIKELYARCSSAMEDIR = 32; private static final int LIKELYALREADYCONNECTED = 64; private static int situations[] = null; private static void buildLikelySituations() { if (situations != null) return; int numSituations = 1 << NUMSITUATIONS; List<Integer> allSituations = new ArrayList<Integer>(); for(int i=0; i<numSituations; i++) allSituations.add(new Integer(i)); Collections.sort(allSituations, new SituationSorter()); situations = new int[numSituations]; for(int i=0; i<numSituations; i++) situations[i] = allSituations.get(i).intValue(); } private static class SituationSorter implements Comparator<Integer> { public int compare(Integer r1, Integer r2) { int i1 = r1.intValue(); int i2 = r2.intValue(); int b1 = 0, b2 = 0; for(int i=0; i<NUMSITUATIONS; i++) { int mask = 1 << i; if ((i1 & mask) != 0) b1++; if ((i2 & mask) != 0) b2++; } return b1 - b2; } } private static class PossibleArc { private int situation; private ArcInst ai; private NodeInst ni1, ni2; private PortProto pp1, pp2;// private Point2D pt1, pt2; }; /** * Entry point for mimic router. * @param forced true if this mimic operation was explicitly requested. */ public static void mimicStitch(boolean forced) { buildLikelySituations(); UserInterface ui = Job.getUserInterface(); EditWindow_ wnd = ui.needCurrentEditWindow_(); if (wnd == null) return; Routing.Activity lastActivity = Routing.getRoutingTool().getLastActivity(); if (lastActivity == null) { System.out.println("No wiring activity to mimic"); return; } // if a single arc was deleted, mimiced it if (lastActivity.numDeletedArcs == 1 && lastActivity.numCreatedArcs == 0) { mimicdelete(lastActivity); lastActivity.numDeletedArcs = 0; return; } // if a single arc was just created, mimic that if (lastActivity.numCreatedArcs == 1) { ArcInst ai = EDatabase.clientDatabase().getCell(lastActivity.createdArcsParents[0]).getArcById(lastActivity.createdArcs[0].arcId);// ArcInst ai = lastActivity.createdArcs[0]; new MimicStitchJob(ai, 0, ai, 1, ai.getLambdaBaseWidth(), ai.getProto(), 0, 0, forced);// new MimicStitchJob(ai, 0, ai, 1, ai.getLambdaFullWidth(), ai.getProto(), 0, 0, forced); lastActivity.numCreatedArcs = 0; return; } // if multiple arcs were just created, find the true end and mimic that if (lastActivity.numCreatedArcs > 1 && lastActivity.numCreatedNodes > 0) { // find the ends of arcs that do not attach to the intermediate pins HashSet<NodeInst> gotOne = new HashSet<NodeInst>(); HashSet<NodeInst> gotMany = new HashSet<NodeInst>(); for(int i=0; i<lastActivity.numCreatedArcs; i++) { ArcInst ai = EDatabase.clientDatabase().getCell(lastActivity.createdArcsParents[i]).getArcById(lastActivity.createdArcs[i].arcId);// ArcInst ai = lastActivity.createdArcs[i]; for(int e=0; e<2; e++) { NodeInst ni = ai.getPortInst(e).getNodeInst(); if (!gotMany.contains(ni)) { if (!gotOne.contains(ni)) gotOne.add(ni); else { gotOne.remove(ni); gotMany.add(ni); } } } } int foundEnds = 0; Connection [] ends = new Connection[2]; double width = 0; for(int i=0; i<lastActivity.numCreatedArcs; i++) { ArcInst ai = EDatabase.clientDatabase().getCell(lastActivity.createdArcsParents[i]).getArcById(lastActivity.createdArcs[i].arcId);// ArcInst ai = lastActivity.createdArcs[i]; for(int e=0; e<2; e++) { NodeInst ni = ai.getPortInst(e).getNodeInst(); if (!gotOne.contains(ni)) continue; if (foundEnds < 2) { ends[foundEnds] = ai.getConnection(e); if (ai.getLambdaBaseWidth() > width) width = ai.getLambdaBaseWidth();// if (ai.getLambdaFullWidth() > width)// width = ai.getLambdaFullWidth(); } foundEnds++; } } // if exactly two ends are found, mimic that connection if (foundEnds == 2) { double prefX = 0, prefY = 0; if (lastActivity.numCreatedNodes == 1) { Poly portPoly0 = ends[0].getPortInst().getPoly(); double x0 = portPoly0.getCenterX(); double y0 = portPoly0.getCenterY(); Poly portPoly1 = ends[1].getPortInst().getPoly(); double x1 = portPoly1.getCenterX(); double y1 = portPoly1.getCenterY(); prefX = lastActivity.createdNodes[0].anchor.getLambdaX() - (x0+x1) / 2; prefY = lastActivity.createdNodes[0].anchor.getLambdaY() - (y0+y1) / 2; } else if (lastActivity.numCreatedNodes == 2) { Poly portPoly0 = ends[0].getPortInst().getPoly(); double x0 = portPoly0.getCenterX(); double y0 = portPoly0.getCenterY(); Poly portPoly1 = ends[1].getPortInst().getPoly(); double x1 = portPoly1.getCenterX(); double y1 = portPoly1.getCenterY(); prefX = (lastActivity.createdNodes[0].anchor.getLambdaX() + lastActivity.createdNodes[1].anchor.getLambdaX()) / 2 - (x0+x1) / 2; prefY = (lastActivity.createdNodes[0].anchor.getLambdaY() + lastActivity.createdNodes[1].anchor.getLambdaY()) / 2 - (y0+y1) / 2; } new MimicStitchJob(ends[0].getArc(), ends[0].getEndIndex(), ends[1].getArc(), ends[1].getEndIndex(), width, null, prefX, prefY, forced); } lastActivity.numCreatedArcs = 0; return; } } /** * Method to mimic the deletion of an arc. */ private static void mimicdelete(Routing.Activity activity) { UserInterface ui = Job.getUserInterface(); EditWindow_ wnd = ui.needCurrentEditWindow_(); if (wnd == null) return; // determine information about deleted arc ImmutableArcInst mimicAi = activity.deletedArc; Cell cell = Cell.inCurrentThread(activity.deletedArcParent); if (cell == null) return; // cell killed NodeInst mimicNiHead = cell.getNodeById(mimicAi.headNodeId); NodeInst mimicNiTail = cell.getNodeById(mimicAi.tailNodeId); if (mimicNiHead == null || mimicNiTail == null) return; // arc end killed ArcProtoId typ = mimicAi.protoId; Point2D pt0 = mimicAi.headLocation; Point2D pt1 = mimicAi.tailLocation; double dist = pt0.distance(pt1); int angle = 0; if (dist != 0) angle = DBMath.figureAngle(pt0, pt1); // look for a similar situation to delete List<PossibleArc> arcKills = new ArrayList<PossibleArc>(); for(Iterator<ArcInst> it = cell.getArcs(); it.hasNext(); ) { ArcInst ai = it.next(); // arc must be of the same type if (ai.getProto().getId() != typ) continue; // must be the same length and angle Point2D end0 = ai.getHeadLocation(); Point2D end1 = ai.getTailLocation(); double thisDist = end0.distance(end1); if (dist != thisDist) continue; if (dist != 0) { int thisAngle = DBMath.figureAngle(end0, end1); if ((angle%1800) != (thisAngle%1800)) continue; } PossibleArc pa = new PossibleArc(); pa.ai = ai; pa.situation = 0; // arc must connect to the same type of port boolean matchPort = false; if (ai.getHeadPortInst().getPortProto().getId() == activity.deletedPorts[0] && ai.getTailPortInst().getPortProto().getId() == activity.deletedPorts[1]) matchPort = true; if (ai.getHeadPortInst().getPortProto().getId() == activity.deletedPorts[1] && ai.getTailPortInst().getPortProto().getId() == activity.deletedPorts[0]) matchPort = true; if (!matchPort) pa.situation |= LIKELYDIFFPORT; // arcs must have the same bus width NodeInst niHead = ai.getHeadPortInst().getNodeInst(); NodeInst niTail = ai.getTailPortInst().getNodeInst(); int con1 = mimicNiHead.getNumConnections() + mimicNiTail.getNumConnections() + 2; int con2 = niHead.getNumConnections() + niTail.getNumConnections(); if (con1 != con2) pa.situation |= LIKELYDIFFARCCOUNT; // arc must connect to the same type of node boolean matchNode = false; if (niHead.getProto() == mimicNiHead.getProto() && niTail.getProto() == mimicNiTail.getProto()) matchNode = true; if (niHead.getProto() == mimicNiTail.getProto() && niTail.getProto() == mimicNiHead.getProto()) matchNode = true; if (!matchNode) pa.situation |= LIKELYDIFFNODETYPE; // determine size of nodes on mimic arc double mimicWidHead = mimicNiHead.getLambdaBaseXSize(); double mimicHeiHead = mimicNiHead.getLambdaBaseYSize();// SizeOffset so = mimicNiHead.getSizeOffset();// double mimicWidHead = mimicNiHead.getXSize() - so.getLowXOffset() - so.getHighXOffset();// double mimicHeiHead = mimicNiHead.getYSize() - so.getLowYOffset() - so.getHighYOffset(); double mimicWidTail = mimicNiTail.getLambdaBaseXSize(); double mimicHeiTail = mimicNiTail.getLambdaBaseYSize();// so = mimicNiTail.getSizeOffset();// double mimicWidTail = mimicNiTail.getXSize() - so.getLowXOffset() - so.getHighXOffset();// double mimicHeiTail = mimicNiTail.getYSize() - so.getLowYOffset() - so.getHighYOffset(); // determine size of nodes on possible deleted arc double widHead = niHead.getLambdaBaseXSize(); double heiHead = niHead.getLambdaBaseYSize();// so = niHead.getSizeOffset();// double widHead = niHead.getXSize() - so.getLowXOffset() - so.getHighXOffset();// double heiHead = niHead.getYSize() - so.getLowYOffset() - so.getHighYOffset(); double widTail = niTail.getLambdaBaseXSize(); double heiTail = niTail.getLambdaBaseYSize();// so = niTail.getSizeOffset();// double widTail = niTail.getXSize() - so.getLowXOffset() - so.getHighXOffset();// double heiTail = niTail.getYSize() - so.getLowYOffset() - so.getHighYOffset(); // flag if the sizes differ if (widHead != mimicWidHead || heiHead != mimicHeiHead) pa.situation |= LIKELYDIFFNODESIZE; if (widTail != mimicWidTail || heiTail != mimicHeiTail) pa.situation |= LIKELYDIFFNODESIZE; // the same! queue it for deletion arcKills.add(pa); } boolean mimicInteractive = Routing.isMimicStitchInteractive(); boolean matchPorts = Routing.isMimicStitchMatchPorts(); boolean matchPortWidth = Routing.isMimicStitchMatchPortWidth(); boolean matchArcCount = Routing.isMimicStitchMatchNumArcs(); boolean matchNodeType = Routing.isMimicStitchMatchNodeType(); boolean matchNodeSize = Routing.isMimicStitchMatchNodeSize(); boolean noOtherArcsThisDir = Routing.isMimicStitchNoOtherArcsSameDir(); boolean notAlreadyConnected = Routing.isMimicStitchOnlyNewTopology(); processPossibilities(cell, arcKills, 0, 0, Job.Type.EXAMINE, true, mimicInteractive, matchPorts, matchPortWidth, matchArcCount, matchNodeType, matchNodeSize, notAlreadyConnected, noOtherArcsThisDir); } /** * Class to examine a circuit and find mimic opportunities in a new thread. */ private static class MimicStitchJob extends Job { private ArcInst ai1, ai2; private int end1, end2; private double oWidth; private ArcProto oProto; private double prefX, prefY; private boolean forced; private MimicStitchJob(ArcInst ai1, int end1, ArcInst ai2, int end2, double oWidth, ArcProto oProto, double prefX, double prefY, boolean forced) { super("Mimic-Stitch", Routing.getRoutingTool(), Job.Type.EXAMINE, null, null, Job.Priority.USER); this.ai1 = ai1; this.end1 = end1; this.ai2 = ai2; this.end2 = end2; this.oWidth = oWidth; this.oProto = oProto; this.prefX = prefX; this.prefY = prefY; this.forced = forced; setReportExecutionFlag(true); startJob(); } public boolean doIt() throws JobException { // get options boolean mimicInteractive = Routing.isMimicStitchInteractive(); boolean matchPorts = Routing.isMimicStitchMatchPorts(); boolean matchPortWidth = Routing.isMimicStitchMatchPortWidth(); boolean matchArcCount = Routing.isMimicStitchMatchNumArcs(); boolean matchNodeType = Routing.isMimicStitchMatchNodeType(); boolean matchNodeSize = Routing.isMimicStitchMatchNodeSize(); boolean noOtherArcsThisDir = Routing.isMimicStitchNoOtherArcsSameDir(); boolean notAlreadyConnected = Routing.isMimicStitchOnlyNewTopology(); mimicOneArc(ai1, end1, ai2, end2, oWidth, oProto, prefX, prefY, forced, Job.Type.EXAMINE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -