/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: NccUtils.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.ncc.basic; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.hierarchy.View; import com.sun.electric.database.variable.EditWindow_; import com.sun.electric.database.variable.UserInterface; import com.sun.electric.database.variable.VarContext; import com.sun.electric.tool.Job; import com.sun.electric.tool.ncc.Aborter; import com.sun.electric.tool.ncc.NccEngine; import com.sun.electric.tool.ncc.NccGlobals; import com.sun.electric.tool.ncc.NccOptions; import com.sun.electric.tool.ncc.processing.HierarchyInfo; import com.sun.electric.tool.ncc.result.NccResult; import com.sun.electric.tool.ncc.result.BenchmarkResults.BenchIdx; import com.sun.electric.tool.user.ui.WindowContent; import com.sun.electric.tool.user.ui.WindowFrame; /** Subroutines useful for NCC. */ public class NccUtils { private static long pow(int x, int y) { long prod = 1; for (int i=0; i<y; i++) prod*=x; return prod; } public static String fullName(Cell c) {return c.libDescribe();} private static Cell findLayout(Cell.CellGroup group) { for (Iterator<Cell> it=group.getCells(); it.hasNext();) { Cell c = (Cell) it.next(); if (c.getView()==View.LAYOUT) return c.getNewestVersion(); } return null; } /** If cell is layout then pair it with the main schematic cell of cell's * CellGroup. If cell is schematic then pair it with some layout cell from * cell's CellGroup. If cell is neither schematic nor layout then return * the main schematic and some layout cell. Always put the schematic at * index 0 */ public static Cell[] findSchematicAndLayout(Cell cell) { Cell.CellGroup group = cell.getCellGroup(); Cell layout=null, schematic=null; if (cell.isSchematic()) { // have schematic, find layout schematic = cell; layout = findLayout(group); } else if (cell.getView()==View.LAYOUT) { // have layout, find schematic layout = cell; schematic = group.getMainSchematics(); } else { schematic = group.getMainSchematics(); layout = findLayout(group); } if (schematic!=null && layout!=null) return new Cell[] {schematic, layout}; else return null; } public static CellContext getCurrentCellContext() { UserInterface ui = Job.getUserInterface(); EditWindow_ wnd = ui.getCurrentEditWindow_(); return getCellContext(wnd); } public static CellContext getCellContext(EditWindow_ wnd) { if (wnd==null) return null; Cell cell = wnd.getCell(); if (cell==null) { System.out.println("window has no Cell"); return null; } VarContext context = wnd.getVarContext(); return new CellContext(cell, context); } public static List<CellContext> getCellContextsFromWindows() { List<CellContext> cellCtxts = new ArrayList<CellContext>(); // first is always current window UserInterface ui = Job.getUserInterface(); EditWindow_ wnd = ui.getCurrentEditWindow_(); CellContext curCellCtxt = getCellContext(wnd); if (curCellCtxt==null) return cellCtxts; cellCtxts.add(curCellCtxt); for(Iterator<WindowFrame> it=WindowFrame.getWindows(); it.hasNext();) { WindowFrame wf = (WindowFrame)it.next(); WindowContent content = wf.getContent(); if (!(content instanceof EditWindow_)) continue; EditWindow_ wnd2 = (EditWindow_) content; if (wnd2==wnd) continue; CellContext cc = getCellContext((EditWindow_)content); cellCtxts.add(cc); } return cellCtxts; } /** print hours minutes seconds */ public static String hourMinSec(Date start, Date stop) { long elapsedMsec = stop.getTime() - start.getTime(); return hourMinSec(elapsedMsec); } public static String hourMinSec(long elapsedMsec){ final int msecPerHour = 1000*60*60; final int msecPerMin = 1000*60; long hours = elapsedMsec / msecPerHour; elapsedMsec = elapsedMsec % msecPerHour; long mins = elapsedMsec / msecPerMin; elapsedMsec = elapsedMsec % msecPerMin; double secs = elapsedMsec / 1000.0; String time = ""; if (hours!=0) time += hours + " hours "; if (mins!=0) time += mins + " minutes "; time += secs + " seconds"; return time; } public static NccResult buildBlackBoxes(CellContext c1, CellContext c2, HierarchyInfo hierInfo, NccOptions options, Aborter aborter) { System.out.println("Build black boxes for: "+NccUtils.fullName(c1.cell)+ " and: "+NccUtils.fullName(c2.cell)); System.out.flush(); NccResult r = NccEngine.buildBlackBoxes(c1.cell, c1.context, c2.cell, c2.context, hierInfo, options, aborter); System.out.println(r.match() ? "Done" : "Failed"); System.out.flush(); return r; } /** Say whether sizes w1 and w2 are close enough together for NCC * to consider them "equal". * @param w1 first width or length * @param w2 second width or length * @param opt NCC options that specify size matching tolerances * @return true if NCC should consider them equal */ public static boolean sizesMatch(double w1, double w2, NccOptions opt) { double maxWidth = Math.max(w1, w2); double minWidth = Math.min(w1, w2); double absWidErr = maxWidth - minWidth; double relWidErr = absWidErr / minWidth; boolean absV = round(absWidErr,2)<=opt.absoluteSizeTolerance; // rounding to 2 decimals in abs case should be fine boolean relV = relWidErr<=opt.relativeSizeTolerance; return relV || absV; // return absWidErr<=opt.absoluteSizeTolerance || // relWidErr<=opt.relativeSizeTolerance; } /** Wait forever. This allows me to explore memory usage */ public static void hang(String msg) { final long YEAR = 1000*60*60*24*365; try { System.out.println(msg+" now going to sleep for 1 year"); System.out.flush(); Thread.sleep(1*YEAR); } catch (Exception e) { System.out.println("Huh? I woke up."); } } public static double round(double x, int places) { long m = pow(10, places); return Math.rint(x*m)/m; } public static long registerTiming(String msg, long start, BenchIdx benchmark,NccGlobals globals){ long end = NccUtils.getTime(); long time = end-start; if(msg != null) globals.status1(msg+NccUtils.hourMinSec(time)); globals.getBenchmarkResults().results[benchmark.ordinal()] += time; return end; } public static long accumulateBenchmarkValue(String msg, long val, BenchIdx benchmark,NccGlobals globals){ if(msg != null) globals.status1(msg+val); return globals.getBenchmarkResults().results[benchmark.ordinal()] += val; } public static void incrementBenchmarkCount(BenchIdx benchmark,NccGlobals globals){ globals.getBenchmarkResults().results[benchmark.ordinal()]++; } public static long getTime(){ return System.currentTimeMillis(); } }