📄 fpga.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: FPGA.java * FPGA, a customizable technology. * Written by Steven M. Rubin * * Copyright (c) 2005 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.technology.technologies;import com.sun.electric.database.ImmutableArcInst;import com.sun.electric.database.geometry.EGraphics;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.geometry.ERectangle;import com.sun.electric.database.geometry.GenMath;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.hierarchy.Nodable;import com.sun.electric.database.network.Netlist;import com.sun.electric.database.network.Network;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.TextUtils;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.topology.RTBounds;import com.sun.electric.database.variable.EditWindow0;import com.sun.electric.database.variable.EditWindow_;import com.sun.electric.database.variable.ElectricObject;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.UserInterface;import com.sun.electric.database.variable.VarContext;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.AbstractShapeBuilder;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.EdgeH;import com.sun.electric.technology.EdgeV;import com.sun.electric.technology.Foundry;import com.sun.electric.technology.Layer;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.PrimitivePort;import com.sun.electric.technology.Technology;import com.sun.electric.tool.Job;import com.sun.electric.tool.JobException;import com.sun.electric.tool.io.FileType;import com.sun.electric.tool.user.User;import com.sun.electric.tool.user.dialogs.OpenFile;import com.sun.electric.tool.user.dialogs.PromptAt;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import java.net.URL;import java.net.URLConnection;import java.util.ArrayList;import java.util.Iterator;import java.util.List;/** * This is the FPGA Technology. */public class FPGA extends Technology{ /** the FPGA Technology object. */ public static FPGA tech() { return sysFPGA; } private final Layer wireLayer, componentLayer, pipLayer, repeaterLayer; private final ArcProto wireArc; private final PrimitiveNode wirePinNode, pipNode, repeaterNode; public FPGA(Generic generic) { super(generic, "fpga", Foundry.Type.NONE, 1); setTechShortName("FPGA"); setTechDesc("FPGA Building-Blocks"); setFactoryScale(2000, true); // in nanometers: really 2 microns setStaticTechnology(); setNonStandard(); setNoPrimitiveNodes(); //**************************************** LAYERS **************************************** /** Wire layer */ wireLayer = Layer.newInstance(this, "Wire", new EGraphics(false, false, null, 0, 255,0,0,1,true, new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); /** Component layer */ componentLayer = Layer.newInstance(this, "Component", new EGraphics(false, false, null, 0, 0,0,0,1,true, new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); /** Pip layer */ pipLayer = Layer.newInstance(this, "Pip", new EGraphics(false, false, null, 0, 0,255,0,1,true, new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); /** Repeater layer */ repeaterLayer = Layer.newInstance(this, "Repeater", new EGraphics(false, false, null, 0, 0,0,255,1,true, new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); // The layer functions wireLayer.setFunction(Layer.Function.METAL1); // wire componentLayer.setFunction(Layer.Function.ART); // component pipLayer.setFunction(Layer.Function.ART); // pip repeaterLayer.setFunction(Layer.Function.ART); // repeater //**************************************** ARC **************************************** /** wire arc */ wireArc = newArcProto("wire", 0, 0.0, ArcProto.Function.METAL1, new Technology.ArcLayer(wireLayer, 0, Poly.Type.FILLED) ); wireArc.setFactoryFixedAngle(true); wireArc.setFactorySlidable(false); wireArc.setFactoryAngleIncrement(45); //**************************************** NODES **************************************** /** wire pin */ wirePinNode = PrimitiveNode.newInstance("Wire_Pin", this, 1, 1, null, new Technology.NodeLayer [] { new Technology.NodeLayer(wireLayer, 0, Poly.Type.DISC, Technology.NodeLayer.POINTS, new Technology.TechPoint [] { new Technology.TechPoint(EdgeH.makeCenter(), EdgeV.makeCenter()), new Technology.TechPoint(EdgeH.makeRightEdge(), EdgeV.makeCenter())}) }); wirePinNode.addPrimitivePorts(new PrimitivePort [] { PrimitivePort.newInstance(this, wirePinNode, new ArcProto[] {wireArc}, "wire", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); wirePinNode.setFunction(PrimitiveNode.Function.PIN); wirePinNode.setSquare(); wirePinNode.setWipeOn1or2(); /** pip */ pipNode = PrimitiveNode.newInstance("Pip", this, 2, 2, null, new Technology.NodeLayer [] { new Technology.NodeLayer(pipLayer, 0, Poly.Type.FILLED, Technology.NodeLayer.BOX, new Technology.TechPoint [] { new Technology.TechPoint(EdgeH.makeLeftEdge(), EdgeV.makeBottomEdge()), new Technology.TechPoint(EdgeH.makeRightEdge(), EdgeV.makeTopEdge())}) }); pipNode.addPrimitivePorts(new PrimitivePort [] { PrimitivePort.newInstance(this, pipNode, new ArcProto[] {wireArc}, "pip", 0,180, 0, PortCharacteristic.UNKNOWN, EdgeH.makeCenter(), EdgeV.makeCenter(), EdgeH.makeCenter(), EdgeV.makeCenter()) }); pipNode.setFunction(PrimitiveNode.Function.CONNECT); pipNode.setSquare(); /** repeater */ repeaterNode = PrimitiveNode.newInstance("Repeater", this, 10, 3, null, new Technology.NodeLayer [] { new Technology.NodeLayer(repeaterLayer, 0, Poly.Type.FILLED, Technology.NodeLayer.BOX, new Technology.TechPoint [] { new Technology.TechPoint(EdgeH.makeLeftEdge(), EdgeV.makeBottomEdge()), new Technology.TechPoint(EdgeH.makeRightEdge(), EdgeV.makeTopEdge())}) }); repeaterNode.addPrimitivePorts(new PrimitivePort [] { PrimitivePort.newInstance(this, repeaterNode, new ArcProto[] {wireArc}, "a", 180,45, 0, PortCharacteristic.UNKNOWN, EdgeH.makeLeftEdge(), EdgeV.makeCenter(), EdgeH.makeLeftEdge(), EdgeV.makeCenter()), PrimitivePort.newInstance(this, repeaterNode, new ArcProto[] {wireArc}, "b", 0,45, 1, PortCharacteristic.UNKNOWN, EdgeH.makeRightEdge(), EdgeV.makeCenter(), EdgeH.makeRightEdge(), EdgeV.makeCenter()) }); repeaterNode.setFunction(PrimitiveNode.Function.CONNECT); // Building information for palette nodeGroups = new Object[7][1]; int count = 0; nodeGroups[count++][0] = wireArc; nodeGroups[count++][0] = Technology.SPECIALMENUCELL; nodeGroups[count++][0] = Technology.SPECIALMENUMISC; nodeGroups[count++][0] = Technology.SPECIALMENUPURE; nodeGroups[count++][0] = wirePinNode; nodeGroups[count++][0] = pipNode; nodeGroups[count++][0] = repeaterNode; // Foundry newFoundry(Foundry.Type.NONE, null); } /******************** TREE STRUCTURE FOR ARCHITECTURE FILE ********************/ /** max depth of FPGA nesting */ private static final int MAXDEPTH = 50; private static class LispTree { private String keyword; private int lineNumber; private List<Object> values; LispTree() { values = new ArrayList<Object>(); } void add(Object obj) { values.add(obj); } int size() { return values.size(); } boolean isLeaf(int i) { return !(values.get(i) instanceof LispTree); } boolean isBranch(int i) { return values.get(i) instanceof LispTree; } String getLeaf(int i) { return (String)values.get(i); } LispTree getBranch(int i) { return (LispTree)values.get(i); } }; private static LispTree [] treeStack = new LispTree[MAXDEPTH]; private static int treeDepth; private static LispTree treePosition; /******************** ADDITIONAL INFORMATION ABOUT PRIMITIVES ********************/ /** level of display */ private static final int DISPLAYLEVEL = 07; /** display no internals */ private static final int NOPRIMDISPLAY = 0; /** display all internals */ private static final int FULLPRIMDISPLAY = 01; /** display only active internals */ private static final int ACTIVEPRIMDISPLAY = 02; /** set to display text */ private static final int TEXTDISPLAY = 010; /** set if segment or pip is active */ private static final int ACTIVEPART = 1; /** saved area for segment/pip activity */ private static final int ACTIVESAVE = 2; private static class FPGAPort { String name; double posX, posY; int con; PortCharacteristic characteristic; PrimitivePort pp; }; private static class FPGANet { String name; int segActive; Point2D [] segFrom; Point2D [] segTo; }; private static class FPGAPip { String name; int pipActive; int con1, con2; double posX, posY; }; private static class FPGANode extends PrimitiveNode { FPGAPort [] portList; FPGANet [] netList; FPGAPip [] pipList; protected FPGANode(String protoName, Technology tech, double defWidth, double defHeight, Technology.NodeLayer [] layers) { super(protoName, tech, EPoint.ORIGIN, EPoint.ORIGIN, null, defWidth, defHeight, ERectangle.ORIGIN, ERectangle.ORIGIN, layers); } int numPorts() { if (portList == null) return 0; return portList.length; } int numNets() { if (netList == null) return 0; return netList.length; } int numPips() { if (pipList == null) return 0; return pipList.length; } }; /** key of Variable holding active pips. */ private static final Variable.Key ACTIVEPIPS_KEY = Variable.newKey("FPGA_activepips"); /** key of Variable holding active repeaters. */ private static final Variable.Key ACTIVEREPEATERS_KEY = Variable.newKey("FPGA_activerepeaters");// /** key of Variable holding cache of pips on node. */ private static final Variable.Key NODEPIPCACHE_KEY = Variable.newKey("FPGA_nodepipcache");// /** key of Variable holding cache of active arcs. */ private static final Variable.Key ARCACTIVECACHE_KEY = Variable.newKey("FPGA_arcactivecache"); /** name of current repeater for activity examining */ private String repeaterName; /** nonzero if current repeater is found to be active */private boolean repeaterActive; /** what is being displayed */ private int internalDisplay = FULLPRIMDISPLAY | TEXTDISPLAY; /** whether the technology has been read */ private boolean defined = false; private static final Technology.NodeLayer[] NULLNODELAYER = new Technology.NodeLayer[0]; /** * Method to return a list of Polys that describe a given NodeInst. * This method overrides the general one in the Technology object * because of the unusual primitives in this Technology. * @param ni the NodeInst to describe. * @param electrical true to get the "electrical" layers. * This makes no sense for Schematics primitives. * @param reasonable true to get only a minimal set of contact cuts in large contacts. * This makes no sense for Schematics primitives. * @param primLayers an array of NodeLayer objects to convert to Poly objects. * @param layerOverride the layer to use for all generated polygons (if not null). * @return an array of Poly objects. */ @Override protected Poly [] getShapeOfNode(NodeInst ni, boolean electrical, boolean reasonable, Technology.NodeLayer [] primLayers, Layer layerOverride) { return getShapeOfNode(ni, null, null, electrical, reasonable, primLayers, layerOverride); } /** * Method to return a list of Polys that describe a given NodeInst. * This method overrides the general one in the Technology object * because of the unusual primitives in this Technology. * @param ni the NodeInst to describe. * @param wnd the window in which this node will be drawn. * @param context the VarContext to this node in the hierarchy. * @param electrical true to get the "electrical" layers. * This makes no sense for Schematics primitives. * @param reasonable true to get only a minimal set of contact cuts in large contacts. * This makes no sense for Schematics primitives. * @param primLayers an array of NodeLayer objects to convert to Poly objects. * @param layerOverride the layer to use for all generated polygons (if not null). * @return an array of Poly objects. */ private Poly [] getShapeOfNode(NodeInst ni, EditWindow0 wnd, VarContext context, boolean electrical, boolean reasonable, Technology.NodeLayer [] primLayers, Layer layerOverride) { if (ni.isCellInstance()) return null; PrimitiveNode np = (PrimitiveNode)ni.getProto(); if (np == wirePinNode) { if (ni.pinUseCount()) primLayers = NULLNODELAYER; } else if (np == repeaterNode) { if ((internalDisplay&DISPLAYLEVEL) == ACTIVEPRIMDISPLAY) { if (!repeaterActive(ni)) primLayers = NULLNODELAYER; } } else if (np instanceof FPGANode) { // dynamic primitive FPGANode fn = (FPGANode)np; // hard reset of all segment and pip activity int numPips = 0, numSegs = 0; for(int i=0; i<fn.numNets(); i++) fn.netList[i].segActive = 0; for(int i=0; i<fn.numPips(); i++) fn.pipList[i].pipActive = 0; switch (internalDisplay & DISPLAYLEVEL) { case NOPRIMDISPLAY: break; case ACTIVEPRIMDISPLAY: // count number of active nets and pips // determine the active segments and pips reEvaluatePips(ni, fn, context); // save the activity bits for(int i=0; i<fn.numNets(); i++) if ((fn.netList[i].segActive&ACTIVEPART) != 0) fn.netList[i].segActive |= ACTIVESAVE; for(int i=0; i<fn.numPips(); i++) if ((fn.pipList[i].pipActive&ACTIVEPART) != 0) fn.pipList[i].pipActive |= ACTIVESAVE; // propagate inactive segments to others that may be active if (context != null && context.getNodable() != null) { VarContext higher = context.pop(); for(int i=0; i<fn.numNets(); i++) { if ((fn.netList[i].segActive&ACTIVESAVE) != 0) continue; boolean found = false; for(int j=0; j<fn.numPorts(); j++) { if (fn.portList[j].con != i) continue; for(Iterator<Connection> it = ni.getConnections(); it.hasNext(); ) { Connection con = it.next(); if (con.getPortInst().getPortProto() != fn.portList[j].pp) continue; ArcInst ai = con.getArc(); int otherEnd = 1 - con.getEndIndex(); if (arcEndActive(ai, otherEnd, higher)) { found = true; break; } } if (found) break; } if (found) fn.netList[i].segActive |= ACTIVESAVE; } } // add up the active segments for(int i=0; i<fn.numPips(); i++) if ((fn.pipList[i].pipActive&ACTIVESAVE) != 0) numPips++; for(int i=0; i<fn.numNets(); i++) if ((fn.netList[i].segActive&ACTIVESAVE) != 0) numSegs += fn.netList[i].segFrom.length; break; case FULLPRIMDISPLAY: for(int i=0; i<fn.numNets(); i++) { fn.netList[i].segActive |= ACTIVESAVE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -