All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.electric.tool.ncc.NccEngine Maven / Gradle / Ivy

There is a newer version: 9.02-e
Show newest version
/* -*- tab-width: 4 -*-
 *
 * Electric(tm) VLSI Design System
 *
 * File: NccEngine.java
 *
 * Copyright (c) 2003, 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.
*/

/**
 * NccEngine performs an n-way netlist comparison.  NccEngine 
 * must be passed all Ncc options as procedural arguments; it does not access 
 * the User NCC options directly.  This allows programs to call the 
 * engine without becoming involved with how User's options are stored.
 */
package com.sun.electric.tool.ncc;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.variable.VarContext;
import com.sun.electric.tool.ncc.basic.NccUtils;
import com.sun.electric.tool.ncc.netlist.NccNetlist;
import com.sun.electric.tool.ncc.netlist.Part;
import com.sun.electric.tool.ncc.netlist.Wire;
import com.sun.electric.tool.ncc.processing.ExportChecker;
import com.sun.electric.tool.ncc.processing.ForceMatch;
import com.sun.electric.tool.ncc.processing.HashCodePartitioning;
import com.sun.electric.tool.ncc.processing.HierarchyInfo;
import com.sun.electric.tool.ncc.processing.LocalPartitionResult;
import com.sun.electric.tool.ncc.processing.LocalPartitioning;
import com.sun.electric.tool.ncc.processing.ReportHashCodeFailure;
import com.sun.electric.tool.ncc.processing.SerialParallelMerge;
import com.sun.electric.tool.ncc.result.NccResult;
import com.sun.electric.tool.ncc.result.BenchmarkResults.BenchIdx;
import com.sun.electric.tool.ncc.strategy.StratCheckSizes;
import com.sun.electric.tool.ncc.trees.Circuit;
import com.sun.electric.tool.ncc.trees.EquivRecord;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/** NccEngine performs the topological comparison of two Cells.
 * These Cells are from the same
 * CompareList and are supposed to be topologically
 * identical.
 * 
 * Note that NCC calls NccEngine.compare() many times. For example,
 * if every CompareList contained exactly two Cells, then NCC
 * would call NccEngine.compare() once for each CompareList.
 * 
 *  NCC calls NccEngine.compare() on the leaf Cells first, and proceeds 
 *  upwards towards the
 *  root. The object, HierarchyInfo, stores information that NCC
 *  must pass from lower level comparisons to higher level comparisons. 
 */
public class NccEngine {
	// ------------------------------ private data ----------------------------
	private NccGlobals globals;

	// ----------------------- private methods --------------------------------
	// return null if user aborts
	private List buildNccNetlists(List cells, 
			                                  List contexts, 
			                                  boolean blackBox, 
			                                  HierarchyInfo hierInfo) {
		globals.error(cells.size()!=contexts.size(),
					  "number of cells, and contexts must be the same");										
		List nccLists = new ArrayList();
		Iterator itCell;
		Iterator itCon;
		for (itCell=cells.iterator(),
			 itCon=contexts.iterator(); itCell.hasNext();) {
			Cell cell = itCell.next();
			VarContext context = itCon.next();
			NccNetlist nccList = new NccNetlist(cell, context,
			                                    hierInfo, blackBox, globals);
			if (nccList.userAbort()) return null;
			nccLists.add(nccList);
		}
		return nccLists;
	}
	
	private int[] getNetObjCounts(EquivRecord rec, int numCells) {
		int[] counts = new int[numCells];
		// don't blow up if no parts or wires
		if (rec==null) return counts;
		int i=0;
		for (Iterator it=rec.getCircuits(); it.hasNext(); i++) {
			Circuit ckt = it.next();
			counts[i] = ckt.numNetObjs();
		}
		return counts;
	}
	
	/** Ivan wants this print out. */
	private void printWireComponentCounts() {
		int numCells = globals.getNumNetlistsBeingCompared();
		int[] partCounts = getNetObjCounts(globals.getParts(), numCells);
		int[] wireCounts = getNetObjCounts(globals.getWires(), numCells);
		int[] portCounts = getNetObjCounts(globals.getWires(), numCells);
		String[] cellNames = globals.getRootCellNames();
		VarContext[] contexts = globals.getRootContexts();
		for (int i=0; i forcedParts = new HashSet();
			Set forcedWires = new HashSet();
			ForceMatch.doYourJob(forcedParts, forcedWires, globals);

			LocalPartitionResult localRes =
				LocalPartitioning.doYourJob(forcedParts, forcedWires, globals);

			if (globals.userWantsToAbort()) return NccResult.newUserAbortResult();

			// Tricky: init leaf lists after Local Partitioning because Local
			// Partitioning can make an EquivRecord change from matched to
			// mismatched!
			globals.initLeafLists();

			
			start = NccUtils.registerTiming("  Local partitioning took ",start,BenchIdx.LOCAL_PARTITIONING_TIME,globals);
//			Date d3 = new Date();
//			globals.status1("  Local partitioning took "+ 
//					        NccUtils.hourMinSec(d2, d3));


			boolean topoOK = HashCodePartitioning.doYourJob(globals);
			if (!localRes.matches()) {
				globals.getNccGuiInfo().setPartRecReports(localRes.getPartRecReports());
				globals.getNccGuiInfo().setWireRecReports(localRes.getWireRecReports());
				localRes.printErrorReport();
				return NccResult.newResult(expNamesOK, false, false, globals);
			}
				
			if (globals.userWantsToAbort()) return NccResult.newUserAbortResult();
			
			//Date d4 = new Date();
			start = NccUtils.getTime();
			boolean expTopoOK = true;
			if (topoOK) {
				expCheck.suggestPortMatchesBasedOnTopology();
				expTopoOK = expCheck.ensureExportsWithMatchingNamesAreOnEquivalentNets();
			}

			start = NccUtils.registerTiming("  Export checking took ",start,BenchIdx.EXPORT_CHECKING_TIME,globals);

 //           Date d5 = new Date();
//			globals.status1("  Export checking took "+NccUtils.hourMinSec(d4, d5));
            
			boolean sizesOK = StratCheckSizes.doYourJob(globals);

			start = NccUtils.registerTiming("  Size checking took ",start,BenchIdx.SIZE_CHECKING_TIME,globals);

//			Date d6 = new Date();
//			globals.status1("  Size checking took "+NccUtils.hourMinSec(d5, d6));
			
			if (!topoOK) {
				ReportHashCodeFailure hcf = new ReportHashCodeFailure(globals);
				globals.getNccGuiInfo().setPartRecReports(hcf.getPartRecReports());
				globals.getNccGuiInfo().setWireRecReports(hcf.getWireRecReports());
			}

			boolean exportsOK = expNamesOK && expTopoOK;
			boolean topologyOK = localRes.matches() && topoOK;
            
			return NccResult.newResult(exportsOK, topologyOK, sizesOK, globals);
		}
	}

	private NccResult areEquivalent(List cells, List contexts, 
					  		        HierarchyInfo hierInfo,
					  		        boolean blackBox, 
					  		        NccOptions options, Aborter aborter) {
		globals = new NccGlobals(options, aborter);
		
		globals.status2("****************************************"+					  		
		                "****************************************");					  		

		// black boxing is implemented by building netlists that are empty 
		// except for their Exports.
		Date before = new Date();
		List nccNetlists = 
			buildNccNetlists(cells, contexts, blackBox, hierInfo);
		Date after = new Date();
		globals.status1("  NCC net list construction took "+NccUtils.hourMinSec(before, after)+".");

		// null list returned means user requested abort
		if (nccNetlists==null) return NccResult.newUserAbortResult();
        globals.setInitialNetlists(nccNetlists);
        
		NccResult result = designsMatch(hierInfo, false);
		
		if(result.match())
			NccUtils.incrementBenchmarkCount(BenchIdx.PASS_RESULT, globals);
		else{
			NccUtils.incrementBenchmarkCount(BenchIdx.FAIL_RESULT, globals);
		}
		
		globals.status2("****************************************"+					  		
		                "****************************************");
		return result;		              					  				
	}
	
	private static NccResult compare2(Cell cell1, VarContext context1, 
									  Cell cell2, VarContext context2, 
									  HierarchyInfo hierInfo,
									  boolean blackBox,
									  NccOptions options,
									  Aborter aborter) {
		ArrayList cells = new ArrayList();
		cells.add(cell1);
		cells.add(cell2);
		ArrayList contexts = new ArrayList();
		contexts.add(context1);
		contexts.add(context2);
				
		return compareMany(cells, contexts, hierInfo, blackBox, 
		                   options, aborter);
	}
	private static NccResult compareMany(List cells, List contexts,
									     HierarchyInfo hierCompInfo,
									     boolean blackBox, 
									     NccOptions options, Aborter aborter) {
		NccEngine ncc = new NccEngine();
		return ncc.areEquivalent(cells, contexts, hierCompInfo, 
								 blackBox, options, aborter);
	}
	// -------------------------- public methods ------------------------------
	/** 
	 * Check to see if all cells are topologically equivalent.  Note that
	 * the NCC engine can compare any number of Cells at the same time.
	 * @param cells a list of cells to compare.
	 * @param contexts a list of VarContexts for the corresponding Cell. The
	 * VarContxt is used to evaluate schematic 
	 * variables. Use null if variables don't need to be evaluated. 
	 * @param hierCompInfo Information needed to perform hierarchical
	 * netlist comparison. For flat comparisons pass null.
	 * @param options NCC options
	 */
	public static NccResult compare(List cells, List contexts,
	                                HierarchyInfo hierCompInfo, 
	                                NccOptions options, Aborter aborter) {
		return compareMany(cells, contexts, hierCompInfo, false, 
		                   options, aborter);
	}
	/** 
	 * Check to see if two cells are topologically equivalent.  
	 * @param cell1 the root cell for the first design
	 * @param context1 the VarContext for the first Cell
	 * @param cell2 the root cell for the second design
	 * @param context2 the VarContext for the second Cell
	 * @param hierInfo Information needed to perform hierarchical
	 * netlist comparison. For flat comparisons pass null.
	 * @param options NCC options
	 */
	public static NccResult compare(Cell cell1, VarContext context1, 
	                                Cell cell2, VarContext context2, 
	                                HierarchyInfo hierInfo, 
	                                NccOptions options, Aborter aborter) {
		return compare2(cell1, context1, cell2, context2, hierInfo, false, 
				        options, aborter);
	}
	/** 
	 * Instead of checking to see if two cells are topologically 
	 * equivalent, simply pretend that we've already compared them
	 * and found them to match. Put information into hierInfo that indicates
	 * that these two Cells match. 
	 * @param cell1 the root cell for the first design
	 * @param ctxt1 the VarContext for the first Cell
	 * @param cell2 the root cell for the second design
	 * @param ctxt2 the VarContext for the second Cell
	 * @param hierInfo Information needed to perform hierarchical
	 * netlist comparison. For flat comparisons pass null.
	 * @param options NCC options
	 */
	public static NccResult buildBlackBoxes(Cell cell1, VarContext ctxt1, 
								          Cell cell2, VarContext ctxt2,
								          HierarchyInfo hierInfo, 
								          NccOptions options, Aborter aborter) {
		return compare2(cell1, ctxt1, cell2, ctxt2, hierInfo, true, 
				               options, aborter);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy