/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: ManhattanOrientationTest.java
*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.api.minarea;
import com.sun.electric.api.minarea.launcher.DefaultLayoutCell;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import com.sun.electric.api.minarea.geometry.Point;
import com.sun.electric.api.minarea.geometry.Polygon.Rectangle;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.URL;
/**
*
*/
public class CIFParserTest {
public CIFParserTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void writeSerializations() {
URL url = CIFParserTest.class.getResource("SimpleHierarchy.cif");
int scaleFactor = 10;
writeSerialization("BasicAreas_CPG.lay", url, scaleFactor, "CPG", 101);
writeSerialization("BasicAreas_CMF.lay", url, scaleFactor, "CMF", 101);
writeSerialization("BasicAreas_CSP.lay", url, scaleFactor, "CSP", 101);
writeSerialization("SimpleHierarchy_CPG.lay", url, scaleFactor, "CPG", 102);
writeSerialization("SimpleHierarchy_CMF.lay", url, scaleFactor, "CMF", 102);
writeSerialization("SimpleHierarchy_CSP.lay", url, scaleFactor, "CSP", 102);
}
private static void writeSerialization(String fileName, URL cifUrl, int scaleFactor, String layerSelector, int topCellId) {
boolean COMPARE = true;
try {
if (COMPARE) {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
writeSerialization(ba, cifUrl, scaleFactor, layerSelector, topCellId);
ba.close();
byte[] result = ba.toByteArray();
InputStream in = CIFParserTest.class.getResourceAsStream("launcher/" + fileName);
byte[] expected = new byte[in.available()];
assertEquals(result.length, in.read(expected));
assertArrayEquals(expected, result);
} else {
FileOutputStream os = new FileOutputStream(fileName);
writeSerialization(os, cifUrl, scaleFactor, layerSelector, topCellId);
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void writeSerialization(OutputStream os, URL cifUrl, int scaleFactor, String layerSelector, int topCellId) throws IOException {
boolean DEBUG = false;
CIF cif;
GenCIFActions gcif = new GenCIFActions();
gcif.layerSelector = layerSelector;
gcif.scaleFactor = scaleFactor;
if (DEBUG) {
DebugCIFActions dcif = new DebugCIFActions();
dcif.out = System.out;
dcif.impl = gcif;
cif = new CIF(dcif);
} else {
cif = new CIF(gcif);
}
cif.openTextInput(cifUrl);
cif.importALibrary();
cif.closeInput();
LayoutCell topCell = gcif.cells.get(Integer.valueOf(topCellId));
ObjectOutputStream out = new ObjectOutputStream(os);
out.writeObject(topCell);
out.close();
}
public static class GenCIFActions implements CIF.CIFActions {
private int scaleFactor;
private String layerSelector;
private Map<Integer, DefaultLayoutCell> cells = new HashMap<Integer, DefaultLayoutCell>();
private DefaultLayoutCell curCell;
private ManhattanOrientation curOrient;
// private long[] curTranslate = new long[2];
private Point curTranslate;
private boolean isSelectedLayer;
public void initInterpreter() {
cells.clear();
curCell = null;
}
public void makeWire(int width/* , path */) {
}
public void makeStartDefinition(int symbol, int mtl, int div) {
Integer symbolObj = Integer.valueOf(symbol);
assert curCell == null;
if (cells.containsKey(symbolObj)) {
throw new IllegalStateException("attempt to redefine symbol " + symbol);
}
curCell = new DefaultLayoutCell(symbolObj.toString());
cells.put(symbolObj, curCell);
isSelectedLayer = false;
}
public void makeEndDefinition() {
assert curCell != null;
curCell = null;
}
public void makeDeleteDefinition(int n) {
System.out.println("makeDeleteDefinition not supported");
}
public void initTransform() {
curOrient = ManhattanOrientation.R0;
curTranslate = new Point(0, 0);
}
public void appendTranslate(int xt, int yt) {
curTranslate = curTranslate.add(new Point(xt, yt));
}
public void appendMirrorX() {
/*
* MirrorX in CIF means change sign of x-coordinate, this correspond
* to MY in EDIF notation.
*/
appendOrient(ManhattanOrientation.MY);
}
public void appendMirrorY() {
/*
* MirrorY in CIF means change sign of y-coordinate, this correspond
* to MX in EDIF notation.
*/
appendOrient(ManhattanOrientation.MX);
}
public void appendRotate(int xRot, int yRot) {
ManhattanOrientation orient;
if (yRot == 0) {
if (xRot == 0) {
throw new IllegalArgumentException("Zero rotate vector");
}
orient = xRot > 0 ? ManhattanOrientation.R0 : ManhattanOrientation.R180;
} else {
if (xRot != 0) {
throw new UnsupportedOperationException("Unly Manhattan rotations are supported");
}
orient = yRot > 0 ? ManhattanOrientation.R90 : ManhattanOrientation.R270;
}
appendOrient(orient);
}
private void appendOrient(ManhattanOrientation orient) {
curTranslate = curTranslate.transform(orient);
curOrient = orient.concatenate(curOrient);
}
public void initPath() {
}
public void appendPoint(Point p) {
}
public void makeCall(int symbol, int lineNumber/* , transform */) {
DefaultLayoutCell subCell = cells.get(Integer.valueOf(symbol));
if (subCell == null) {
throw new IllegalArgumentException("Subcell " + symbol + " not found");
}
if (subCell == curCell) {
throw new IllegalArgumentException("Recursive cell call");
}
if (subCell.getNumRectangles() == 0 && subCell.getNumSubcells() == 0) {
// skip empty subcells
return;
}
if (curTranslate.getX() % scaleFactor != 0 || curTranslate.getY() % scaleFactor != 0) {
throw new IllegalArgumentException("Scale factor error");
}
int anchorX = curTranslate.getX() / scaleFactor;
int anchorY = curTranslate.getY() / scaleFactor;
if (curCell != null) {
curCell.addSubCell(subCell, anchorX, anchorY, curOrient);
}
}
public void makeLayer(String lName) {
isSelectedLayer = lName.equals(layerSelector);
}
public void makeFlash(int diameter, Point center) {
}
public void makePolygon(/* path */) {
}
public void makeBox(int length, int width, Point center, int xr, int yr) {
int xl = center.getX() - length / 2;
int yl = center.getY() - width / 2;
int xh = center.getX() + length / 2;
int yh = center.getY() + width / 2;
if (xl % scaleFactor != 0 || yl % scaleFactor != 0 || xh % scaleFactor != 0 || yh % scaleFactor != 0) {
throw new IllegalArgumentException("Scale factor error");
}
xl /= scaleFactor;
yl /= scaleFactor;
xh /= scaleFactor;
yh /= scaleFactor;
if (yr != 0 || xr <= 0) {
throw new UnsupportedOperationException("Rotated boxes are not supported");
}
if (curCell != null && isSelectedLayer) {
curCell.addRectangle(xl, yl, xh, yh);
}
}
public void makeUserComment(int command, String text) {
}
public void makeSymbolName(String name) {
if (curCell != null) {
curCell.setName(name);
}
}
public void makeInstanceName(String name) {
}
public void makeGeomName(String name, Point pt, String lay) {
}
public void makeLabel(String name, Point pt) {
}
public void processEnd() {
}
public void doneInterpreter() {
}
}
public static class DebugCIFActions implements CIF.CIFActions {
private PrintStream out;
private CIF.CIFActions impl;
public void initInterpreter() {
out.println("initInterpretator();");
impl.initInterpreter();
}
public void makeWire(int width/* , path */) {
out.println("makeWire(" + width + ");");
impl.makeWire(width);
}
public void makeStartDefinition(int symbol, int mtl, int div) {
out.println("makeStartDefinition(" + symbol + "," + mtl + "," + div + ");");
impl.makeStartDefinition(symbol, mtl, div);
}
public void makeEndDefinition() {
out.println("makeEndDefinition();");
impl.makeEndDefinition();
}
public void makeDeleteDefinition(int n) {
out.print("makeDeleteDefinition(" + n + ");");
impl.makeDeleteDefinition(n);
}
public void initTransform() {
out.println("initTransform();");
impl.initTransform();
}
public void appendTranslate(int xt, int yt) {
out.println("appendTranslate(" + xt + "," + yt + ");");
impl.appendTranslate(xt, yt);
}
public void appendMirrorX() {
out.println("appendMirrorX();");
impl.appendMirrorX();
}
public void appendMirrorY() {
out.println("appendMirrorY();");
impl.appendMirrorY();
}
public void appendRotate(int xRot, int yRot) {
out.println("appendRotate(" + xRot + "," + yRot + ");");
impl.appendRotate(xRot, yRot);
}
public void initPath() {
out.println("initPath();");
impl.initPath();
}
public void appendPoint(Point p) {
out.println("appendPoint(" + p.getX() + "," + p.getY() + ");");
impl.appendPoint(p);
}
public void makeCall(int symbol, int lineNumber/* , transform */) {
out.println("makeCall(" + symbol + "," + lineNumber + ");");
impl.makeCall(symbol, lineNumber);
}
public void makeLayer(String lName) {
out.println("makeLayer(\"" + lName + "\");");
impl.makeLayer(lName);
}
public void makeFlash(int diameter, Point center) {
out.println("makeFlash(" + diameter + "," + center.getX() + "," + center.getY() + ");");
impl.makeFlash(diameter, center);
}
public void makePolygon(/* path */) {
out.println("makePolygon();");
impl.makePolygon();
}
public void makeBox(int length, int width, Point center, int xr, int yr) {
out.println("makeBox(" + length + "," + width + "," + center.getX() + "," + center.getY() + ","
+ xr + "," + yr + ");");
impl.makeBox(length, width, center, xr, yr);
}
public void makeUserComment(int command, String text) {
out.println("makeUserComment(" + command + ",\"" + text + "\");");
impl.makeUserComment(command, text);
}
public void makeSymbolName(String name) {
out.println("makeSymbolName(\"" + name + "\");");
impl.makeSymbolName(name);
}
public void makeInstanceName(String name) {
out.println("makeInstanceName(\"" + name + "\");");
impl.makeInstanceName(name);
}
public void makeGeomName(String name, Point pt, String lay) {
out.println("makeGeomName(\"" + name + "\"," + pt.getX() + "," + pt.getY() + ","
+ (lay != null ? "\"" + lay + "\"" : "null") + ");");
impl.makeGeomName(name, pt, lay);
}
public void makeLabel(String name, Point pt) {
out.println("makeLableName(\"" + name + "\"," + pt.getX() + "," + pt.getY() + ");");
impl.makeLabel(name, pt);
}
public void processEnd() {
out.println("processEnd();");
impl.processEnd();
}
public void doneInterpreter() {
out.println("doneInterpreter();");
impl.doneInterpreter();
}
}
public static class NullCIFActions implements CIF.CIFActions {
public void initInterpreter() {
}
public void makeWire(int width/* , path */) {
}
public void makeStartDefinition(int symbol, int mtl, int div) {
}
public void makeEndDefinition() {
}
public void makeDeleteDefinition(int n) {
}
public void initTransform() {
}
public void appendTranslate(int xt, int yt) {
}
public void appendMirrorX() {
}
public void appendMirrorY() {
}
public void appendRotate(int xRot, int yRot) {
}
public void initPath() {
}
public void appendPoint(Point p) {
}
public void makeCall(int symbol, int lineNumber/* , transform */) {
}
public void makeLayer(String lName) {
}
public void makeFlash(int diameter, Point center) {
}
public void makePolygon(/* path */) {
}
public void makeBox(int length, int width, Point center, int xr, int yr) {
}
public void makeUserComment(int command, String text) {
}
public void makeSymbolName(String name) {
}
public void makeInstanceName(String name) {
}
public void makeGeomName(String name, Point pt, String lay) {
}
public void makeLabel(String name, Point pt) {
}
public void processEnd() {
}
public void doneInterpreter() {
}
}
}