1
/* -*- tab-width: 4 -*-
3
* Electric(tm) VLSI Design System
7
* Copyright (c) 2003 Sun Microsystems and Static Free Software
9
* Electric(tm) is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 3 of the License, or
12
* (at your option) any later version.
14
* Electric(tm) is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with Electric(tm); see the file COPYING. If not, write to
21
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22
* Boston, Mass 02111-1307, USA.
24
package com.sun.electric.technology.xml;
26
import com.sun.electric.database.geometry.EGraphics;
27
import com.sun.electric.database.geometry.EPoint;
28
import com.sun.electric.database.geometry.ERectangle;
29
import com.sun.electric.database.geometry.Poly.Type;
30
import com.sun.electric.technology.DRCTemplate;
31
import com.sun.electric.technology.EdgeH;
32
import com.sun.electric.technology.EdgeV;
33
import com.sun.electric.technology.Technology.TechPoint;
34
import com.sun.electric.tool.Job;
36
import java.awt.Color;
37
import java.io.IOException;
38
import java.io.InputStream;
39
import java.io.PrintWriter;
40
import java.io.Serializable;
41
import java.io.StringReader;
42
import java.io.StringWriter;
44
import java.net.URLConnection;
45
import java.util.ArrayList;
46
import java.util.Arrays;
47
import java.util.Calendar;
48
import java.util.Collections;
49
import java.util.Date;
50
import java.util.HashMap;
51
import java.util.LinkedHashMap;
52
import java.util.List;
55
import javax.xml.XMLConstants;
56
import javax.xml.parsers.SAXParser;
57
import javax.xml.parsers.SAXParserFactory;
59
import javax.xml.validation.Schema;
60
import javax.xml.validation.SchemaFactory;
61
import org.xml.sax.Attributes;
62
import org.xml.sax.InputSource;
63
import org.xml.sax.Locator;
64
import org.xml.sax.SAXException;
65
import org.xml.sax.SAXParseException;
66
import org.xml.sax.helpers.DefaultHandler;
71
public class XmlParam {
73
public static class Technology implements Serializable {
74
public String techName;
75
public String className;
76
public String shortTechName;
77
public String description;
78
public int minNumMetals;
79
public int maxNumMetals;
80
public int defaultNumMetals;
81
public double scaleValue;
82
public boolean scaleRelevant;
83
public String defaultFoundry;
84
public double minResistance;
85
public double minCapacitance;
86
private final LinkedHashMap<String,Layer> layers = new LinkedHashMap<String,Layer>();
87
public final List<ArcProto> arcs = new ArrayList<ArcProto>();
88
public final List<PrimitiveNode> nodes = new ArrayList<PrimitiveNode>();
89
public final List<SpiceHeader> spiceHeaders = new ArrayList<SpiceHeader>();
90
public final List<DisplayStyle> displayStyles = new ArrayList<DisplayStyle>();
91
public MenuPalette menuPalette;
92
public final LinkedHashMap<String,RuleSet> ruleSets = new LinkedHashMap<String,RuleSet>();
93
public final List<Foundry> foundries = new ArrayList<Foundry>();
95
public Layer newLayer(String name) {
97
throw new NullPointerException();
98
if (layers.containsKey(name))
99
throw new IllegalArgumentException("Duplicate Layer " + name);
100
Layer layer = new Layer(name);
101
layers.put(name, layer);
105
public RuleSet newRuleSet(String name) {
107
throw new NullPointerException();
108
if (ruleSets.containsKey(name))
109
throw new IllegalArgumentException("Duplicate RuleSet " + name);
110
RuleSet ruleSet = new RuleSet(name);
111
ruleSets.put(name, ruleSet);
115
public Layer findLayer(String name) {
116
return layers.get(name);
119
public ArcProto findArc(String name) {
120
for (ArcProto arc: arcs) {
121
if (arc.name.equals(name))
127
public PrimitiveNode findNode(String name) {
128
for (PrimitiveNode node: nodes) {
129
if (node.name.equals(name))
135
public void writeXml(String fileName) {
137
PrintWriter out = new PrintWriter(fileName);
138
Writer writer = new Writer(out);
139
writer.writeTechnology(this);
141
System.out.println("Wrote " + fileName);
142
System.out.println(" (Add this file to the 'Added Technologies' Project Settings to install it in Electric)");
143
} catch (IOException e) {
144
System.out.println("Error creating " + fileName);
149
public static class Layer implements Serializable {
150
public final String name;
151
public com.sun.electric.technology.Layer.Function function;
152
public int extraFunction;
155
public double resistance;
156
public double capacitance;
157
public double edgeCapacitance;
158
public PureLayerNode pureLayerNode;
160
private Layer(String name) {
165
public static class PureLayerNode implements Serializable {
167
public String oldName;
170
public final List<String> portArcs = new ArrayList<String>();
173
public static class ArcProto implements Serializable {
175
public String oldName;
176
public com.sun.electric.technology.ArcProto.Function function;
177
public boolean wipable;
178
public boolean curvable;
179
public boolean special;
180
public boolean notUsed;
181
public boolean skipSizeInPalette;
183
public boolean extended;
184
public boolean fixedAngle;
185
public int angleIncrement;
186
public double antennaRatio;
187
public double elibWidthOffset;
188
public final List<ArcLayer> arcLayers = new ArrayList<ArcLayer>();
189
public ArcPin arcPin;
192
public static class ArcPin implements Serializable {
194
public String portName;
195
public double elibSize;
196
public final List<String> portArcs = new ArrayList<String>();
199
public static class ArcLayer implements Serializable {
201
public final Distance extend = new Distance();
205
public static class PrimitiveNode implements Serializable {
207
public String oldName;
208
public boolean shrinkArcs;
209
public boolean square;
210
public boolean canBeZeroSize;
211
public boolean wipes;
212
public boolean lockable;
213
public boolean edgeSelect;
214
public boolean skipSizeInPalette;
215
public boolean notUsed;
216
public boolean lowVt;
217
public boolean highVt;
218
public boolean nativeBit;
223
public com.sun.electric.technology.PrimitiveNode.Function function;
224
public EPoint diskOffset;
225
public final Distance defaultWidth = new Distance();
226
public final Distance defaultHeight = new Distance();
227
public ERectangle nodeBase;
228
public final List<NodeLayer> nodeLayers = new ArrayList<NodeLayer>();
229
public final List<PrimitivePort> ports = new ArrayList<PrimitivePort>();
230
public int specialType;
231
public double[] specialValues;
232
public NodeSizeRule nodeSizeRule;
233
public String spiceTemplate;
236
public static class NodeLayer implements Serializable {
240
public boolean inLayers;
241
public boolean inElectricalLayers;
242
public int representation;
243
public final Distance lx = new Distance();
244
public final Distance hx = new Distance();
245
public final Distance ly = new Distance();
246
public final Distance hy = new Distance();
247
public final List<TechPoint> techPoints = new ArrayList<TechPoint>();
248
public double sizex, sizey, sep1d, sep2d;
249
public String sizeRule, sepRule, sepRule2D;
250
public double lWidth, rWidth, tExtent, bExtent;
253
public static class NodeSizeRule implements Serializable {
255
public double height;
259
public static class PrimitivePort implements Serializable {
261
public int portAngle;
262
public int portRange;
263
public int portTopology;
264
public final Distance lx = new Distance();
265
public final Distance hx = new Distance();
266
public final Distance ly = new Distance();
267
public final Distance hy = new Distance();
268
public final List<String> portArcs = new ArrayList<String>();
271
public static class SpiceHeader implements Serializable {
273
public final List<String> spiceLines = new ArrayList<String>();
276
public static class DisplayStyle implements Serializable {
278
public final List<Color> transparentLayers = new ArrayList<Color>();
279
private final LinkedHashMap<Layer,LayerDisplayStyle> layerStylesInternal = new LinkedHashMap<Layer,LayerDisplayStyle>();
280
public final Map<Layer,LayerDisplayStyle> layerStyles = Collections.unmodifiableMap(layerStylesInternal);
282
public LayerDisplayStyle newLayer(Layer layer) {
283
LayerDisplayStyle lds = new LayerDisplayStyle(layer);
284
LayerDisplayStyle old = layerStylesInternal.put(layer, lds);
290
public static class LayerDisplayStyle implements Serializable {
291
public final Layer layer;
292
public EGraphics desc;
293
public String mode3D;
294
public double factor3D;
296
private LayerDisplayStyle(Layer layer) {
301
public static class MenuPalette implements Serializable {
302
public int numColumns;
303
public List<List<Object>> menuBoxes = new ArrayList<List<Object>>();
305
public String writeXml() {
306
StringWriter sw = new StringWriter();
307
PrintWriter out = new PrintWriter(sw);
308
OneLineWriter writer = new OneLineWriter(out);
309
writer.writeMenuPaletteXml(this);
311
return sw.getBuffer().toString();
315
public static class MenuNodeInst implements Serializable {
316
public String protoName;
317
public com.sun.electric.technology.PrimitiveNode.Function function;
319
public double fontSize;
323
public static class MenuCell implements Serializable {
324
public String cellName;
325
// public String text;
326
// public double fontSize;
329
public static class Distance implements Serializable {
331
public double lambdaValue;
332
public final List<DistanceRule> terms = new ArrayList<DistanceRule>();
334
public void assign(Distance d) {
336
lambdaValue = d.lambdaValue;
337
for (DistanceRule term: d.terms)
338
terms.add(term.clone());
341
public void assign(com.sun.electric.technology.Technology.Distance d) {
343
lambdaValue = d.lambdaValue;
344
for (com.sun.electric.technology.Technology.DistanceRule term: d.terms)
345
terms.add(new DistanceRule(term));
348
public Distance clone() {
349
Distance d = new Distance();
354
public double getLambda(DistanceContext context) {
355
double value = lambdaValue;
356
for (DistanceRule term: terms)
357
value += term.getLambda(context);
360
private void writeXml(Writer writer, boolean multiLine) {
361
for (DistanceRule term: terms) {
362
term.writeXml(writer);
366
if (lambdaValue != 0) {
367
writer.bcpe(XmlKeyword.lambda, lambdaValue);
372
public void addLambda(double value) {
373
lambdaValue += value;
375
public void addRule(String ruleName, double k) {
376
addRule(ruleName, null, k);
378
public void addRule(String ruleName, Layer layer, double k) {
379
addRule(ruleName, layer, null, k);
381
public void addRule(String ruleName, Layer layer, Layer layer2, double k) {
382
terms.add(new DistanceRule(ruleName, layer, layer2, k));
384
public boolean isEmpty() { return lambdaValue == 0 && terms.isEmpty(); }
387
public static interface DistanceContext {
388
public double getRule(String ruleName);
391
public static class DistanceRule implements Serializable, Cloneable {
392
final String ruleName;
397
public DistanceRule(com.sun.electric.technology.Technology.DistanceRule oldRule) {
398
this(oldRule.ruleName, null, null, oldRule.k);
401
private DistanceRule(String ruleName, Layer layer, Layer layer2, double k) {
402
this.ruleName = ruleName;
404
this.layer2 = layer2;
408
public DistanceRule clone() {
410
return (DistanceRule)super.clone();
411
} catch (CloneNotSupportedException e) {
412
throw new AssertionError();
416
private void writeXml(Writer writer) {
417
writer.b(XmlKeyword.rule);
418
writer.a("ruleName", ruleName);
420
writer.a("layer", layer.name);
422
writer.a("layer2", layer2.name);
429
private double getLambda(DistanceContext context) {
430
return context.getRule(ruleName)*k;
434
public static class RuleSet implements Serializable {
435
public final String name;
436
public final Map<String,Map<Layer,Distance>> layerRules = new LinkedHashMap<String,Map<Layer,Distance>>();
438
private RuleSet(String name) {
442
public Map<Layer,Distance> newLayerRule(String ruleName) {
443
if (ruleName == null)
444
throw new NullPointerException();
445
if (layerRules.containsKey(ruleName))
446
throw new IllegalArgumentException("Duplicate LayerRule " + ruleName);
447
Map<Layer,Distance> layerRule = new LinkedHashMap<Layer,Distance>();
448
layerRules.put(ruleName, layerRule);
453
public static class Foundry implements Serializable {
455
public final Map<String,String> layerGds = new LinkedHashMap<String,String>();
456
public final List<DRCTemplate> rules = new ArrayList<DRCTemplate>();
459
private XmlParam() {}
461
private static enum XmlKeyword {
487
angleIncrement(true),
489
elibWidthOffset(true),
502
// skipSizeInPalette,
541
patternedOnDisplay(true),
542
patternedOnPrinter(true),
568
private final boolean hasText;
570
private XmlKeyword() {
573
private XmlKeyword(boolean hasText) {
574
this.hasText = hasText;
578
private static final HashMap<String,XmlKeyword> xmlKeywords = new HashMap<String,XmlKeyword>();
580
for (XmlKeyword k: XmlKeyword.class.getEnumConstants())
581
xmlKeywords.put(k.name(), k);
584
private static Schema schema = null;
586
private static synchronized void loadTechnologySchema() throws SAXException {
587
if (schema != null) return;
588
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
589
URL technologySchemaUrl = Technology.class.getResource("xml/TechnologyParam.xsd");
590
if (technologySchemaUrl != null)
591
schema = schemaFactory.newSchema(technologySchemaUrl);
594
System.err.println("Schema file TechnologyParam.xsd, working without XML schema");
595
System.out.println("Schema file TechnologyParam.xsd, working without XML schema");
599
public static Technology parseTechnology(URL fileURL) {
600
// System.out.println("Memory usage " + Main.getMemoryUsage() + " bytes");
601
SAXParserFactory factory = SAXParserFactory.newInstance();
602
factory.setNamespaceAware(true);
605
loadTechnologySchema();
606
factory.setSchema(schema);
607
// factory.setValidating(true);
608
// System.out.println("Memory usage " + Main.getMemoryUsage() + " bytes");
610
long startTime = System.currentTimeMillis();
611
SAXParser parser = factory.newSAXParser();
612
URLConnection urlCon = fileURL.openConnection();
613
InputStream inputStream = urlCon.getInputStream();
615
XMLReader handler = new XMLReader();
616
parser.parse(inputStream, handler);
619
long stopTime = System.currentTimeMillis();
620
System.out.println("Loading technology " + fileURL + " ... " + (stopTime - startTime) + " msec");
623
} catch (SAXParseException e) {
624
String msg = "Error parsing Xml technology:\n" +
625
e.getMessage() + "\n" +
626
" Line " + e.getLineNumber() + " column " + e.getColumnNumber() + " of " + fileURL;
627
msg = msg.replaceAll("\"http://electric.sun.com/Technology\":", "");
628
System.out.println(msg);
629
Job.getUserInterface().showErrorMessage(msg, "Error parsing Xml technology");
630
} catch (Exception e) {
631
String msg = "Error loading Xml technology " + fileURL + " :\n"
632
+ e.getMessage() + "\n";
633
System.out.println(msg);
634
Job.getUserInterface().showErrorMessage(msg, "Error loading Xml technology");
640
* Method to parse a string of XML that describes the component menu in a Technology Editing context.
641
* Normal parsing of XML returns objects in the Xml class, but
642
* this method returns objects in a given Technology-Editor world.
643
* @param xml the XML string
644
* @param nodes the PrimitiveNode objects describing nodes in the technology.
645
* @param arcs the ArcProto objects describing arcs in the technology.
646
* @return the MenuPalette describing the component menu.
648
public static MenuPalette parseComponentMenuXMLTechEdit(String xml, List<PrimitiveNode> nodes, List<ArcProto> arcs)
650
SAXParserFactory factory = SAXParserFactory.newInstance();
651
factory.setNamespaceAware(true);
654
SAXParser parser = factory.newSAXParser();
655
InputSource is = new InputSource(new StringReader(xml));
656
XMLReader handler = new XMLReader(nodes, arcs);
657
parser.parse(is, handler);
658
return handler.tech.menuPalette;
659
} catch (Exception e)
661
System.out.println("Error parsing XML component menu data");
667
private static class XMLReader extends DefaultHandler {
668
private static boolean DEBUG = false;
669
private Locator locator;
671
private Technology tech = new Technology();
672
private Layer curLayer;
673
private ArcProto curArc;
674
private PrimitiveNode curNode;
675
private NodeLayer curNodeLayer;
676
private PrimitivePort curPort;
677
private int curSpecialValueIndex;
678
private ArrayList<Object> curMenuBox;
679
private MenuNodeInst curMenuNodeInst;
680
private MenuCell curMenuCell;
681
private Distance curDistance;
682
private SpiceHeader curSpiceHeader;
684
private DisplayStyle curDisplayStyle;
685
private int curTransparent = 0;
689
private LayerDisplayStyle curLayerDisplayStyle;
690
private boolean patternedOnDisplay;
691
private boolean patternedOnPrinter;
692
private final int[] pattern = new int[16];
693
private int curPatternIndex;
694
private EGraphics.Outline outline;
695
private double opacity;
696
private boolean foreground;
698
private RuleSet curRuleSet;
699
private Map<Layer,Distance> curLayerRule;
700
private Foundry curFoundry;
702
private boolean acceptCharacters;
703
private StringBuilder charBuffer = new StringBuilder();
704
private Attributes attributes;
709
XMLReader(List<PrimitiveNode> nodes, List<ArcProto> arcs)
711
for(ArcProto xap : arcs)
713
for(PrimitiveNode xnp : nodes)
717
private void beginCharacters() {
718
assert !acceptCharacters;
719
acceptCharacters = true;
720
assert charBuffer.length() == 0;
722
private String endCharacters() {
723
assert acceptCharacters;
724
String s = charBuffer.toString();
725
charBuffer.setLength(0);
726
acceptCharacters = false;
731
////////////////////////////////////////////////////////////////////
732
// Default implementation of the EntityResolver interface.
733
////////////////////////////////////////////////////////////////////
736
* Resolve an external entity.
738
* <p>Always return null, so that the parser will use the system
739
* identifier provided in the XML document. This method implements
740
* the SAX default behaviour: application writers can override it
741
* in a subclass to do special translations such as catalog lookups
742
* or URI redirection.</p>
744
* @param publicId The public identifier, or null if none is
746
* @param systemId The system identifier provided in the XML
748
* @return The new input source, or null to require the
750
* @exception java.io.IOException If there is an error setting
751
* up the new input source.
752
* @exception org.xml.sax.SAXException Any SAX exception, possibly
753
* wrapping another exception.
754
* @see org.xml.sax.EntityResolver#resolveEntity
756
public InputSource resolveEntity(String publicId, String systemId)
757
throws IOException, SAXException {
763
////////////////////////////////////////////////////////////////////
764
// Default implementation of DTDHandler interface.
765
////////////////////////////////////////////////////////////////////
769
* Receive notification of a notation declaration.
771
* <p>By default, do nothing. Application writers may override this
772
* method in a subclass if they wish to keep track of the notations
773
* declared in a document.</p>
775
* @param name The notation name.
776
* @param publicId The notation public identifier, or null if not
778
* @param systemId The notation system identifier.
779
* @exception org.xml.sax.SAXException Any SAX exception, possibly
780
* wrapping another exception.
781
* @see org.xml.sax.DTDHandler#notationDecl
783
public void notationDecl(String name, String publicId, String systemId)
784
throws SAXException {
790
* Receive notification of an unparsed entity declaration.
792
* <p>By default, do nothing. Application writers may override this
793
* method in a subclass to keep track of the unparsed entities
794
* declared in a document.</p>
796
* @param name The entity name.
797
* @param publicId The entity public identifier, or null if not
799
* @param systemId The entity system identifier.
800
* @param notationName The name of the associated notation.
801
* @exception org.xml.sax.SAXException Any SAX exception, possibly
802
* wrapping another exception.
803
* @see org.xml.sax.DTDHandler#unparsedEntityDecl
805
public void unparsedEntityDecl(String name, String publicId,
806
String systemId, String notationName)
807
throws SAXException {
813
////////////////////////////////////////////////////////////////////
814
// Default implementation of ContentHandler interface.
815
////////////////////////////////////////////////////////////////////
819
* Receive a Locator object for document events.
821
* <p>By default, do nothing. Application writers may override this
822
* method in a subclass if they wish to store the locator for use
823
* with other document events.</p>
825
* @param locator A locator for all SAX document events.
826
* @see org.xml.sax.ContentHandler#setDocumentLocator
827
* @see org.xml.sax.Locator
829
public void setDocumentLocator(Locator locator) {
830
this.locator = locator;
833
private void printLocator() {
834
System.out.println("publicId=" + locator.getPublicId() + " systemId=" + locator.getSystemId() +
835
" line=" + locator.getLineNumber() + " column=" + locator.getColumnNumber());
840
* Receive notification of the beginning of the document.
842
* <p>By default, do nothing. Application writers may override this
843
* method in a subclass to take specific actions at the beginning
844
* of a document (such as allocating the root node of a tree or
845
* creating an output file).</p>
847
* @exception org.xml.sax.SAXException Any SAX exception, possibly
848
* wrapping another exception.
849
* @see org.xml.sax.ContentHandler#startDocument
851
public void startDocument()
852
throws SAXException {
854
System.out.println("startDocument");
860
* Receive notification of the end of the document.
862
* <p>By default, do nothing. Application writers may override this
863
* method in a subclass to take specific actions at the end
864
* of a document (such as finalising a tree or closing an output
867
* @exception org.xml.sax.SAXException Any SAX exception, possibly
868
* wrapping another exception.
869
* @see org.xml.sax.ContentHandler#endDocument
871
public void endDocument()
872
throws SAXException {
874
System.out.println("endDocument");
880
* Receive notification of the start of a Namespace mapping.
882
* <p>By default, do nothing. Application writers may override this
883
* method in a subclass to take specific actions at the start of
884
* each Namespace prefix scope (such as storing the prefix mapping).</p>
886
* @param prefix The Namespace prefix being declared.
887
* @param uri The Namespace URI mapped to the prefix.
888
* @exception org.xml.sax.SAXException Any SAX exception, possibly
889
* wrapping another exception.
890
* @see org.xml.sax.ContentHandler#startPrefixMapping
892
public void startPrefixMapping(String prefix, String uri)
893
throws SAXException {
895
System.out.println("startPrefixMapping prefix=" + prefix + " uri=" + uri);
901
* Receive notification of the end of a Namespace mapping.
903
* <p>By default, do nothing. Application writers may override this
904
* method in a subclass to take specific actions at the end of
905
* each prefix mapping.</p>
907
* @param prefix The Namespace prefix being declared.
908
* @exception org.xml.sax.SAXException Any SAX exception, possibly
909
* wrapping another exception.
910
* @see org.xml.sax.ContentHandler#endPrefixMapping
912
public void endPrefixMapping(String prefix)
913
throws SAXException {
915
System.out.println("endPrefixMapping prefix=" + prefix);
921
* Receive notification of the start of an element.
923
* <p>By default, do nothing. Application writers may override this
924
* method in a subclass to take specific actions at the start of
925
* each element (such as allocating a new tree node or writing
926
* output to a file).</p>
928
* @param uri The Namespace URI, or the empty string if the
929
* element has no Namespace URI or if Namespace
930
* processing is not being performed.
931
* @param localName The local name (without prefix), or the
932
* empty string if Namespace processing is not being
934
* @param qName The qualified name (with prefix), or the
935
* empty string if qualified names are not available.
936
* @param attributes The attributes attached to the element. If
937
* there are no attributes, it shall be an empty
939
* @exception org.xml.sax.SAXException Any SAX exception, possibly
940
* wrapping another exception.
941
* @see org.xml.sax.ContentHandler#startElement
943
public void startElement(String uri, String localName,
944
String qName, Attributes attributes)
945
throws SAXException {
946
boolean dump = false;
947
XmlKeyword key = xmlKeywords.get(localName);
948
// System.out.print("<" + key.name());
949
this.attributes = attributes;
952
tech.techName = a("name");
953
tech.className = a_("class");
957
tech.minNumMetals = Integer.parseInt(a("min"));
958
tech.maxNumMetals = Integer.parseInt(a("max"));
959
tech.defaultNumMetals = Integer.parseInt(a("default"));
962
tech.scaleValue = Double.parseDouble(a("value"));
963
tech.scaleRelevant = Boolean.parseBoolean(a("relevant"));
966
tech.defaultFoundry = a("value");
969
tech.minResistance = Double.parseDouble(a("value"));
972
tech.minCapacitance = Double.parseDouble(a("value"));
975
if (curDisplayStyle != null) {
976
curLayerDisplayStyle = curDisplayStyle.newLayer(tech.findLayer(a("name")));
978
curR = curG = curB = 0;
979
patternedOnDisplay = false;
980
patternedOnPrinter = false;
981
Arrays.fill(pattern, 0);
983
// EGraphics.Outline outline = null;
984
} else if (curLayerRule != null) {
985
curDistance = new Distance();
986
Distance old = curLayerRule.put(tech.findLayer(a("name")), curDistance);
988
throw new IllegalArgumentException("Duplicate layer " + a("name"));
990
curLayer = tech.newLayer(a("name"));
991
curLayer.function = com.sun.electric.technology.Layer.Function.valueOf(a("fun"));
992
String extraFunStr = a_("extraFun");
993
if (extraFunStr != null) {
994
if (extraFunStr.equals("depletion_heavy"))
995
curLayer.extraFunction = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.HEAVY;
996
else if (extraFunStr.equals("depletion_light"))
997
curLayer.extraFunction = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.LIGHT;
998
else if (extraFunStr.equals("enhancement_heavy"))
999
curLayer.extraFunction = com.sun.electric.technology.Layer.Function.ENHANCEMENT|com.sun.electric.technology.Layer.Function.HEAVY;
1000
else if (extraFunStr.equals("enhancement_light"))
1001
curLayer.extraFunction = com.sun.electric.technology.Layer.Function.ENHANCEMENT|com.sun.electric.technology.Layer.Function.LIGHT;
1003
curLayer.extraFunction = com.sun.electric.technology.Layer.Function.parseExtraName(extraFunStr);
1008
curLayer.cif = a("cif");
1011
curLayer.skill = a("skill");
1014
curLayer.resistance = Double.parseDouble(a("resistance"));
1015
curLayer.capacitance = Double.parseDouble(a("capacitance"));
1016
curLayer.edgeCapacitance = Double.parseDouble(a("edgeCapacitance"));
1019
curLayer.pureLayerNode = new PureLayerNode();
1020
curLayer.pureLayerNode.name = a("name");
1021
String styleStr = a_("style");
1022
curLayer.pureLayerNode.style = styleStr != null ? Type.valueOf(styleStr) : Type.FILLED;
1023
curLayer.pureLayerNode.port = a("port");
1026
curArc = new ArcProto();
1027
curArc.name = a("name");
1028
curArc.function = com.sun.electric.technology.ArcProto.Function.valueOf(a("fun"));
1031
curArc.wipable = true;
1034
curArc.curvable = true;
1037
curArc.special = true;
1041
curArc.notUsed = true;
1042
if (curNode != null)
1043
curNode.notUsed = true;
1045
case skipSizeInPalette:
1047
curArc.skipSizeInPalette = true;
1048
if (curNode != null)
1049
curNode.skipSizeInPalette = true;
1052
ArcLayer arcLay = new ArcLayer();
1053
arcLay.layer = a("layer");
1054
curDistance = arcLay.extend;
1055
arcLay.style = Type.valueOf(a("style"));
1056
curArc.arcLayers.add(arcLay);
1059
curArc.arcPin = new ArcPin();
1060
curArc.arcPin.name = a("name");
1061
curArc.arcPin.portName = a("port");
1062
curArc.arcPin.elibSize = Double.valueOf(a("elibSize"));
1065
curNode = new PrimitiveNode();
1066
curNode.name = a("name");
1067
curNode.function = com.sun.electric.technology.PrimitiveNode.Function.valueOf(a("fun"));
1070
curNode.shrinkArcs = true;
1073
curNode.square = true;
1076
curNode.canBeZeroSize = true;
1079
curNode.wipes = true;
1082
curNode.lockable = true;
1085
curNode.edgeSelect = true;
1088
curNode.lowVt = true;
1091
curNode.highVt = true;
1094
curNode.nativeBit = true;
1097
curNode.od18 = true;
1100
curNode.od25 = true;
1103
curNode.od33 = true;
1106
curNode.diskOffset = EPoint.fromLambda(Double.parseDouble(a("x")), Double.parseDouble(a("y")));
1109
curDistance = curNode.defaultWidth;
1112
curDistance = curNode.defaultHeight;
1115
double lx = Double.parseDouble(a("lx"));
1116
double hx = Double.parseDouble(a("hx"));
1117
double ly = Double.parseDouble(a("ly"));
1118
double hy = Double.parseDouble(a("hy"));
1119
curNode.nodeBase = ERectangle.fromLambda(lx, ly, hx - lx, hy - ly);
1122
curNodeLayer = new NodeLayer();
1123
curNodeLayer.layer = a("layer");
1124
curNodeLayer.style = Type.valueOf(a("style"));
1125
String portNum = a_("portNum");
1126
if (portNum != null)
1127
curNodeLayer.portNum = Integer.parseInt(portNum);
1128
String electrical = a_("electrical");
1129
if (electrical != null) {
1130
if (Boolean.parseBoolean(electrical))
1131
curNodeLayer.inElectricalLayers = true;
1133
curNodeLayer.inLayers = true;
1135
curNodeLayer.inElectricalLayers = curNodeLayer.inLayers = true;
1139
if (curNodeLayer != null) {
1140
curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.BOX;
1141
curNodeLayer.lx.k = da_("klx", -1);
1142
curNodeLayer.hx.k = da_("khx", 1);
1143
curNodeLayer.ly.k = da_("kly", -1);
1144
curNodeLayer.hy.k = da_("khy", 1);
1146
if (curPort != null) {
1147
curPort.lx.k = da_("klx", -1);
1148
curPort.hx.k = da_("khx", 1);
1149
curPort.ly.k = da_("kly", -1);
1150
curPort.hy.k = da_("khy", 1);
1154
curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.POINTS;
1157
curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.MULTICUTBOX;
1158
curNodeLayer.lx.k = da_("klx", -1);
1159
curNodeLayer.hx.k = da_("khx", 1);
1160
curNodeLayer.ly.k = da_("kly", -1);
1161
curNodeLayer.hy.k = da_("khy", 1);
1162
curNodeLayer.sizeRule = a("sizeRule");
1163
curNodeLayer.sepRule = a("sepRule");
1164
curNodeLayer.sepRule2D = a_("sepRule2D");
1167
curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.BOX;
1168
curNodeLayer.lx.k = da_("klx", -1);
1169
curNodeLayer.hx.k = da_("khx", 1);
1170
curNodeLayer.ly.k = da_("kly", -1);
1171
curNodeLayer.hy.k = da_("khy", 1);
1172
curNodeLayer.lWidth = Double.parseDouble(a("lWidth"));
1173
curNodeLayer.rWidth = Double.parseDouble(a("rWidth"));
1174
curNodeLayer.tExtent = Double.parseDouble(a("tExtent"));
1175
curNodeLayer.bExtent = Double.parseDouble(a("bExtent"));
1178
if (curNodeLayer != null) {
1179
curNodeLayer.lx.addLambda(Double.parseDouble(a("klx")));
1180
curNodeLayer.hx.addLambda(Double.parseDouble(a("khx")));
1181
curNodeLayer.ly.addLambda(Double.parseDouble(a("kly")));
1182
curNodeLayer.hy.addLambda(Double.parseDouble(a("khy")));
1184
if (curPort != null) {
1185
curPort.lx.addLambda(Double.parseDouble(a("klx")));
1186
curPort.hx.addLambda(Double.parseDouble(a("khx")));
1187
curPort.ly.addLambda(Double.parseDouble(a("kly")));
1188
curPort.hy.addLambda(Double.parseDouble(a("khy")));
1192
double xm = Double.parseDouble(a("xm"));
1193
double xa = Double.parseDouble(a("xa"));
1194
double ym = Double.parseDouble(a("ym"));
1195
double ya = Double.parseDouble(a("ya"));
1196
TechPoint p = new TechPoint(new EdgeH(xm, xa), new EdgeV(ym, ya));
1197
if (curNodeLayer != null)
1198
curNodeLayer.techPoints.add(p);
1201
curPort = new PrimitivePort();
1202
curPort.name = a("name");
1205
curPort.portAngle = Integer.parseInt(a("primary"));
1206
curPort.portRange = Integer.parseInt(a("range"));
1209
curNode.specialType = com.sun.electric.technology.PrimitiveNode.POLYGONAL;
1212
curNode.specialType = com.sun.electric.technology.PrimitiveNode.SERPTRANS;
1213
curNode.specialValues = new double[6];
1214
curSpecialValueIndex = 0;
1217
curNode.nodeSizeRule = new NodeSizeRule();
1218
curNode.nodeSizeRule.width = Double.parseDouble(a("width"));
1219
curNode.nodeSizeRule.height = Double.parseDouble(a("height"));
1220
curNode.nodeSizeRule.rule = a("rule");
1223
curNode.spiceTemplate = a("value");
1226
curSpiceHeader = new SpiceHeader();
1227
curSpiceHeader.level = Integer.parseInt(a("level"));
1228
tech.spiceHeaders.add(curSpiceHeader);
1231
curSpiceHeader.spiceLines.add(a("line"));
1235
curDisplayStyle = new DisplayStyle();
1236
curDisplayStyle.name = a("name");
1237
tech.displayStyles.add(curDisplayStyle);
1239
case transparentLayer:
1240
curTransparent = Integer.parseInt(a("transparent"));
1241
curR = curG = curB = 0;
1243
case transparentColor:
1244
curTransparent = Integer.parseInt(a("transparent"));
1245
if (curTransparent > 0) {
1246
Color color = curDisplayStyle.transparentLayers.get(curTransparent - 1);
1247
curR = color.getRed();
1248
curG = color.getGreen();
1249
curB = color.getBlue();
1253
curR = Integer.parseInt(a("r"));
1254
curG = Integer.parseInt(a("g"));
1255
curB = Integer.parseInt(a("b"));
1258
curLayerDisplayStyle.mode3D = a("mode");
1259
curLayerDisplayStyle.factor3D = Double.parseDouble(a("factor"));
1263
tech.menuPalette = new MenuPalette();
1264
tech.menuPalette.numColumns = Integer.parseInt(a("numColumns"));
1267
curMenuBox = new ArrayList<Object>();
1268
tech.menuPalette.menuBoxes.add(curMenuBox);
1271
curMenuCell = new MenuCell();
1272
curMenuCell.cellName = a("cellName");
1275
curMenuNodeInst = new MenuNodeInst();
1276
curMenuNodeInst.protoName = a("protoName");
1277
curMenuNodeInst.function = com.sun.electric.technology.PrimitiveNode.Function.valueOf(a("function"));
1278
String rotField = a_("rotation");
1279
if (rotField != null) curMenuNodeInst.rotation = Integer.parseInt(rotField);
1282
curMenuNodeInst.text = a("text");
1283
curMenuNodeInst.fontSize = Double.parseDouble(a("size"));
1286
String kStr = a_("k");
1288
Layer layer2 = null;
1289
String layerStr = a_("layer");
1290
if (layerStr != null) {
1291
layer = tech.findLayer(layerStr);
1292
assert layer != null;
1294
String layerStr2 = layerStr != null ? a_("layer2") : null;
1295
if (layerStr2 != null) {
1296
layer2 = tech.findLayer(layerStr2);
1297
assert layer2 != null;
1299
curDistance.addRule(a("ruleName"), layer, layer2, kStr != null ? Double.valueOf(kStr) : 1);
1302
curRuleSet = tech.newRuleSet(a("ruleName"));
1305
curLayerRule = curRuleSet.newLayerRule(a("ruleName"));
1308
curFoundry = new Foundry();
1309
curFoundry.name = a("name");
1310
tech.foundries.add(curFoundry);
1313
curFoundry.layerGds.put(a("layer"), a("gds"));
1317
case NodeLayersRule:
1319
DRCTemplate.parseXmlElement(curFoundry.rules, key.name(), attributes);
1324
// System.out.print(">");
1327
assert !key.hasText;
1328
// System.out.println(">");
1330
System.out.println("startElement uri=" + uri + " localName=" + localName + " qName=" + qName);
1331
for (int i = 0; i < attributes.getLength(); i++) {
1332
System.out.println("\tattribute " + i + " uri=" + attributes.getURI(i) +
1333
" localName=" + attributes.getLocalName(i) + " QName=" + attributes.getQName(i) +
1334
" type=" + attributes.getType(i) + " value=<" + attributes.getValue(i) + ">");
1339
private double da_(String attrName, double defaultValue) {
1340
String s = a_(attrName);
1341
return s != null ? Double.parseDouble(s) : defaultValue;
1344
private String a(String attrName) {
1345
String v = attributes.getValue(attrName);
1346
// System.out.print(" " + attrName + "=\"" + v + "\"");
1350
private String a_(String attrName) {
1351
String v = attributes.getValue(attrName);
1352
if (v == null) return null;
1353
// System.out.print(" " + attrName + "=\"" + v + "\"");
1359
* Receive notification of the end of an element.
1361
* <p>By default, do nothing. Application writers may override this
1362
* method in a subclass to take specific actions at the end of
1363
* each element (such as finalising a tree node or writing
1364
* output to a file).</p>
1366
* @param uri The Namespace URI, or the empty string if the
1367
* element has no Namespace URI or if Namespace
1368
* processing is not being performed.
1369
* @param localName The local name (without prefix), or the
1370
* empty string if Namespace processing is not being
1372
* @param qName The qualified name (with prefix), or the
1373
* empty string if qualified names are not available.
1374
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1375
* wrapping another exception.
1376
* @see org.xml.sax.ContentHandler#endElement
1378
public void endElement(String uri, String localName, String qName)
1379
throws SAXException {
1380
XmlKeyword key = xmlKeywords.get(localName);
1382
String text = endCharacters();
1383
// System.out.println(text + "</" + localName + ">");
1386
tech.shortTechName = text;
1389
tech.description = text;
1392
if (curLayer != null)
1393
curLayer.pureLayerNode.oldName = text;
1395
curArc.oldName = text;
1396
if (curNode != null)
1397
curNode.oldName = text;
1400
curArc.extended = Boolean.parseBoolean(text);
1403
curArc.fixedAngle = Boolean.parseBoolean(text);
1406
curArc.wipable = Boolean.parseBoolean(text);
1408
case angleIncrement:
1409
curArc.angleIncrement = Integer.parseInt(text);
1412
curArc.antennaRatio = Double.parseDouble(text);
1414
case elibWidthOffset:
1415
curArc.elibWidthOffset = Double.parseDouble(text);
1418
curPort.portTopology = Integer.parseInt(text);
1421
if (curLayer != null && curLayer.pureLayerNode != null)
1422
curLayer.pureLayerNode.portArcs.add(text);
1423
if (curArc != null && curArc.arcPin != null)
1424
curArc.arcPin.portArcs.add(text);
1425
if (curPort != null)
1426
curPort.portArcs.add(text);
1429
curNode.specialValues[curSpecialValueIndex++] = Double.parseDouble(text);
1433
curR = Integer.parseInt(text);
1436
curG = Integer.parseInt(text);
1439
curB = Integer.parseInt(text);
1441
case patternedOnDisplay:
1442
patternedOnDisplay = Boolean.parseBoolean(text);
1444
case patternedOnPrinter:
1445
patternedOnPrinter = Boolean.parseBoolean(text);
1449
assert text.length() == 16;
1450
for (int j = 0; j < text.length(); j++) {
1451
if (text.charAt(text.length() - j - 1) != ' ')
1454
pattern[curPatternIndex++] = p;
1457
outline = EGraphics.Outline.valueOf(text);
1460
opacity = Double.parseDouble(text);
1463
foreground = Boolean.parseBoolean(text);
1467
curMenuBox.add(tech.findArc(text));
1470
curMenuBox.add(tech.findNode(text));
1473
curMenuBox.add(text);
1476
curDistance.addLambda(Double.parseDouble(text));
1483
// System.out.println("</" + localName + ">");
1488
if (curDisplayStyle != null) {
1489
assert curPatternIndex == pattern.length;
1490
curLayerDisplayStyle.desc = new EGraphics(patternedOnDisplay, patternedOnPrinter, outline, curTransparent,
1491
curR, curG, curB, opacity, foreground, pattern.clone());
1492
curLayerDisplayStyle = null;
1493
} else if (curLayerRule != null) {
1500
tech.arcs.add(curArc);
1504
tech.nodes.add(curNode);
1508
curNode.nodeLayers.add(curNodeLayer);
1509
curNodeLayer = null;
1512
curNode.ports.add(curPort);
1516
curMenuBox.add(curMenuNodeInst);
1517
curMenuNodeInst = null;
1521
curDisplayStyle = null;
1523
case transparentLayer:
1524
while (curTransparent > curDisplayStyle.transparentLayers.size())
1525
curDisplayStyle.transparentLayers.add(null);
1526
Color oldColor = curDisplayStyle.transparentLayers.set(curTransparent - 1, new Color(curR, curG, curB));
1527
assert oldColor == null;
1531
curMenuBox.add("LOADCELL " + curMenuCell.cellName);
1532
// curMenuBox.add(curMenuCell);
1540
curLayerRule = null;
1545
case defaultFoundry:
1547
case minCapacitance:
1557
case skipSizeInPalette:
1593
case transparentColor:
1605
case NodeLayersRule:
1615
* Receive notification of character data inside an element.
1617
* <p>By default, do nothing. Application writers may override this
1618
* method to take specific actions for each chunk of character data
1619
* (such as adding the data to a node or buffer, or printing it to
1622
* @param ch The characters.
1623
* @param start The start position in the character array.
1624
* @param length The number of characters to use from the
1626
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1627
* wrapping another exception.
1628
* @see org.xml.sax.ContentHandler#characters
1630
public void characters(char ch[], int start, int length)
1631
throws SAXException {
1632
if (acceptCharacters) {
1633
charBuffer.append(ch, start, length);
1635
boolean nonBlank = false;
1636
for (int i = 0; i < length; i++) {
1637
char c = ch[start + i];
1638
nonBlank = nonBlank || c != ' ' && c != '\n';
1641
System.out.print("characters size=" + ch.length + " start=" + start + " length=" + length + " {");
1642
for (int i = 0; i < length; i++)
1643
System.out.print(ch[start + i]);
1644
System.out.println("}");
1651
* Receive notification of ignorable whitespace in element content.
1653
* <p>By default, do nothing. Application writers may override this
1654
* method to take specific actions for each chunk of ignorable
1655
* whitespace (such as adding data to a node or buffer, or printing
1656
* it to a file).</p>
1658
* @param ch The whitespace characters.
1659
* @param start The start position in the character array.
1660
* @param length The number of characters to use from the
1662
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1663
* wrapping another exception.
1664
* @see org.xml.sax.ContentHandler#ignorableWhitespace
1666
public void ignorableWhitespace(char ch[], int start, int length)
1667
throws SAXException {
1673
* Receive notification of a processing instruction.
1675
* <p>By default, do nothing. Application writers may override this
1676
* method in a subclass to take specific actions for each
1677
* processing instruction, such as setting status variables or
1678
* invoking other methods.</p>
1680
* @param target The processing instruction target.
1681
* @param data The processing instruction data, or null if
1683
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1684
* wrapping another exception.
1685
* @see org.xml.sax.ContentHandler#processingInstruction
1687
public void processingInstruction(String target, String data)
1688
throws SAXException {
1694
* Receive notification of a skipped entity.
1696
* <p>By default, do nothing. Application writers may override this
1697
* method in a subclass to take specific actions for each
1698
* processing instruction, such as setting status variables or
1699
* invoking other methods.</p>
1701
* @param name The name of the skipped entity.
1702
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1703
* wrapping another exception.
1704
* @see org.xml.sax.ContentHandler#processingInstruction
1706
public void skippedEntity(String name)
1707
throws SAXException {
1713
////////////////////////////////////////////////////////////////////
1714
// Default implementation of the ErrorHandler interface.
1715
////////////////////////////////////////////////////////////////////
1719
* Receive notification of a parser warning.
1721
* <p>The default implementation does nothing. Application writers
1722
* may override this method in a subclass to take specific actions
1723
* for each warning, such as inserting the message in a log file or
1724
* printing it to the console.</p>
1726
* @param e The warning information encoded as an exception.
1727
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1728
* wrapping another exception.
1729
* @see org.xml.sax.ErrorHandler#warning
1730
* @see org.xml.sax.SAXParseException
1732
public void warning(SAXParseException e)
1733
throws SAXException {
1734
System.out.println("warning publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
1735
" line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
1740
* Receive notification of a recoverable parser error.
1742
* <p>The default implementation does nothing. Application writers
1743
* may override this method in a subclass to take specific actions
1744
* for each error, such as inserting the message in a log file or
1745
* printing it to the console.</p>
1747
* @param e The error information encoded as an exception.
1748
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1749
* wrapping another exception.
1750
* @see org.xml.sax.ErrorHandler#warning
1751
* @see org.xml.sax.SAXParseException
1753
public void error(SAXParseException e)
1754
throws SAXException {
1755
// System.out.println("error publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
1756
// " line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
1762
* Report a fatal XML parsing error.
1764
* <p>The default implementation throws a SAXParseException.
1765
* Application writers may override this method in a subclass if
1766
* they need to take specific actions for each fatal error (such as
1767
* collecting all of the errors into a single report): in any case,
1768
* the application must stop all regular processing when this
1769
* method is invoked, since the document is no longer reliable, and
1770
* the parser may no longer report parsing events.</p>
1772
* @param e The error information encoded as an exception.
1773
* @exception org.xml.sax.SAXException Any SAX exception, possibly
1774
* wrapping another exception.
1775
* @see org.xml.sax.ErrorHandler#fatalError
1776
* @see org.xml.sax.SAXParseException
1778
public void fatalError(SAXParseException e)
1779
throws SAXException {
1780
// System.out.println("fatal error publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
1781
// " line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
1787
private static class Writer {
1788
private static final int INDENT_WIDTH = 4;
1789
protected final PrintWriter out;
1791
protected boolean indentEmitted;
1793
private Writer(PrintWriter out) {
1797
private void writeTechnology(Technology t) {
1798
Calendar cal = Calendar.getInstance();
1799
cal.setTime(new Date());
1804
out.println("<!--");
1806
pl(" * Electric(tm) VLSI Design System");
1808
pl(" * File: " + t.techName + ".xml");
1809
pl(" * " + t.techName + " technology description");
1810
pl(" * Generated automatically from a library");
1812
pl(" * Copyright (c) " + cal.get(Calendar.YEAR) + " Sun Microsystems and Static Free Software");
1814
pl(" * Electric(tm) is free software; you can redistribute it and/or modify");
1815
pl(" * it under the terms of the GNU General Public License as published by");
1816
pl(" * the Free Software Foundation; either version 3 of the License, or");
1817
pl(" * (at your option) any later version.");
1819
pl(" * Electric(tm) is distributed in the hope that it will be useful,");
1820
pl(" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
1821
pl(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
1822
pl(" * GNU General Public License for more details.");
1824
pl(" * You should have received a copy of the GNU General Public License");
1825
pl(" * along with Electric(tm); see the file COPYING. If not, write to");
1826
pl(" * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,");
1827
pl(" * Boston, Mass 02111-1307, USA.");
1832
b(XmlKeyword.technology); a("name", t.techName); a("class", t.className); l();
1833
a("xmlns", "http://electric.sun.com/Technology"); l();
1834
a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); l();
1835
a("xsi:schemaLocation", "http://electric.sun.com/Technology ../../technology/xml/TechnologyParam.xsd"); cl();
1838
bcpel(XmlKeyword.shortName, t.shortTechName);
1839
bcpel(XmlKeyword.description, t.description);
1840
b(XmlKeyword.numMetals); a("min", t.minNumMetals); a("max", t.maxNumMetals); a("default", t.defaultNumMetals); el();
1841
b(XmlKeyword.scale); a("value", t.scaleValue); a("relevant", t.scaleRelevant); el();
1842
b(XmlKeyword.defaultFoundry); a("value", t.defaultFoundry); el();
1843
b(XmlKeyword.minResistance); a("value", t.minResistance); el();
1844
b(XmlKeyword.minCapacitance); a("value", t.minCapacitance); el();
1845
// printlnAttribute(" gateLengthSubtraction", gi.gateShrinkage);
1846
// printlnAttribute(" gateInclusion", gi.includeGateInResistance);
1847
// printlnAttribute(" groundNetInclusion", gi.includeGround);
1850
comment("**************************************** LAYERS ****************************************");
1851
for (Layer li: t.layers.values()) {
1855
comment("******************** ARCS ********************");
1856
for (ArcProto ai: t.arcs) {
1861
comment("******************** NODES ********************");
1862
for (PrimitiveNode ni: t.nodes) {
1867
for (SpiceHeader spiceHeader: t.spiceHeaders)
1868
writeSpiceHeaderXml(spiceHeader);
1870
for (DisplayStyle displayStyle: t.displayStyles)
1871
writeDisplayStyleXml(displayStyle);
1873
writeMenuPaletteXml(t.menuPalette);
1875
for (RuleSet ruleSet: t.ruleSets.values())
1878
for (Foundry foundry: t.foundries)
1879
writeFoundryXml(foundry);
1881
el(XmlKeyword.technology);
1884
private void writeXml(Layer li) {
1885
String funString = null;
1886
int funExtra = li.extraFunction;
1887
if (funExtra != 0) {
1888
final int deplEnhMask = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.ENHANCEMENT;
1889
if ((funExtra&deplEnhMask) != 0) {
1890
funString = com.sun.electric.technology.Layer.Function.getExtraName(funExtra&(deplEnhMask));
1891
funExtra &= ~deplEnhMask;
1893
funString += "_" + com.sun.electric.technology.Layer.Function.getExtraName(funExtra);
1895
funString = com.sun.electric.technology.Layer.Function.getExtraName(funExtra);
1898
b(XmlKeyword.layer); a("name", li.name); a("fun", li.function.name()); a("extraFun", funString); cl();
1900
if (li.cif != null && li.cif.length() > 0) {
1901
b(XmlKeyword.cifLayer); a("cif", li.cif); el();
1903
if (li.skill != null && li.skill.length() > 0) {
1904
b(XmlKeyword.skillLayer); a("skill", li.skill); el();
1907
// write the SPICE information
1908
if (li.resistance != 0 || li.capacitance != 0 || li.edgeCapacitance != 0) {
1909
b(XmlKeyword.parasitics); a("resistance", li.resistance); a("capacitance", li.capacitance); a("edgeCapacitance", li.edgeCapacitance); el();
1911
if (li.pureLayerNode != null) {
1912
String nodeName = li.pureLayerNode.name;
1913
Type style = li.pureLayerNode.style;
1914
String styleStr = style == Type.FILLED ? null : style.name();
1915
String portName = li.pureLayerNode.port;
1916
b(XmlKeyword.pureLayerNode); a("name", nodeName); a("style", styleStr); a("port", portName);
1917
if (li.pureLayerNode.oldName == null && li.pureLayerNode.portArcs.isEmpty()) {
1921
bcpel(XmlKeyword.oldName, li.pureLayerNode.oldName);
1922
for (String portArc: li.pureLayerNode.portArcs)
1923
bcpel(XmlKeyword.portArc, portArc);
1924
el(XmlKeyword.pureLayerNode);
1927
el(XmlKeyword.layer);
1931
private void writeXml(ArcProto ai) {
1932
b(XmlKeyword.arcProto); a("name", ai.name); a("fun", ai.function.getConstantName()); cl();
1933
bcpel(XmlKeyword.oldName, ai.oldName);
1936
bel(XmlKeyword.wipable);
1938
bel(XmlKeyword.curvable);
1940
bel(XmlKeyword.special);
1942
bel(XmlKeyword.notUsed);
1943
if (ai.skipSizeInPalette)
1944
bel(XmlKeyword.skipSizeInPalette);
1945
bcpel(XmlKeyword.extended, ai.extended);
1946
bcpel(XmlKeyword.fixedAngle, ai.fixedAngle);
1947
bcpel(XmlKeyword.angleIncrement, ai.angleIncrement);
1948
if (ai.antennaRatio != 0)
1949
bcpel(XmlKeyword.antennaRatio, ai.antennaRatio);
1950
if (ai.elibWidthOffset != 0)
1951
bcpel(XmlKeyword.elibWidthOffset, ai.elibWidthOffset);
1953
for (ArcLayer al: ai.arcLayers) {
1954
String style = al.style == Type.FILLED ? "FILLED" : "CLOSED";
1955
b(XmlKeyword.arcLayer); a("layer", al.layer); a("style", style);
1956
if (al.extend.isEmpty()) {
1960
writeDistance(al.extend);
1961
el(XmlKeyword.arcLayer);
1964
if (ai.arcPin != null) {
1965
b(XmlKeyword.arcPin); a("name", ai.arcPin.name); a("port", ai.arcPin.portName); a("elibSize", ai.arcPin.elibSize);
1966
if (ai.arcPin.portArcs.isEmpty()) {
1970
for (String portArc: ai.arcPin.portArcs)
1971
bcpel(XmlKeyword.portArc, portArc);
1972
el(XmlKeyword.arcPin);
1975
el(XmlKeyword.arcProto);
1978
private void writeXml(PrimitiveNode ni) {
1979
b(XmlKeyword.primitiveNode); a("name", ni.name); a("fun", ni.function.name()); cl();
1980
bcpel(XmlKeyword.oldName, ni.oldName);
1983
bel(XmlKeyword.shrinkArcs);
1985
bel(XmlKeyword.square);
1986
if (ni.canBeZeroSize)
1987
bel(XmlKeyword.canBeZeroSize);
1989
bel(XmlKeyword.wipes);
1991
bel(XmlKeyword.lockable);
1993
bel(XmlKeyword.edgeSelect);
1994
if (ni.skipSizeInPalette)
1995
bel(XmlKeyword.skipSizeInPalette);
1997
bel(XmlKeyword.notUsed);
1999
bel(XmlKeyword.lowVt);
2001
bel(XmlKeyword.highVt);
2003
bel(XmlKeyword.nativeBit);
2005
bel(XmlKeyword.od18);
2007
bel(XmlKeyword.od25);
2009
bel(XmlKeyword.od33);
2011
if (ni.diskOffset != null) {
2012
b(XmlKeyword.diskOffset); a("x", ni.diskOffset.getLambdaX()); a("y", ni.diskOffset.getLambdaY()); el();
2015
if (!ni.defaultWidth.isEmpty()) {
2016
bcl(XmlKeyword.defaultWidth);
2017
writeDistance(ni.defaultWidth);
2018
el(XmlKeyword.defaultWidth);
2021
if (!ni.defaultHeight.isEmpty()) {
2022
bcl(XmlKeyword.defaultHeight);
2023
writeDistance(ni.defaultHeight);
2024
el(XmlKeyword.defaultHeight);
2027
if (ni.nodeBase != null) {
2028
double lx = ni.nodeBase.getLambdaMinX();
2029
double hx = ni.nodeBase.getLambdaMaxX();
2030
double ly = ni.nodeBase.getLambdaMinY();
2031
double hy = ni.nodeBase.getLambdaMaxY();
2032
b(XmlKeyword.nodeBase); a("lx", lx); a("hx", hx); a("ly", ly); a("hy", hy); el();
2035
for(int j=0; j<ni.nodeLayers.size(); j++) {
2036
NodeLayer nl = ni.nodeLayers.get(j);
2037
b(XmlKeyword.nodeLayer); a("layer", nl.layer); a("style", nl.style.name());
2038
if (nl.portNum != 0) a("portNum", Integer.valueOf(nl.portNum));
2039
if (!(nl.inLayers && nl.inElectricalLayers))
2040
a("electrical", nl.inElectricalLayers);
2042
switch (nl.representation) {
2043
case com.sun.electric.technology.Technology.NodeLayer.BOX:
2044
if (ni.specialType == com.sun.electric.technology.PrimitiveNode.SERPTRANS) {
2045
writeBox(XmlKeyword.serpbox, nl.lx, nl.hx, nl.ly, nl.hy);
2046
a("lWidth", nl.lWidth); a("rWidth", nl.rWidth); a("tExtent", nl.tExtent); a("bExtent", nl.bExtent); cl();
2047
writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
2048
el(XmlKeyword.serpbox);
2050
writeBox(XmlKeyword.box, nl.lx, nl.hx, nl.ly, nl.hy); cl();
2051
writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
2055
case com.sun.electric.technology.Technology.NodeLayer.POINTS:
2056
b(XmlKeyword.points); el();
2058
case com.sun.electric.technology.Technology.NodeLayer.MULTICUTBOX:
2059
writeBox(XmlKeyword.multicutbox, nl.lx, nl.hx, nl.ly, nl.hy);
2060
a("sizeRule", nl.sizeRule); a("sepRule", nl.sepRule); a("sepRule2D", nl.sepRule2D);
2061
if (nl.lx.isEmpty() && nl.hx.isEmpty() && nl.ly.isEmpty() && nl.hy.isEmpty()) {
2065
writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
2066
el(XmlKeyword.multicutbox);
2070
for (TechPoint tp: nl.techPoints) {
2071
double xm = tp.getX().getMultiplier();
2072
double xa = tp.getX().getAdder();
2073
double ym = tp.getY().getMultiplier();
2074
double ya = tp.getY().getAdder();
2075
b(XmlKeyword.techPoint); a("xm", xm); a("xa", xa); a("ym", ym); a("ya", ya); el();
2077
el(XmlKeyword.nodeLayer);
2079
for (int j = 0; j < ni.ports.size(); j++) {
2080
PrimitivePort pd = ni.ports.get(j);
2081
b(XmlKeyword.primitivePort); a("name", pd.name); cl();
2082
b(XmlKeyword.portAngle); a("primary", pd.portAngle); a("range", pd.portRange); el();
2083
bcpel(XmlKeyword.portTopology, pd.portTopology);
2085
writeBox(XmlKeyword.box, pd.lx, pd.hx, pd.ly, pd.hy); cl();
2086
writeLambdaBox(pd.lx, pd.hx, pd.ly, pd.hy);
2089
for (String portArc: pd.portArcs)
2090
bcpel(XmlKeyword.portArc, portArc);
2091
el(XmlKeyword.primitivePort);
2093
switch (ni.specialType) {
2094
case com.sun.electric.technology.PrimitiveNode.POLYGONAL:
2095
bel(XmlKeyword.polygonal);
2097
case com.sun.electric.technology.PrimitiveNode.SERPTRANS:
2098
b(XmlKeyword.serpTrans); cl();
2099
for (int i = 0; i < 6; i++) {
2100
bcpel(XmlKeyword.specialValue, ni.specialValues[i]);
2102
el(XmlKeyword.serpTrans);
2105
if (ni.nodeSizeRule != null) {
2106
NodeSizeRule r = ni.nodeSizeRule;
2107
b(XmlKeyword.minSizeRule); a("width", r.width); a("height", r.height); a("rule", r.rule); el();
2109
if (ni.spiceTemplate != null)
2111
b(XmlKeyword.spiceTemplate); a("value", ni.spiceTemplate); el();
2114
el(XmlKeyword.primitiveNode);
2117
private void writeDistance(Distance d) {
2118
d.writeXml(this, true);
2121
private void writeBox(XmlKeyword keyword, Distance lx, Distance hx, Distance ly, Distance hy) {
2123
if (lx.k != -1) a("klx", lx.k);
2124
if (hx.k != 1) a("khx", hx.k);
2125
if (ly.k != -1) a("kly", ly.k);
2126
if (hy.k != 1) a("khy", hy.k);
2129
private void writeLambdaBox(Distance lx, Distance hx, Distance ly, Distance hy) {
2130
double lxv = lx.getLambda(EMPTY_CONTEXT);
2131
double hxv = hx.getLambda(EMPTY_CONTEXT);
2132
double lyv = ly.getLambda(EMPTY_CONTEXT);
2133
double hyv = hy.getLambda(EMPTY_CONTEXT);
2134
// if (lxv == 0 && hxv == 0 && lyv == 0 && hyv == 0) return;
2135
b(XmlKeyword.lambdaBox); a("klx", lxv); a("khx", hxv); a("kly", lyv); a("khy", hyv); el();
2138
private void writeSpiceHeaderXml(SpiceHeader spiceHeader) {
2139
b(XmlKeyword.spiceHeader); a("level", spiceHeader.level); cl();
2140
for (String line: spiceHeader.spiceLines) {
2141
b(XmlKeyword.spiceLine); a("line", line); el();
2143
el(XmlKeyword.spiceHeader);
2147
private void writeDisplayStyleXml(DisplayStyle displayStyle) {
2148
b(XmlKeyword.displayStyle); a("name", displayStyle.name); cl();
2150
if (displayStyle.transparentLayers.size() != 0) {
2151
comment("Transparent layers");
2152
for (int i = 0; i < displayStyle.transparentLayers.size(); i++) {
2153
Color color = displayStyle.transparentLayers.get(i);
2154
b(XmlKeyword.transparentLayer); a("transparent", i + 1); cl();
2155
bcpel(XmlKeyword.r, color.getRed());
2156
bcpel(XmlKeyword.g, color.getGreen());
2157
bcpel(XmlKeyword.b, color.getBlue());
2158
el(XmlKeyword.transparentLayer);
2163
for (LayerDisplayStyle l: displayStyle.layerStyles.values()) {
2164
b(XmlKeyword.layer); a("name", l.layer.name); cl();
2165
EGraphics desc = l.desc;
2166
if (desc.getTransparentLayer() > 0) {
2167
b(XmlKeyword.transparentColor); a("transparent", desc.getTransparentLayer()); el();
2169
Color color = desc.getColor();
2170
b(XmlKeyword.opaqueColor); a("r", color.getRed()); a("g", color.getGreen()); a("b", color.getBlue()); el();
2173
bcpel(XmlKeyword.patternedOnDisplay, desc.isPatternedOnDisplay());
2174
bcpel(XmlKeyword.patternedOnPrinter, desc.isPatternedOnPrinter());
2176
int [] pattern = desc.getPattern();
2177
for(int j=0; j<16; j++) {
2179
for(int k=0; k<16; k++)
2180
p += (pattern[j] & (1 << (15-k))) != 0 ? 'X' : ' ';
2181
bcpel(XmlKeyword.pattern, p);
2184
if (desc.getOutlined() != null)
2185
bcpel(XmlKeyword.outlined, desc.getOutlined().getConstName());
2186
bcpel(XmlKeyword.opacity, desc.getOpacity());
2187
bcpel(XmlKeyword.foreground, desc.getForeground());
2189
// write the 3D information
2190
if (l.mode3D != null) {
2191
b(XmlKeyword.display3D); a("mode", l.mode3D); a("factor", l.factor3D); el();
2194
el(XmlKeyword.layer);
2197
el(XmlKeyword.displayStyle);
2201
public void writeMenuPaletteXml(MenuPalette menuPalette) {
2202
if (menuPalette == null) return;
2203
b(XmlKeyword.menuPalette); a("numColumns", menuPalette.numColumns); cl();
2204
for (int i = 0; i < menuPalette.menuBoxes.size(); i++) {
2205
if (i % menuPalette.numColumns == 0)
2207
writeMenuBoxXml(menuPalette.menuBoxes.get(i));
2210
el(XmlKeyword.menuPalette);
2214
private void writeMenuBoxXml(List<Object> list) {
2215
b(XmlKeyword.menuBox);
2216
if (list.size() == 0) {
2221
for (Object o: list) {
2222
if (o instanceof ArcProto) {
2223
bcpel(XmlKeyword.menuArc, ((ArcProto)o).name);
2224
} else if (o instanceof PrimitiveNode) {
2225
bcpel(XmlKeyword.menuNode, ((PrimitiveNode)o).name);
2226
} else if (o instanceof MenuCell) {
2227
MenuCell cell = (MenuCell)o;
2228
b(XmlKeyword.menuCell); a("cellName", cell.cellName); el();
2229
} else if (o instanceof MenuNodeInst) {
2230
MenuNodeInst ni = (MenuNodeInst)o;
2231
b(XmlKeyword.menuNodeInst); a("protoName", ni.protoName); a("function", ni.function.name());
2232
if (ni.rotation != 0) a("rotation", ni.rotation);
2233
if (ni.text == null) {
2237
b(XmlKeyword.menuNodeText); a("text", ni.text); a("size", ni.fontSize); el();
2238
el(XmlKeyword.menuNodeInst);
2241
if (o == null) bel(XmlKeyword.menuText); else
2242
bcpel(XmlKeyword.menuText, o);
2245
el(XmlKeyword.menuBox);
2248
private void writeXml(RuleSet ruleSet) {
2249
b(XmlKeyword.ruleSet); a("name", ruleSet.name); cl();
2250
for (Map.Entry<String,Map<Layer,Distance>> e: ruleSet.layerRules.entrySet())
2251
writeLayerRuleXml(e.getKey(), e.getValue());
2252
el(XmlKeyword.ruleSet);
2256
private void writeLayerRuleXml(String ruleName, Map<Layer,Distance> sizes) {
2257
if (sizes.isEmpty()) return;
2258
b(XmlKeyword.layerRule); a("ruleName", ruleName); cl();
2259
int maxNameLength = 0;
2260
for (Layer l: sizes.keySet())
2261
maxNameLength = Math.max(maxNameLength, l.name.length());
2262
for (Map.Entry<Layer,Distance> e: sizes.entrySet()) {
2263
String layerName = e.getKey().name;
2264
Distance d = e.getValue();
2265
b(XmlKeyword.layer); a("name", layerName); c();
2266
s(maxNameLength - layerName.length());
2267
d.writeXml(this, false);
2268
el(XmlKeyword.layer);
2270
el(XmlKeyword.layerRule);
2273
private void writeFoundryXml(Foundry foundry) {
2274
b(XmlKeyword.Foundry); a("name", foundry.name); cl();
2276
for (Map.Entry<String,String> e: foundry.layerGds.entrySet()) {
2277
b(XmlKeyword.layerGds); a("layer", e.getKey()); a("gds", e.getValue()); el();
2280
for (DRCTemplate rule: foundry.rules)
2281
DRCTemplate.exportDRCRule(out, rule);
2282
el(XmlKeyword.Foundry);
2285
private void header() {
2287
out.print("<?xml"); a("version", "1.0"); a("encoding", "UTF-8"); out.println("?>");
2290
private void comment(String s) {
2292
out.print("<!-- "); p(s); out.print(" -->"); l();
2298
private void a(String name, Object value) {
2300
if (value == null) return;
2301
out.print(" " + name + "=\"");
2302
p(value.toString());
2306
private void bcpe(XmlKeyword key, Object v) {
2307
if (v == null) return;
2308
b(key); c(); p(v.toString()); e(key);
2311
private void bcpel(XmlKeyword key, Object v) {
2312
if (v == null) return;
2313
b(key); c(); p(v.toString()); el(key);
2316
private void bcl(XmlKeyword key) {
2320
private void bel(XmlKeyword key) {
2325
* Print text with replacement of special chars.
2327
private void pl(String s) {
2333
* Print text with replacement of special chars.
2335
protected void p(String s) {
2336
assert indentEmitted;
2337
for (int i = 0; i < s.length(); i++) {
2338
char c = s.charAt(i);
2350
out.print("'");
2362
* Print element name, and indent.
2364
private void b(XmlKeyword key) {
2367
out.print(key.name());
2368
indent += INDENT_WIDTH;
2372
assert indentEmitted;
2378
assert indentEmitted;
2386
private void el(XmlKeyword key) {
2391
assert indentEmitted;
2393
indent -= INDENT_WIDTH;
2396
private void e(XmlKeyword key) {
2397
indent -= INDENT_WIDTH;
2400
out.print(key.name());
2404
protected void checkIndent() {
2405
if (indentEmitted) return;
2407
indentEmitted = true;
2410
protected void s(int numSpaces) {
2411
for (int i = 0; i < numSpaces; i++)
2418
protected void l() {
2420
indentEmitted = false;
2424
public static DistanceContext EMPTY_CONTEXT = new DistanceContext() {
2425
public double getRule(String ruleName) {
2426
throw new UnsupportedOperationException();
2431
* Class to write the XML without multiple lines and indentation.
2432
* Useful when the XML is to be a single string.
2434
private static class OneLineWriter extends Writer
2436
private OneLineWriter(PrintWriter out)
2442
* Print text without replacement of special chars.
2445
protected void p(String s)
2447
for (int i = 0; i < s.length(); i++)
2448
out.print(s.charAt(i));
2452
protected void checkIndent() { indentEmitted = true; }
2455
* Do not print new line.
2458
protected void l() { indentEmitted = false; }