1
/* -*- tab-width: 4 -*-
3
* Electric(tm) VLSI Design System
6
* Written by: Adam Megacz
8
* Copyright (c) 2014 Static Free Software
10
* Electric(tm) is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 3 of the License, or
13
* (at your option) any later version.
15
* Electric(tm) is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with Electric(tm); see the file COPYING. If not, write to
22
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
* Boston, Mass 02111-1307, USA.
25
package com.sun.electric.tool.io.input;
27
import com.sun.electric.database.EditingPreferences;
28
import com.sun.electric.database.geometry.EPoint;
29
import com.sun.electric.database.hierarchy.Cell;
30
import com.sun.electric.database.hierarchy.Library;
31
import com.sun.electric.database.prototype.NodeProto;
32
import com.sun.electric.database.topology.NodeInst;
33
import com.sun.electric.util.TextUtils;
34
import com.sun.electric.util.math.FixpCoord;
35
import com.sun.electric.util.math.Orientation;
37
import java.util.HashMap;
41
* This class builds large instance arrays by creating a
42
* logarithmic-depth tree of bisections; this makes it possible to
43
* import complex foundry-provided cells (such as IO pads) without
44
* creating cripplingly-huge cells.
46
* For example, a 256x256 GDS array reference will result in four
47
* instances of a 128x12 cell; the 128x128 cell will contain four
48
* instances of a 64x64 cell, and so on.
50
* If the requested dimensions are not square then only the larger
51
* dimension is bisected; for example a 256x8 array contains a pair of
52
* 128x8 instances (not four 128x4 instances) -- this ensures that the
53
* minimum possible amount of non-square cells are created and
54
* maximizes the reuse of cells.
56
* If one or both of the requested dimensions are not a power of two
57
* then that dimension is partitioned into two unequal parts: one
58
* which is the largest possible power of two and the other which
59
* contains the remainder (for example, 9x1 becomes 8x1+1x1). This
60
* too ensures that the minimum amount of non-power-of-two-dimension
61
* cells are created, which also maximizes reuse of cells.
63
* Arrays smaller than 4x4 are realized directly.
66
public class CellArrayBuilder {
68
public final Library theLibrary;
70
public CellArrayBuilder(Library theLibrary) { this.theLibrary = theLibrary; }
72
private static HashMap<Map.Entry<NodeProto, String>, CellArray> cellArrayCache =
73
new HashMap<Map.Entry<NodeProto, String>, CellArray>();
75
public class CellArray {
77
public final NodeProto proto;
78
public final int cols;
79
public final int rows;
80
public final FixpCoord colspace;
81
public final FixpCoord rowspace;
82
private Cell cell = null;
84
public CellArray(NodeProto proto, int cols, int rows, FixpCoord colspace, FixpCoord rowspace) {
88
this.colspace = colspace;
89
this.rowspace = rowspace;
92
public Cell makeCell(EditingPreferences ep) {
93
if (cell != null) return cell;
94
String name = proto.getName();
95
if (name.indexOf('{') != -1) name = name.substring(0, name.indexOf('{'));
96
name += "_" + makeArrayName(cols, rows, colspace, rowspace) + "{lay}";
97
this.cell = Cell.newInstance(theLibrary, name);
98
if (cell == null) throw new RuntimeException("Cell.newInstance("+name+") returned null");
99
EPoint bottomLeftInstance = EPoint.ORIGIN;
100
if (rows < 4 && cols < 4) {
101
// leaf cell of the bisection hierarchy
102
buildFlatArray(proto, cell, bottomLeftInstance, Orientation.fromAngle(0), cols, rows, colspace, rowspace, ep);
104
// non-leaf cell of the bisection hierarchy
105
buildArrayBisected(proto, cell, bottomLeftInstance, Orientation.fromAngle(0), cols, rows, colspace, rowspace, ep);
111
private String makeArrayName(int cols, int rows, FixpCoord colspace, FixpCoord rowspace) {
112
return cols + "x" + rows + "sep" + TextUtils.formatDouble(colspace.getLambda()) + "x" + TextUtils.formatDouble(rowspace.getLambda());
115
private CellArray getCellArray(NodeProto proto, int cols, int rows, FixpCoord colspace, FixpCoord rowspace) {
116
Map.Entry<NodeProto, String> key =
117
new java.util.AbstractMap.SimpleEntry(proto, makeArrayName(cols, rows, colspace, rowspace));
118
CellArray ret = cellArrayCache.get(key);
120
ret = new CellArray(proto, cols, rows, colspace, rowspace);
121
cellArrayCache.put(key, ret);
126
private boolean isPowerOfTwo(int x) {
128
for(int i=0; i<32; i++)
134
public void buildArrayUsingSubcells(NodeProto proto, Cell parent, EPoint bottomLeftInstanceLocation, Orientation orient,
135
int cols, int rows, FixpCoord colspace, FixpCoord rowspace, EditingPreferences ep) {
137
// if there are an even number of rows and columns this is a straightforward instantiation
138
if (isPowerOfTwo(cols) && isPowerOfTwo(rows)) {
141
EPoint loc = bottomLeftInstanceLocation;
143
Orientation corient = orient.canonic();
145
switch(corient.getAngle()) {
148
arrCell = getCellArray(proto, rows, cols, rowspace, colspace).makeCell(ep);
152
arrCell = getCellArray(proto, cols, rows, colspace, rowspace).makeCell(ep);
154
default: throw new Error("got rotation of " + corient.getAngle());
157
switch(corient.getAngle()) {
159
loc = corient.isYMirrored() ? loc : EPoint.fromFixp(loc.getCoordX().getFixp(), rowspace.multiply(rows-1).add(loc.getCoordY()).getFixp());
162
loc = EPoint.fromFixp(loc.getCoordX().add(colspace.multiply(cols-1)).getFixp(), loc.getCoordY().getFixp());
163
loc = corient.isYMirrored() ? loc : EPoint.fromFixp(loc.getCoordX().getFixp(), rowspace.multiply(rows-1).add(loc.getCoordY()).getFixp());
166
loc = EPoint.fromFixp(loc.getCoordX().add(colspace.multiply(cols-1)).getFixp(), loc.getCoordY().getFixp());
167
loc = !corient.isYMirrored() ? loc : EPoint.fromFixp(loc.getCoordX().getFixp(), rowspace.multiply(rows-1).add(loc.getCoordY()).getFixp());
170
loc = !corient.isYMirrored() ? loc : EPoint.fromFixp(loc.getCoordX().getFixp(), rowspace.multiply(rows-1).add(loc.getCoordY()).getFixp());
172
default: throw new Error("got rotation of " + corient.getAngle());
174
NodeInst.makeInstance(arrCell, ep, loc, arrCell.getDefWidth(null), arrCell.getDefHeight(null), parent, orient, null);
177
// otherwise be more intelligent
178
buildArrayBisected(proto, parent, bottomLeftInstanceLocation, orient, cols, rows, colspace, rowspace, ep);
182
/** makes an array with subcells */
183
public void buildArrayBisected(NodeProto proto, Cell parent, EPoint bottomLeftInstanceLocation, Orientation orient,
184
int cols, int rows, FixpCoord colspace, FixpCoord rowspace, EditingPreferences ep) {
186
for(int x=0; x<cols; ) {
189
while ((width<<1)+x <= cols && (width<<1)<=(cols>=rows?cols/2:cols)) width = width<<1;
191
for(int y=0; y<rows; ) {
194
while ((height<<1)+y <= rows && (height<<1)<=(rows>=cols?rows/2:rows)) height = height<<1;
196
buildArrayUsingSubcells(proto, parent,
197
EPoint.fromFixp(bottomLeftInstanceLocation.getCoordX().add(colspace.multiply(x)).getFixp(),
198
bottomLeftInstanceLocation.getCoordY().add(rowspace.multiply(y)).getFixp()),
201
colspace, rowspace, ep);
209
/** makes an array the "dumb way" */
210
public void buildFlatArray(NodeProto proto, Cell parent, EPoint bottomLeftInstanceLocation, Orientation orient,
211
int cols, int rows, FixpCoord colspace, FixpCoord rowspace, EditingPreferences ep) {
212
FixpCoord ptcX = bottomLeftInstanceLocation.getCoordX();
213
FixpCoord ptcY = bottomLeftInstanceLocation.getCoordY();
214
for (int ic = 0; ic < cols; ic++) {
215
FixpCoord ptX = ptcX;
216
FixpCoord ptY = ptcY;
217
for (int ir = 0; ir < rows; ir++) {
218
EPoint loc = EPoint.fromFixp(ptX.getFixp(), ptY.getFixp());
219
NodeInst ni = NodeInst.makeInstance(proto,ep,loc,proto.getDefWidth(null), proto.getDefHeight(null), parent, orient, null);
220
ptY = ptY.add(rowspace);
222
ptcX = ptcX.add(colspace);
226
/** makes an array as intelligently as possible */
227
public void buildArray(NodeProto proto, Cell parent,
228
EPoint startLoc, Orientation orient,
230
FixpCoord colspace, FixpCoord rowspace, EditingPreferences ep) {
231
if (cols<1) throw new Error();
232
if (rows<1) throw new Error();
233
if (colspace.signum()<0) {
234
colspace = colspace.multiply(-1.0);
235
startLoc = EPoint.fromFixp(startLoc.getCoordX().add(colspace.multiply(-1*(cols-1))).getFixp(), startLoc.getCoordY().getFixp());
237
if (rowspace.signum()<0) {
238
rowspace = rowspace.multiply(-1.0);
239
startLoc = EPoint.fromFixp(startLoc.getCoordX().getFixp(), startLoc.getCoordY().add(rowspace.multiply(-1*(rows-1))).getFixp());
244
System.err.println("buildArray " + proto +
245
" " + cols + "x" + rows +
246
" @ " + colspace.getLambda() + ":" + rowspace.getLambda() +
247
" + " + startLoc.getCoordX().getLambda() + "," + startLoc.getCoordY().getLambda());
250
if (rows < 4 && cols < 4) {
251
// small array; build explicitly
252
buildFlatArray(proto, parent, startLoc, orient, cols, rows, colspace, rowspace, ep);
254
buildArrayUsingSubcells(proto, parent, startLoc, orient, cols, rows, colspace, rowspace, ep);