/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Strategy.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. */ // Updated 31 October to attach to a SymmetryGroup //updated 25 January 2004 (and preceeding week) to remove iteration. //the iteration is now all in the tree structure package com.sun.electric.tool.ncc.strategy; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import com.sun.electric.tool.ncc.NccGlobals; import com.sun.electric.tool.ncc.lists.LeafList; import com.sun.electric.tool.ncc.lists.RecordList; import com.sun.electric.tool.ncc.netlist.NetObject; import com.sun.electric.tool.ncc.trees.Circuit; import com.sun.electric.tool.ncc.trees.EquivRecord; import com.sun.electric.tool.Job; /** * Strategy is the superclass for all strategies. * The Strategy classes implement a doFor method for each * level of the EquivRecord tree: * Integer doFor(NetObject) * Each of these does a call-back to the apply(Strategy) method of its class * which actually computes the appropriate answer, perhaps by doFor calls, * for each of its children, accumulating the answers. * Strategy keeps track of the depth in the tree, * giving reports when depth == 0. * Because of that, calls to Strategy.doFor(Record) * produce a single combined report, but * calls to Record.apply(Strategy) produce multiple reports. */ public abstract class Strategy { // ---------------------------- constants --------------------------------- public static final Integer CODE_ERROR = null; public static final Integer CODE_NO_CHANGE = new Integer(0); // --------------- local variables ------------------- protected int depth; //depth in the tree protected int getDepth(){return depth;} public NccGlobals globals; private Date theStartDate= null; /** Die if error occurs * @param pred true if error occurs * @param msg message to print if error occurs */ public void error(boolean pred, String msg) { if (globals==null) { Job.error(pred, msg); } else { globals.error(pred, msg); } } /** Simple stratgies may pass in null for globals. But they can't * call startTime, elapsedTime, or pickAnOffspring */ protected Strategy(NccGlobals globals) {this.globals=globals;} private LeafList apply(Iterator<EquivRecord> it){ LeafList out= new LeafList(); while (it.hasNext()) { EquivRecord jr= it.next(); out.addAll(doFor(jr)); } return out; } private LeafList apply(RecordList r) { return apply(r.iterator()); } /** Apply this Strategy to a list of leaf and internal records. * @param r a RecordList of EquivRecords to process * @return a LeafList of the new leaf EquivRecords */ public LeafList doFor(RecordList r) {return doFor(r.iterator());} public LeafList doFor(Iterator<EquivRecord> it) { depth++; LeafList out = apply(it); depth--; return out; } /** Method doFor(EquivRecord) processes a single EquivRecord. * @param rr the EquivRecord to process * @return a LeafList of the new leaf EquivRecords */ public LeafList doFor(EquivRecord rr){ depth++; LeafList out = rr.apply(this); depth--; return out; } /** Method doFor(Circuit) process a single Circuit, * dividing the circuit according to this strategy, and * placing the NetObjects of the Circuit into new Circuits * mapped in the return according to the separation Integer. * @param c the Circuit to process. * @return a CircuitMap of offspring Circuits. * Returns an empty map if no offspring intended, and * returns the input input Circuit if method fails to split. */ public HashMap<Integer,List<NetObject>> doFor(Circuit c){ depth++; HashMap<Integer,List<NetObject>> codeToNetObjs = c.apply(this); depth--; return codeToNetObjs; } /** doFor(NetObject) tests the NetObject to decide its catagory. * The default method generates no offspring. * @param n the NetObject to catagorize * @return an Integer for the choice. */ public Integer doFor(NetObject n) {return CODE_NO_CHANGE;} //comments on the "code"th offspring of g EquivRecord pickAnOffspring(Integer code, LeafList g, String label) { int value = code.intValue(); for(Iterator<EquivRecord> it=g.iterator(); it.hasNext();){ EquivRecord er = it.next(); if(er.getValue()==value){ globals.status2(label+": "+ er.nameString()); return er; } } //falls out if not found globals.status2(label+": none"); return null; } protected String offspringStats(LeafList el) { int matched=0, mismatched=0, active=0; for (Iterator<EquivRecord> it=el.iterator(); it.hasNext();) { EquivRecord er = it.next(); if (er.isMismatched()) mismatched++; else if (er.isMatched()) matched++; else active++; } String msg = " offspring counts: #matched="+matched+ " #mismatched="+mismatched+" #active="+active; // if (mismatched!=0) { // globals.status1(msg); // //StrategyPrint.doYourJob(globals.getRoot(), globals); // StratDebug.doYourJob(globals); // globals.error("mismatched!"); // return null; // } return msg; } protected void startTime(String strat, String target){ theStartDate= new Date(); globals.status2((globals.passNumber++)+" "+ strat + " doing " + target); } protected long elapsedTime(){ Date d= new Date(); long time= d.getTime() - theStartDate.getTime(); globals.status2(" took " + time + " miliseconds\n"); return time; } }